From 1c16e4ee978f5581b33b1abf33b9eeac830641d2 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Thu, 6 Apr 2023 10:28:34 +0200 Subject: [PATCH] fix: Fix block local impl trait solving regressions --- crates/hir-ty/src/chalk_db.rs | 51 +++++++++++++++++++++++------ crates/hir-ty/src/tests/coercion.rs | 29 ++++++++++++++++ crates/hir-ty/src/tests/traits.rs | 29 ++++++++++++++++ crates/rust-analyzer/src/reload.rs | 2 +- 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 68375f9e1e..94123ed23e 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 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 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 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| { 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| { + 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 e63a674a3f..c165a7cb16 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 813beaa364..54b8d53d2e 100644 --- a/crates/hir-ty/src/tests/traits.rs +++ b/crates/hir-ty/src/tests/traits.rs @@ -3811,6 +3811,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( diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs index 899c31d206..45e311a48b 100644 --- a/crates/rust-analyzer/src/reload.rs +++ b/crates/rust-analyzer/src/reload.rs @@ -447,7 +447,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); }