Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit 09aceea

Browse files
committed
Auto merge of rust-lang#13933 - Veykril:assoc-search, r=Veykril
Refine search for const and function assoc items This changes our searching behavior, before we always associated all usages and definitions of associated items with all implementations of a trait and the trait itself. Now, when searching for references of a an associated trait item, we still do the same and consider all implementations, but when searching for an associated item of an implementation we now only consider the uses of that specific implementations associated item. This does not affect associated type aliases as we unfortunately are missing information in the IDE layer here still.
2 parents f32f64b + bb4e272 commit 09aceea

File tree

7 files changed

+319
-36
lines changed

7 files changed

+319
-36
lines changed

crates/hir-ty/src/method_resolution.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -712,17 +712,17 @@ fn lookup_impl_assoc_item_for_trait_ref(
712712
let table = InferenceTable::new(db, env);
713713

714714
let impl_data = find_matching_impl(impls, table, trait_ref)?;
715-
impl_data.items.iter().find_map(|it| match it {
715+
impl_data.items.iter().find_map(|&it| match it {
716716
AssocItemId::FunctionId(f) => {
717-
(db.function_data(*f).name == *name).then_some(AssocItemId::FunctionId(*f))
717+
(db.function_data(f).name == *name).then_some(AssocItemId::FunctionId(f))
718718
}
719719
AssocItemId::ConstId(c) => db
720-
.const_data(*c)
720+
.const_data(c)
721721
.name
722722
.as_ref()
723-
.map(|n| *n == *name)
724-
.and_then(|result| if result { Some(AssocItemId::ConstId(*c)) } else { None }),
725-
_ => None,
723+
.map(|n| n == name)
724+
.and_then(|result| if result { Some(AssocItemId::ConstId(c)) } else { None }),
725+
AssocItemId::TypeAliasId(_) => None,
726726
})
727727
}
728728

crates/hir/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2129,7 +2129,7 @@ pub enum AssocItem {
21292129
Const(Const),
21302130
TypeAlias(TypeAlias),
21312131
}
2132-
#[derive(Debug)]
2132+
#[derive(Debug, Clone)]
21332133
pub enum AssocItemContainer {
21342134
Trait(Trait),
21352135
Impl(Impl),

crates/hir/src/source_analyzer.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,7 @@ impl SourceAnalyzer {
504504
AssocItemId::ConstId(const_id) => {
505505
self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
506506
}
507-
_ => assoc,
507+
assoc => assoc,
508508
};
509509

510510
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
@@ -517,7 +517,13 @@ impl SourceAnalyzer {
517517
prefer_value_ns = true;
518518
} else if let Some(path_pat) = parent().and_then(ast::PathPat::cast) {
519519
let pat_id = self.pat_id(&path_pat.into())?;
520-
if let Some((assoc, _)) = infer.assoc_resolutions_for_pat(pat_id) {
520+
if let Some((assoc, subs)) = infer.assoc_resolutions_for_pat(pat_id) {
521+
let assoc = match assoc {
522+
AssocItemId::ConstId(const_id) => {
523+
self.resolve_impl_const_or_trait_def(db, const_id, subs).into()
524+
}
525+
assoc => assoc,
526+
};
521527
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
522528
}
523529
if let Some(VariantId::EnumVariantId(variant)) =

crates/ide-db/src/search.rs

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
use std::{mem, sync::Arc};
88

99
use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt};
10-
use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility};
10+
use hir::{
11+
AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility,
12+
};
1113
use memchr::memmem::Finder;
1214
use once_cell::unsync::Lazy;
1315
use parser::SyntaxKind;
@@ -311,15 +313,15 @@ impl Definition {
311313

312314
pub fn usages<'a>(self, sema: &'a Semantics<'_, RootDatabase>) -> FindUsages<'a> {
313315
FindUsages {
314-
local_repr: match self {
315-
Definition::Local(local) => Some(local.representative(sema.db)),
316-
_ => None,
317-
},
318316
def: self,
319-
trait_assoc_def: as_trait_assoc_def(sema.db, self),
317+
assoc_item_container: self.as_assoc_item(sema.db).map(|a| a.container(sema.db)),
320318
sema,
321319
scope: None,
322320
include_self_kw_refs: None,
321+
local_repr: match self {
322+
Definition::Local(local) => Some(local.representative(sema.db)),
323+
_ => None,
324+
},
323325
search_self_mod: false,
324326
}
325327
}
@@ -328,8 +330,7 @@ impl Definition {
328330
#[derive(Clone)]
329331
pub struct FindUsages<'a> {
330332
def: Definition,
331-
/// If def is an assoc item from a trait or trait impl, this is the corresponding item of the trait definition
332-
trait_assoc_def: Option<Definition>,
333+
assoc_item_container: Option<hir::AssocItemContainer>,
333334
sema: &'a Semantics<'a, RootDatabase>,
334335
scope: Option<SearchScope>,
335336
include_self_kw_refs: Option<hir::Type>,
@@ -380,7 +381,9 @@ impl<'a> FindUsages<'a> {
380381
let sema = self.sema;
381382

382383
let search_scope = {
383-
let base = self.trait_assoc_def.unwrap_or(self.def).search_scope(sema.db);
384+
// FIXME: Is the trait scope needed for trait impl assoc items?
385+
let base =
386+
as_trait_assoc_def(sema.db, self.def).unwrap_or(self.def).search_scope(sema.db);
384387
match &self.scope {
385388
None => base,
386389
Some(scope) => base.intersection(scope),
@@ -651,13 +654,26 @@ impl<'a> FindUsages<'a> {
651654
sink(file_id, reference)
652655
}
653656
Some(NameRefClass::Definition(def))
654-
if match self.trait_assoc_def {
655-
Some(trait_assoc_def) => {
656-
// we have a trait assoc item, so force resolve all assoc items to their trait version
657-
convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def
658-
}
659-
None => self.def == def,
660-
} =>
657+
if self.def == def
658+
// is our def a trait assoc item? then we want to find everything
659+
|| matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
660+
&& convert_to_def_in_trait(self.sema.db, def) == self.def =>
661+
{
662+
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
663+
let reference = FileReference {
664+
range,
665+
name: ast::NameLike::NameRef(name_ref.clone()),
666+
category: ReferenceCategory::new(&def, name_ref),
667+
};
668+
sink(file_id, reference)
669+
}
670+
// FIXME: special case type aliases, we can't filter between impl and trait defs here as we lack the substitutions
671+
// so we always resolve all assoc type aliases to both their trait def and impl defs
672+
Some(NameRefClass::Definition(def))
673+
if self.assoc_item_container.is_some()
674+
&& matches!(self.def, Definition::TypeAlias(_))
675+
&& convert_to_def_in_trait(self.sema.db, def)
676+
== convert_to_def_in_trait(self.sema.db, self.def) =>
661677
{
662678
let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax());
663679
let reference = FileReference {
@@ -748,12 +764,14 @@ impl<'a> FindUsages<'a> {
748764
false
749765
}
750766
Some(NameClass::Definition(def)) if def != self.def => {
751-
// if the def we are looking for is a trait (impl) assoc item, we'll have to resolve the items to trait definition assoc item
752-
if !matches!(
753-
self.trait_assoc_def,
754-
Some(trait_assoc_def)
755-
if convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def
756-
) {
767+
// only when looking for trait assoc items, we want to find other assoc items
768+
if !matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
769+
// FIXME: special case type aliases, we can't filter between impl and trait defs here as we lack the substitutions
770+
// so we always resolve all assoc type aliases to both their trait def and impl defs
771+
&& !(matches!(self.def, Definition::TypeAlias(_))
772+
&& convert_to_def_in_trait(self.sema.db, def)
773+
== convert_to_def_in_trait(self.sema.db, self.def))
774+
{
757775
return false;
758776
}
759777
let FileRange { file_id, range } = self.sema.original_range(name.syntax());

crates/ide/src/highlight_related.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1356,7 +1356,6 @@ fn main() {
13561356
r#"
13571357
trait Trait {
13581358
fn func(self) {}
1359-
//^^^^
13601359
}
13611360
13621361
impl Trait for () {
@@ -1376,7 +1375,6 @@ fn main() {
13761375
r#"
13771376
trait Trait {
13781377
fn func(self) {}
1379-
//^^^^
13801378
}
13811379
13821380
impl Trait for () {

0 commit comments

Comments
 (0)