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

Commit bb4e272

Browse files
committed
Refine search for const and function assoc items
1 parent f32f64b commit bb4e272

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)