about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-06 08:37:33 +0000
committerbors <bors@rust-lang.org>2023-04-06 08:37:33 +0000
commite9e57725aa9ff093af5825503bcd0f28aca341a1 (patch)
tree11f90c077f97d58ca976e4fd2cd80013b140f16d
parente3e324d8305cbc8993ede1a083a0c47a39f711e9 (diff)
parent1c16e4ee978f5581b33b1abf33b9eeac830641d2 (diff)
downloadrust-e9e57725aa9ff093af5825503bcd0f28aca341a1.tar.gz
rust-e9e57725aa9ff093af5825503bcd0f28aca341a1.zip
Auto merge of #14505 - Veykril:block-trait-impls, r=Veykril
fix: Fix block local impl trait solving regressions

Fixes https://github.com/rust-lang/rust-analyzer/issues/14443
-rw-r--r--crates/hir-ty/src/chalk_db.rs51
-rw-r--r--crates/hir-ty/src/tests/coercion.rs29
-rw-r--r--crates/hir-ty/src/tests/traits.rs29
-rw-r--r--crates/rust-analyzer/src/reload.rs2
4 files changed, 100 insertions, 11 deletions
diff --git a/crates/hir-ty/src/chalk_db.rs b/crates/hir-ty/src/chalk_db.rs
index 68375f9e1eb..94123ed23ea 100644
--- a/crates/hir-ty/src/chalk_db.rs
+++ b/crates/hir-ty/src/chalk_db.rs
@@ -18,9 +18,10 @@ use hir_expand::name::name;
 use crate::{
     db::HirDatabase,
     display::HirDisplay,
-    from_assoc_type_id, from_chalk_trait_id, make_binders, make_single_type_binders,
+    from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
+    make_single_type_binders,
     mapping::{from_chalk, ToChalk, TypeAliasAsValue},
-    method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
+    method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
     to_assoc_type_id, to_chalk_trait_id,
     traits::ChalkContext,
     utils::generics,
@@ -106,6 +107,19 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
             _ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
         };
 
+        let trait_module = trait_.module(self.db.upcast());
+        let type_module = match self_ty_fp {
+            Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db.upcast())),
+            Some(TyFingerprint::ForeignType(type_id)) => {
+                Some(from_foreign_def_id(type_id).module(self.db.upcast()))
+            }
+            Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db.upcast())),
+            _ => None,
+        };
+
+        let mut def_blocks =
+            [trait_module.containing_block(), type_module.and_then(|it| it.containing_block())];
+
         // Note: Since we're using impls_for_trait, only impls where the trait
         // can be resolved should ever reach Chalk. impl_datum relies on that
         // and will panic if the trait can't be resolved.
@@ -120,6 +134,14 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
                 .and_then(|map| map.parent())
                 .and_then(|module| module.containing_block())
         })
+        .inspect(|&block_id| {
+            // make sure we don't search the same block twice
+            def_blocks.iter_mut().for_each(|block| {
+                if *block == Some(block_id) {
+                    *block = None;
+                }
+            });
+        })
         .filter_map(|block_id| self.db.trait_impls_in_block(block_id));
 
         let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
@@ -127,18 +149,27 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
         match fps {
             [] => {
                 debug!("Unrestricted search for {:?} impls...", trait_);
-                impl_maps.into_iter().chain(block_impls).for_each(|impls| {
+                let mut f = |impls: Arc<TraitImpls>| {
                     result.extend(impls.for_trait(trait_).map(id_to_chalk));
-                });
+                };
+                impl_maps.into_iter().chain(block_impls).for_each(&mut f);
+                def_blocks
+                    .into_iter()
+                    .filter_map(|it| self.db.trait_impls_in_block(it?))
+                    .for_each(f);
             }
             fps => {
-                impl_maps.into_iter().chain(block_impls).for_each(|impls| {
-                    result.extend(
-                        fps.iter().flat_map(|fp| {
+                let mut f =
+                    |impls: Arc<TraitImpls>| {
+                        result.extend(fps.iter().flat_map(|fp| {
                             impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
-                        }),
-                    );
-                });
+                        }));
+                    };
+                impl_maps.into_iter().chain(block_impls).for_each(&mut f);
+                def_blocks
+                    .into_iter()
+                    .filter_map(|it| self.db.trait_impls_in_block(it?))
+                    .for_each(f);
             }
         }
 
diff --git a/crates/hir-ty/src/tests/coercion.rs b/crates/hir-ty/src/tests/coercion.rs
index e63a674a3fd..c165a7cb161 100644
--- a/crates/hir-ty/src/tests/coercion.rs
+++ b/crates/hir-ty/src/tests/coercion.rs
@@ -902,3 +902,32 @@ fn test() {
 }",
     );
 }
+
+#[test]
+fn regression_14443_dyn_coercion_block_impls() {
+    check_no_mismatches(
+        r#"
+//- minicore: coerce_unsized
+trait T {}
+
+fn dyn_t(d: &dyn T) {}
+
+fn main() {
+    struct A;
+    impl T for A {}
+
+    let a = A;
+
+    let b = {
+        struct B;
+        impl T for B {}
+
+        B
+    };
+
+    dyn_t(&a);
+    dyn_t(&b);
+}
+"#,
+    )
+}
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 17a0c12c3ef..161e8385ec7 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -3812,6 +3812,35 @@ fn f() {
 }
 
 #[test]
+fn regression_14443_trait_solve() {
+    check_no_mismatches(
+        r#"
+trait T {
+    fn f(&self) {}
+}
+
+
+fn main() {
+    struct A;
+    impl T for A {}
+
+    let a = A;
+
+    let b = {
+        struct B;
+        impl T for B {}
+
+        B
+    };
+
+    a.f();
+    b.f();
+}
+"#,
+    )
+}
+
+#[test]
 fn associated_type_sized_bounds() {
     check_infer(
         r#"
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 436a4e651d3..ddf130e08dd 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -456,7 +456,7 @@ impl GlobalState {
             let mut proc_macros = Vec::default();
             for ws in &**self.workspaces {
                 let (other, mut crate_proc_macros) =
-                    ws.to_crate_graph(&mut load, &self.config.cargo().extra_env);
+                    ws.to_crate_graph(&mut load, &self.config.extra_env());
                 crate_graph.extend(other, &mut crate_proc_macros);
                 proc_macros.push(crate_proc_macros);
             }