Repository: rust-lang/rust-analyzer
Pull request #17960 (2024-08-25 10:09:52)

fix: add extra_test_bin_args to test explorer test runner
@HKalbasi I thought I included this in #17470 but it appears not so I have created a new issue #17959 for this fix.


Patch:
diff --git a/crates/hir-def/src/lib.rs b/crates/hir-def/src/lib.rs
index eb235f9b9f..40ead05b90 100644
--- a/crates/hir-def/src/lib.rs
+++ b/crates/hir-def/src/lib.rs
@@ -241,7 +241,7 @@ pub type StaticLoc = AssocItemLoc<Static>;
 impl_intern!(StaticId, StaticLoc, intern_static, lookup_intern_static);
 impl_loc!(StaticLoc, id: Static, container: ItemContainerId);
 
-#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub struct TraitId(salsa::InternId);
 pub type TraitLoc = ItemLoc<Trait>;
 impl_intern!(TraitId, TraitLoc, intern_trait, lookup_intern_trait);
diff --git a/crates/hir-ty/src/method_resolution.rs b/crates/hir-ty/src/method_resolution.rs
index d08f9b7ff0..3ddfea13ab 100644
--- a/crates/hir-ty/src/method_resolution.rs
+++ b/crates/hir-ty/src/method_resolution.rs
@@ -35,7 +35,7 @@ use crate::{
 };
 
 /// This is used as a key for indexing impls.
-#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub enum TyFingerprint {
     // These are lang item impls:
     Str,
diff --git a/crates/ide-db/src/imports/import_assets.rs b/crates/ide-db/src/imports/import_assets.rs
index 82a182806a..07e1973347 100644
--- a/crates/ide-db/src/imports/import_assets.rs
+++ b/crates/ide-db/src/imports/import_assets.rs
@@ -531,61 +531,40 @@ fn trait_applicable_items(
     })
     .collect();
 
-    let autoderef_method_receiver = {
-        let mut deref_chain = trait_candidate.receiver_ty.autoderef(db).collect::<Vec<_>>();
-        // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
-        if let Some((ty, _len)) = deref_chain.last().and_then(|ty| ty.as_array(db)) {
-            let slice = Type::new_slice(ty);
-            deref_chain.push(slice);
+    trait_candidates.retain(|&candidate_trait_id| {
+        // we care about the following cases:
+        // 1. Trait's definition crate
+        // 2. Definition crates for all trait's generic arguments
+        //     a. This is recursive for fundamental types: `Into<Box<A>> for ()`` is OK, but
+        //        `Into<Vec<A>> for ()`` is *not*.
+        // 3. Receiver type definition crate
+        //    a. This is recursive for fundamental types
+        let defining_crate_for_trait = Trait::from(candidate_trait_id).krate(db);
+        let Some(receiver) = trait_candidate.receiver_ty.fingerprint_for_trait_impl() else {
+            return false;
+        };
+
+        // in order to handle implied bounds through an associated type, keep any
+        // method receiver that matches `TyFingerprint::Unnameable`. this receiver
+        // won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual
+        // implementations.
+        if matches!(receiver, TyFingerprint::Unnameable) {
+            return true;
         }
-        deref_chain
-            .into_iter()
-            .filter_map(|ty| Some((ty.krate(db).into(), ty.fingerprint_for_trait_impl()?)))
-            .sorted()
-            .unique()
-            .collect::<Vec<_>>()
-    };
 
-    // can be empty if the entire deref chain is has no valid trait impl fingerprints
-    if autoderef_method_receiver.is_empty() {
-        return Default::default();
-    }
+        let definitions_exist_in_trait_crate = db
+            .trait_impls_in_crate(defining_crate_for_trait.into())
+            .has_impls_for_trait_and_self_ty(candidate_trait_id, receiver);
 
-    // in order to handle implied bounds through an associated type, keep all traits if any
-    // type in the deref chain matches `TyFingerprint::Unnameable`. This fingerprint
-    // won't be in `TraitImpls` anyways, as `TraitImpls` only contains actual implementations.
-    if !autoderef_method_receiver
-        .iter()
-        .any(|(_, fingerprint)| matches!(fingerprint, TyFingerprint::Unnameable))
-    {
-        trait_candidates.retain(|&candidate_trait_id| {
-            // we care about the following cases:
-            // 1. Trait's definition crate
-            // 2. Definition crates for all trait's generic arguments
-            //     a. This is recursive for fundamental types: `Into<Box<A>> for ()`` is OK, but
-            //        `Into<Vec<A>> for ()`` is *not*.
-            // 3. Receiver type definition crate
-            //    a. This is recursive for fundamental types
-            let defining_crate_for_trait = Trait::from(candidate_trait_id).krate(db);
-
-            let trait_impls_in_crate = db.trait_impls_in_crate(defining_crate_for_trait.into());
-            let definitions_exist_in_trait_crate =
-                autoderef_method_receiver.iter().any(|&(_, fingerprint)| {
-                    trait_impls_in_crate
-                        .has_impls_for_trait_and_self_ty(candidate_trait_id, fingerprint)
-                });
-            // this is a closure for laziness: if `definitions_exist_in_trait_crate` is true,
-            // we can avoid a second db lookup.
-            let definitions_exist_in_receiver_crate = || {
-                autoderef_method_receiver.iter().any(|&(krate, fingerprint)| {
-                    db.trait_impls_in_crate(krate)
-                        .has_impls_for_trait_and_self_ty(candidate_trait_id, fingerprint)
-                })
-            };
+        // this is a closure for laziness: if `definitions_exist_in_trait_crate` is true,
+        // we can avoid a second db lookup.
+        let definitions_exist_in_receiver_crate = || {
+            db.trait_impls_in_crate(trait_candidate.receiver_ty.krate(db).into())
+                .has_impls_for_trait_and_self_ty(candidate_trait_id, receiver)
+        };
 
-            definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate()
-        });
-    }
+        definitions_exist_in_trait_crate || definitions_exist_in_receiver_crate()
+    });
 
     let mut located_imports = FxIndexSet::default();
     let mut trait_import_paths = FxHashMap::default();
diff --git a/crates/ide-diagnostics/src/handlers/unused_variables.rs b/crates/ide-diagnostics/src/handlers/unused_variables.rs
index 84007b16aa..c594754bd4 100644
--- a/crates/ide-diagnostics/src/handlers/unused_variables.rs
+++ b/crates/ide-diagnostics/src/handlers/unused_variables.rs
@@ -23,7 +23,7 @@ pub(crate) fn unused_variables(
         return None;
     }
     let diagnostic_range = ctx.sema.diagnostics_display_range(ast);
-    // The range for the Actual Name. We don't want to replace the entire declaration. Using the diagnostic range causes issues within in Array Destructuring.
+    // The range for the Actual Name. We don't want to replace the entire declarition. Using the diagnostic range causes issues within in Array Destructuring.
     let name_range = d
         .local
         .primary_source(ctx.sema.db)
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index f74e3d6db1..2889af844b 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -1884,6 +1884,7 @@ impl Config {
                 CargoFeaturesDef::Selected(it) => it,
             },
             extra_args: self.extra_args().clone(),
+            extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(),
             extra_env: self.extra_env().clone(),
             target_dir: self.target_dir_from_config(),
         }
