Skip to content

Commit e9e5772

Browse files
committed
Auto merge of rust-lang#14505 - Veykril:block-trait-impls, r=Veykril
fix: Fix block local impl trait solving regressions Fixes rust-lang/rust-analyzer#14443
2 parents e3e324d + 1c16e4e commit e9e5772

File tree

4 files changed

+100
-11
lines changed

4 files changed

+100
-11
lines changed

crates/hir-ty/src/chalk_db.rs

+41-10
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ use hir_expand::name::name;
1818
use crate::{
1919
db::HirDatabase,
2020
display::HirDisplay,
21-
from_assoc_type_id, from_chalk_trait_id, make_binders, make_single_type_binders,
21+
from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, make_binders,
22+
make_single_type_binders,
2223
mapping::{from_chalk, ToChalk, TypeAliasAsValue},
23-
method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
24+
method_resolution::{TraitImpls, TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
2425
to_assoc_type_id, to_chalk_trait_id,
2526
traits::ChalkContext,
2627
utils::generics,
@@ -106,6 +107,19 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
106107
_ => self_ty_fp.as_ref().map(std::slice::from_ref).unwrap_or(&[]),
107108
};
108109

110+
let trait_module = trait_.module(self.db.upcast());
111+
let type_module = match self_ty_fp {
112+
Some(TyFingerprint::Adt(adt_id)) => Some(adt_id.module(self.db.upcast())),
113+
Some(TyFingerprint::ForeignType(type_id)) => {
114+
Some(from_foreign_def_id(type_id).module(self.db.upcast()))
115+
}
116+
Some(TyFingerprint::Dyn(trait_id)) => Some(trait_id.module(self.db.upcast())),
117+
_ => None,
118+
};
119+
120+
let mut def_blocks =
121+
[trait_module.containing_block(), type_module.and_then(|it| it.containing_block())];
122+
109123
// Note: Since we're using impls_for_trait, only impls where the trait
110124
// can be resolved should ever reach Chalk. impl_datum relies on that
111125
// and will panic if the trait can't be resolved.
@@ -120,25 +134,42 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
120134
.and_then(|map| map.parent())
121135
.and_then(|module| module.containing_block())
122136
})
137+
.inspect(|&block_id| {
138+
// make sure we don't search the same block twice
139+
def_blocks.iter_mut().for_each(|block| {
140+
if *block == Some(block_id) {
141+
*block = None;
142+
}
143+
});
144+
})
123145
.filter_map(|block_id| self.db.trait_impls_in_block(block_id));
124146

125147
let id_to_chalk = |id: hir_def::ImplId| id.to_chalk(self.db);
126148
let mut result = vec![];
127149
match fps {
128150
[] => {
129151
debug!("Unrestricted search for {:?} impls...", trait_);
130-
impl_maps.into_iter().chain(block_impls).for_each(|impls| {
152+
let mut f = |impls: Arc<TraitImpls>| {
131153
result.extend(impls.for_trait(trait_).map(id_to_chalk));
132-
});
154+
};
155+
impl_maps.into_iter().chain(block_impls).for_each(&mut f);
156+
def_blocks
157+
.into_iter()
158+
.filter_map(|it| self.db.trait_impls_in_block(it?))
159+
.for_each(f);
133160
}
134161
fps => {
135-
impl_maps.into_iter().chain(block_impls).for_each(|impls| {
136-
result.extend(
137-
fps.iter().flat_map(|fp| {
162+
let mut f =
163+
|impls: Arc<TraitImpls>| {
164+
result.extend(fps.iter().flat_map(|fp| {
138165
impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
139-
}),
140-
);
141-
});
166+
}));
167+
};
168+
impl_maps.into_iter().chain(block_impls).for_each(&mut f);
169+
def_blocks
170+
.into_iter()
171+
.filter_map(|it| self.db.trait_impls_in_block(it?))
172+
.for_each(f);
142173
}
143174
}
144175

crates/hir-ty/src/tests/coercion.rs

+29
Original file line numberDiff line numberDiff line change
@@ -902,3 +902,32 @@ fn test() {
902902
}",
903903
);
904904
}
905+
906+
#[test]
907+
fn regression_14443_dyn_coercion_block_impls() {
908+
check_no_mismatches(
909+
r#"
910+
//- minicore: coerce_unsized
911+
trait T {}
912+
913+
fn dyn_t(d: &dyn T) {}
914+
915+
fn main() {
916+
struct A;
917+
impl T for A {}
918+
919+
let a = A;
920+
921+
let b = {
922+
struct B;
923+
impl T for B {}
924+
925+
B
926+
};
927+
928+
dyn_t(&a);
929+
dyn_t(&b);
930+
}
931+
"#,
932+
)
933+
}

crates/hir-ty/src/tests/traits.rs

+29
Original file line numberDiff line numberDiff line change
@@ -3811,6 +3811,35 @@ fn f() {
38113811
);
38123812
}
38133813

3814+
#[test]
3815+
fn regression_14443_trait_solve() {
3816+
check_no_mismatches(
3817+
r#"
3818+
trait T {
3819+
fn f(&self) {}
3820+
}
3821+
3822+
3823+
fn main() {
3824+
struct A;
3825+
impl T for A {}
3826+
3827+
let a = A;
3828+
3829+
let b = {
3830+
struct B;
3831+
impl T for B {}
3832+
3833+
B
3834+
};
3835+
3836+
a.f();
3837+
b.f();
3838+
}
3839+
"#,
3840+
)
3841+
}
3842+
38143843
#[test]
38153844
fn associated_type_sized_bounds() {
38163845
check_infer(

crates/rust-analyzer/src/reload.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -456,7 +456,7 @@ impl GlobalState {
456456
let mut proc_macros = Vec::default();
457457
for ws in &**self.workspaces {
458458
let (other, mut crate_proc_macros) =
459-
ws.to_crate_graph(&mut load, &self.config.cargo().extra_env);
459+
ws.to_crate_graph(&mut load, &self.config.extra_env());
460460
crate_graph.extend(other, &mut crate_proc_macros);
461461
proc_macros.push(crate_proc_macros);
462462
}

0 commit comments

Comments
 (0)