mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Merge #10729
10729: Fix: Lookup impls in local def maps r=jonas-schievink a=XFFXFF fixes #10676 Co-authored-by: zhoufan <1247714429@qq.com>
This commit is contained in:
commit
b2bce38bb4
@ -77,6 +77,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
|
|||||||
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
|
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
|
||||||
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
|
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
|
||||||
|
|
||||||
|
#[salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
|
||||||
|
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
|
||||||
|
|
||||||
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
|
||||||
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
|
||||||
|
|
||||||
|
@ -261,33 +261,45 @@ impl InherentImpls {
|
|||||||
let mut impls = Self { map: FxHashMap::default() };
|
let mut impls = Self { map: FxHashMap::default() };
|
||||||
|
|
||||||
let crate_def_map = db.crate_def_map(krate);
|
let crate_def_map = db.crate_def_map(krate);
|
||||||
collect_def_map(db, &crate_def_map, &mut impls);
|
impls.collect_def_map(db, &crate_def_map);
|
||||||
|
|
||||||
return Arc::new(impls);
|
return Arc::new(impls);
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) {
|
pub(crate) fn inherent_impls_in_block_query(
|
||||||
for (_module_id, module_data) in def_map.modules() {
|
db: &dyn HirDatabase,
|
||||||
for impl_id in module_data.scope.impls() {
|
block: BlockId,
|
||||||
let data = db.impl_data(impl_id);
|
) -> Option<Arc<Self>> {
|
||||||
if data.target_trait.is_some() {
|
let mut impls = Self { map: FxHashMap::default() };
|
||||||
continue;
|
if let Some(block_def_map) = db.block_def_map(block) {
|
||||||
}
|
impls.collect_def_map(db, &block_def_map);
|
||||||
|
return Some(Arc::new(impls));
|
||||||
|
}
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
let self_ty = db.impl_self_ty(impl_id);
|
fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
|
||||||
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
|
for (_module_id, module_data) in def_map.modules() {
|
||||||
if let Some(fp) = fp {
|
for impl_id in module_data.scope.impls() {
|
||||||
impls.map.entry(fp).or_default().push(impl_id);
|
let data = db.impl_data(impl_id);
|
||||||
}
|
if data.target_trait.is_some() {
|
||||||
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// To better support custom derives, collect impls in all unnamed const items.
|
let self_ty = db.impl_self_ty(impl_id);
|
||||||
// const _: () = { ... };
|
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
|
||||||
for konst in module_data.scope.unnamed_consts() {
|
if let Some(fp) = fp {
|
||||||
let body = db.body(konst.into());
|
self.map.entry(fp).or_default().push(impl_id);
|
||||||
for (_, block_def_map) in body.blocks(db.upcast()) {
|
}
|
||||||
collect_def_map(db, &block_def_map, impls);
|
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// To better support custom derives, collect impls in all unnamed const items.
|
||||||
|
// const _: () = { ... };
|
||||||
|
for konst in module_data.scope.unnamed_consts() {
|
||||||
|
let body = db.body(konst.into());
|
||||||
|
for (_, block_def_map) in body.blocks(db.upcast()) {
|
||||||
|
self.collect_def_map(db, &block_def_map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -744,11 +756,49 @@ fn iterate_inherent_methods(
|
|||||||
None => return ControlFlow::Continue(()),
|
None => return ControlFlow::Continue(()),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if let Some(module_id) = visible_from_module {
|
||||||
|
if let Some(block_id) = module_id.containing_block() {
|
||||||
|
if let Some(impls) = db.inherent_impls_in_block(block_id) {
|
||||||
|
impls_for_self_ty(
|
||||||
|
&impls,
|
||||||
|
self_ty,
|
||||||
|
db,
|
||||||
|
env.clone(),
|
||||||
|
name,
|
||||||
|
receiver_ty,
|
||||||
|
visible_from_module,
|
||||||
|
callback,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for krate in def_crates {
|
for krate in def_crates {
|
||||||
let impls = db.inherent_impls_in_crate(krate);
|
let impls = db.inherent_impls_in_crate(krate);
|
||||||
|
impls_for_self_ty(
|
||||||
|
&impls,
|
||||||
|
self_ty,
|
||||||
|
db,
|
||||||
|
env.clone(),
|
||||||
|
name,
|
||||||
|
receiver_ty,
|
||||||
|
visible_from_module,
|
||||||
|
callback,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
return ControlFlow::Continue(());
|
||||||
|
|
||||||
let impls_for_self_ty = filter_inherent_impls_for_self_ty(&impls, &self_ty.value);
|
fn impls_for_self_ty(
|
||||||
|
impls: &InherentImpls,
|
||||||
|
self_ty: &Canonical<Ty>,
|
||||||
|
db: &dyn HirDatabase,
|
||||||
|
env: Arc<TraitEnvironment>,
|
||||||
|
name: Option<&Name>,
|
||||||
|
receiver_ty: Option<&Canonical<Ty>>,
|
||||||
|
visible_from_module: Option<ModuleId>,
|
||||||
|
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
|
||||||
|
) -> ControlFlow<()> {
|
||||||
|
let impls_for_self_ty = filter_inherent_impls_for_self_ty(impls, &self_ty.value);
|
||||||
for &impl_def in impls_for_self_ty {
|
for &impl_def in impls_for_self_ty {
|
||||||
for &item in db.impl_data(impl_def).items.iter() {
|
for &item in db.impl_data(impl_def).items.iter() {
|
||||||
if !is_valid_candidate(
|
if !is_valid_candidate(
|
||||||
@ -776,8 +826,8 @@ fn iterate_inherent_methods(
|
|||||||
callback(receiver_ty, item)?;
|
callback(receiver_ty, item)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
ControlFlow::Continue(())
|
||||||
}
|
}
|
||||||
ControlFlow::Continue(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the self type for the index trait call.
|
/// Returns the self type for the index trait call.
|
||||||
|
@ -1386,3 +1386,24 @@ fn f<S: Sized, T, U: ?Sized>() {
|
|||||||
"#]],
|
"#]],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn local_impl() {
|
||||||
|
check_types(
|
||||||
|
r#"
|
||||||
|
fn main() {
|
||||||
|
struct SomeStruct(i32);
|
||||||
|
|
||||||
|
impl SomeStruct {
|
||||||
|
fn is_even(&self) -> bool {
|
||||||
|
self.0 % 2 == 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let o = SomeStruct(3);
|
||||||
|
let is_even = o.is_even();
|
||||||
|
// ^^^^^^^ bool
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user