diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index fd09fdeb0b..ada2821d6b 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -330,11 +330,16 @@ impl Definition { #[derive(Clone)] pub struct FindUsages<'a> { def: Definition, - assoc_item_container: Option, sema: &'a Semantics<'a, RootDatabase>, scope: Option, + /// The container of our definition should it be an assoc item + assoc_item_container: Option, + /// whether to search for the `Self` type of the definition include_self_kw_refs: Option, + /// the local representative for the local definition we are searching for + /// (this is required for finding all local declarations in a or-pattern) local_repr: Option, + /// whether to search for the `self` module search_self_mod: bool, } @@ -655,7 +660,7 @@ impl<'a> FindUsages<'a> { } Some(NameRefClass::Definition(def)) if self.def == def - // is our def a trait assoc item? then we want to find everything + // is our def a trait assoc item? then we want to find all assoc items from trait impls of our trait || matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_))) && convert_to_def_in_trait(self.sema.db, def) == self.def => { @@ -764,15 +769,21 @@ impl<'a> FindUsages<'a> { false } Some(NameClass::Definition(def)) if def != self.def => { - // only when looking for trait assoc items, we want to find other assoc items - if !matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_))) - // FIXME: special case type aliases, we can't filter between impl and trait defs here as we lack the substitutions - // so we always resolve all assoc type aliases to both their trait def and impl defs - && !(matches!(self.def, Definition::TypeAlias(_)) - && convert_to_def_in_trait(self.sema.db, def) - == convert_to_def_in_trait(self.sema.db, self.def)) - { - return false; + match (&self.assoc_item_container, self.def) { + // for type aliases we always want to reference the trait def and all the trait impl counterparts + // FIXME: only until we can resolve them correctly, see FIXME above + (Some(_), Definition::TypeAlias(_)) + if convert_to_def_in_trait(self.sema.db, def) + != convert_to_def_in_trait(self.sema.db, self.def) => + { + return false + } + (Some(_), Definition::TypeAlias(_)) => {} + // We looking at an assoc item of a trait definition, so reference all the + // corresponding assoc items belonging to this trait's trait implementations + (Some(hir::AssocItemContainer::Trait(_)), _) + if convert_to_def_in_trait(self.sema.db, def) == self.def => {} + _ => return false, } let FileRange { file_id, range } = self.sema.original_range(name.syntax()); let reference = FileReference { diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs index e49f68c57b..60fb1544a8 100644 --- a/crates/ide/src/references.rs +++ b/crates/ide/src/references.rs @@ -1897,4 +1897,123 @@ fn f() { "#]], ); } + + #[test] + fn name_clashes() { + check( + r#" +trait Foo { + fn method$0(&self) -> u8; +} + +struct Bar { + method: u8, +} + +impl Foo for Bar { + fn method(&self) -> u8 { + self.method + } +} +fn method() {} +"#, + expect![[r#" + method Function FileId(0) 16..39 19..25 + + FileId(0) 101..107 + "#]], + ); + check( + r#" +trait Foo { + fn method(&self) -> u8; +} + +struct Bar { + method$0: u8, +} + +impl Foo for Bar { + fn method(&self) -> u8 { + self.method + } +} +fn method() {} +"#, + expect![[r#" + method Field FileId(0) 60..70 60..66 + + FileId(0) 136..142 Read + "#]], + ); + check( + r#" +trait Foo { + fn method(&self) -> u8; +} + +struct Bar { + method: u8, +} + +impl Foo for Bar { + fn method$0(&self) -> u8 { + self.method + } +} +fn method() {} +"#, + expect![[r#" + method Function FileId(0) 98..148 101..107 + + (no references) + "#]], + ); + check( + r#" +trait Foo { + fn method(&self) -> u8; +} + +struct Bar { + method: u8, +} + +impl Foo for Bar { + fn method(&self) -> u8 { + self.method$0 + } +} +fn method() {} +"#, + expect![[r#" + method Field FileId(0) 60..70 60..66 + + FileId(0) 136..142 Read + "#]], + ); + check( + r#" +trait Foo { + fn method(&self) -> u8; +} + +struct Bar { + method: u8, +} + +impl Foo for Bar { + fn method(&self) -> u8 { + self.method + } +} +fn method$0() {} +"#, + expect![[r#" + method Function FileId(0) 151..165 154..160 + + (no references) + "#]], + ); + } }