@@ -1934,6 +1935,7 @@ impl Config {
                         CargoFeaturesDef::Selected(it) => it,
                     },
                     extra_args: self.check_extra_args(),
+                    extra_test_bin_args: self.runnables_extraTestBinaryArgs().clone(),
                     extra_env: self.check_extra_env(),
                     target_dir: self.target_dir_from_config(),
                 },
diff --git a/crates/rust-analyzer/src/flycheck.rs b/crates/rust-analyzer/src/flycheck.rs
index 9fb4328657..b035d779a7 100644
--- a/crates/rust-analyzer/src/flycheck.rs
+++ b/crates/rust-analyzer/src/flycheck.rs
@@ -30,6 +30,7 @@ pub(crate) struct CargoOptions {
     pub(crate) all_features: bool,
     pub(crate) features: Vec<String>,
     pub(crate) extra_args: Vec<String>,
+    pub(crate) extra_test_bin_args: Vec<String>,
     pub(crate) extra_env: FxHashMap<String, String>,
     pub(crate) target_dir: Option<Utf8PathBuf>,
 }


Test patch:
diff --git a/crates/ide-completion/src/tests/flyimport.rs b/crates/ide-completion/src/tests/flyimport.rs
index 8350fdcc4c..158dbaf1b1 100644
--- a/crates/ide-completion/src/tests/flyimport.rs
+++ b/crates/ide-completion/src/tests/flyimport.rs
@@ -1633,39 +1633,3 @@ fn main() {
         "#]],
     );
 }
-
-#[test]
-fn trait_impl_on_slice_method_on_deref_slice_type() {
-    check(
-        r#"
-//- minicore: deref, sized
-struct SliceDeref;
-impl core::ops::Deref for SliceDeref {
-    type Target = [()];
-
-    fn deref(&self) -> &Self::Target {
-        &[]
-    }
-}
-fn main() {
-    SliceDeref.choose$0();
-}
-mod module {
-    pub(super) trait SliceRandom {
-        type Item;
-
-        fn choose(&self);
-    }
-
-    impl<T> SliceRandom for [T] {
-        type Item = T;
-
-        fn choose(&self) {}
-    }
-}
-"#,
-        expect![[r#"
-            me choose (use module::SliceRandom) fn(&self)
-        "#]],
-    );
-}
diff --git a/crates/rust-analyzer/src/test_runner.rs b/crates/rust-analyzer/src/test_runner.rs
index 293cff4743..5e43a3c60d 100644
--- a/crates/rust-analyzer/src/test_runner.rs
+++ b/crates/rust-analyzer/src/test_runner.rs
@@ -102,6 +102,11 @@ impl CargoTestHandle {
         }
         cmd.args(["-Z", "unstable-options"]);
         cmd.arg("--format=json");
+
+        for extra_arg in options.extra_test_bin_args {
+            cmd.arg(extra_arg);
+        }
+
         Ok(Self { _handle: CommandHandle::spawn(cmd, sender)? })
     }
 }