mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-12-29 06:23:25 +00:00
fix: Fix block local impl trait solving regressions
This commit is contained in:
parent
236576227a
commit
1c16e4ee97
4 changed files with 100 additions and 11 deletions
|
@ -18,9 +18,10 @@ use hir_expand::name::name;
|
||||||
use crate::{
|
use crate::{
|
||||||
db::HirDatabase,
|
db::HirDatabase,
|
||||||
display::HirDisplay,
|
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},
|
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,
|
to_assoc_type_id, to_chalk_trait_id,
|
||||||
traits::ChalkContext,
|
traits::ChalkContext,
|
||||||
utils::generics,
|
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(&[]),
|
_ => 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
|
// 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
|
// can be resolved should ever reach Chalk. impl_datum relies on that
|
||||||
// and will panic if the trait can't be resolved.
|
// 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(|map| map.parent())
|
||||||
.and_then(|module| module.containing_block())
|
.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));
|
.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);
|
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 {
|
match fps {
|
||||||
[] => {
|
[] => {
|
||||||
debug!("Unrestricted search for {:?} impls...", trait_);
|
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));
|
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 => {
|
fps => {
|
||||||
impl_maps.into_iter().chain(block_impls).for_each(|impls| {
|
let mut f =
|
||||||
result.extend(
|
|impls: Arc<TraitImpls>| {
|
||||||
fps.iter().flat_map(|fp| {
|
result.extend(fps.iter().flat_map(|fp| {
|
||||||
impls.for_trait_and_self_ty(trait_, *fp).map(id_to_chalk)
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
|
@ -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]
|
#[test]
|
||||||
fn associated_type_sized_bounds() {
|
fn associated_type_sized_bounds() {
|
||||||
check_infer(
|
check_infer(
|
||||||
|
|
|
@ -447,7 +447,7 @@ impl GlobalState {
|
||||||
let mut proc_macros = Vec::default();
|
let mut proc_macros = Vec::default();
|
||||||
for ws in &**self.workspaces {
|
for ws in &**self.workspaces {
|
||||||
let (other, mut crate_proc_macros) =
|
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);
|
crate_graph.extend(other, &mut crate_proc_macros);
|
||||||
proc_macros.push(crate_proc_macros);
|
proc_macros.push(crate_proc_macros);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue