Skip to content

Commit b2bce38

Browse files
bors[bot]xffxff
andauthored
Merge #10729
10729: Fix: Lookup impls in local def maps r=jonas-schievink a=XFFXFF fixes #10676 Co-authored-by: zhoufan <[email protected]>
2 parents f724c84 + f00cd91 commit b2bce38

File tree

3 files changed

+99
-25
lines changed

3 files changed

+99
-25
lines changed

crates/hir_ty/src/db.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
7777
#[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)]
7878
fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>;
7979

80+
#[salsa::invoke(InherentImpls::inherent_impls_in_block_query)]
81+
fn inherent_impls_in_block(&self, block: BlockId) -> Option<Arc<InherentImpls>>;
82+
8083
#[salsa::invoke(TraitImpls::trait_impls_in_crate_query)]
8184
fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>;
8285

crates/hir_ty/src/method_resolution.rs

Lines changed: 75 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -261,33 +261,45 @@ impl InherentImpls {
261261
let mut impls = Self { map: FxHashMap::default() };
262262

263263
let crate_def_map = db.crate_def_map(krate);
264-
collect_def_map(db, &crate_def_map, &mut impls);
264+
impls.collect_def_map(db, &crate_def_map);
265265

266266
return Arc::new(impls);
267+
}
268+
269+
pub(crate) fn inherent_impls_in_block_query(
270+
db: &dyn HirDatabase,
271+
block: BlockId,
272+
) -> Option<Arc<Self>> {
273+
let mut impls = Self { map: FxHashMap::default() };
274+
if let Some(block_def_map) = db.block_def_map(block) {
275+
impls.collect_def_map(db, &block_def_map);
276+
return Some(Arc::new(impls));
277+
}
278+
return None;
279+
}
280+
281+
fn collect_def_map(&mut self, db: &dyn HirDatabase, def_map: &DefMap) {
282+
for (_module_id, module_data) in def_map.modules() {
283+
for impl_id in module_data.scope.impls() {
284+
let data = db.impl_data(impl_id);
285+
if data.target_trait.is_some() {
286+
continue;
287+
}
267288

268-
fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut InherentImpls) {
269-
for (_module_id, module_data) in def_map.modules() {
270-
for impl_id in module_data.scope.impls() {
271-
let data = db.impl_data(impl_id);
272-
if data.target_trait.is_some() {
273-
continue;
274-
}
275-
276-
let self_ty = db.impl_self_ty(impl_id);
277-
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
278-
if let Some(fp) = fp {
279-
impls.map.entry(fp).or_default().push(impl_id);
280-
}
281-
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
289+
let self_ty = db.impl_self_ty(impl_id);
290+
let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
291+
if let Some(fp) = fp {
292+
self.map.entry(fp).or_default().push(impl_id);
282293
}
294+
// `fp` should only be `None` in error cases (either erroneous code or incomplete name resolution)
295+
}
283296

284-
// To better support custom derives, collect impls in all unnamed const items.
285-
// const _: () = { ... };
286-
for konst in module_data.scope.unnamed_consts() {
287-
let body = db.body(konst.into());
288-
for (_, block_def_map) in body.blocks(db.upcast()) {
289-
collect_def_map(db, &block_def_map, impls);
290-
}
297+
// To better support custom derives, collect impls in all unnamed const items.
298+
// const _: () = { ... };
299+
for konst in module_data.scope.unnamed_consts() {
300+
let body = db.body(konst.into());
301+
for (_, block_def_map) in body.blocks(db.upcast()) {
302+
self.collect_def_map(db, &block_def_map);
291303
}
292304
}
293305
}
@@ -744,11 +756,49 @@ fn iterate_inherent_methods(
744756
None => return ControlFlow::Continue(()),
745757
};
746758

759+
if let Some(module_id) = visible_from_module {
760+
if let Some(block_id) = module_id.containing_block() {
761+
if let Some(impls) = db.inherent_impls_in_block(block_id) {
762+
impls_for_self_ty(
763+
&impls,
764+
self_ty,
765+
db,
766+
env.clone(),
767+
name,
768+
receiver_ty,
769+
visible_from_module,
770+
callback,
771+
)?;
772+
}
773+
}
774+
}
775+
747776
for krate in def_crates {
748777
let impls = db.inherent_impls_in_crate(krate);
778+
impls_for_self_ty(
779+
&impls,
780+
self_ty,
781+
db,
782+
env.clone(),
783+
name,
784+
receiver_ty,
785+
visible_from_module,
786+
callback,
787+
)?;
788+
}
789+
return ControlFlow::Continue(());
749790

750-
let impls_for_self_ty = filter_inherent_impls_for_self_ty(&impls, &self_ty.value);
751-
791+
fn impls_for_self_ty(
792+
impls: &InherentImpls,
793+
self_ty: &Canonical<Ty>,
794+
db: &dyn HirDatabase,
795+
env: Arc<TraitEnvironment>,
796+
name: Option<&Name>,
797+
receiver_ty: Option<&Canonical<Ty>>,
798+
visible_from_module: Option<ModuleId>,
799+
callback: &mut dyn FnMut(&Canonical<Ty>, AssocItemId) -> ControlFlow<()>,
800+
) -> ControlFlow<()> {
801+
let impls_for_self_ty = filter_inherent_impls_for_self_ty(impls, &self_ty.value);
752802
for &impl_def in impls_for_self_ty {
753803
for &item in db.impl_data(impl_def).items.iter() {
754804
if !is_valid_candidate(
@@ -776,8 +826,8 @@ fn iterate_inherent_methods(
776826
callback(receiver_ty, item)?;
777827
}
778828
}
829+
ControlFlow::Continue(())
779830
}
780-
ControlFlow::Continue(())
781831
}
782832

783833
/// Returns the self type for the index trait call.

crates/hir_ty/src/tests/method_resolution.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1386,3 +1386,24 @@ fn f<S: Sized, T, U: ?Sized>() {
13861386
"#]],
13871387
);
13881388
}
1389+
1390+
#[test]
1391+
fn local_impl() {
1392+
check_types(
1393+
r#"
1394+
fn main() {
1395+
struct SomeStruct(i32);
1396+
1397+
impl SomeStruct {
1398+
fn is_even(&self) -> bool {
1399+
self.0 % 2 == 0
1400+
}
1401+
}
1402+
1403+
let o = SomeStruct(3);
1404+
let is_even = o.is_even();
1405+
// ^^^^^^^ bool
1406+
}
1407+
"#,
1408+
);
1409+
}

0 commit comments

Comments
 (0)