Skip to content

Commit cd4ac0d

Browse files
committed
Auto merge of rust-lang#14020 - Veykril:search-fix, r=Veykril
fix: Fix assoc item search finding unrelated definitions Fixes rust-lang/rust-analyzer#14014
2 parents 86f73a0 + 951ee3d commit cd4ac0d

File tree

2 files changed

+141
-11
lines changed

2 files changed

+141
-11
lines changed

crates/ide-db/src/search.rs

+22-11
Original file line numberDiff line numberDiff line change
@@ -330,11 +330,16 @@ impl Definition {
330330
#[derive(Clone)]
331331
pub struct FindUsages<'a> {
332332
def: Definition,
333-
assoc_item_container: Option<hir::AssocItemContainer>,
334333
sema: &'a Semantics<'a, RootDatabase>,
335334
scope: Option<SearchScope>,
335+
/// The container of our definition should it be an assoc item
336+
assoc_item_container: Option<hir::AssocItemContainer>,
337+
/// whether to search for the `Self` type of the definition
336338
include_self_kw_refs: Option<hir::Type>,
339+
/// the local representative for the local definition we are searching for
340+
/// (this is required for finding all local declarations in a or-pattern)
337341
local_repr: Option<hir::Local>,
342+
/// whether to search for the `self` module
338343
search_self_mod: bool,
339344
}
340345

@@ -655,7 +660,7 @@ impl<'a> FindUsages<'a> {
655660
}
656661
Some(NameRefClass::Definition(def))
657662
if self.def == def
658-
// is our def a trait assoc item? then we want to find everything
663+
// is our def a trait assoc item? then we want to find all assoc items from trait impls of our trait
659664
|| matches!(self.assoc_item_container, Some(hir::AssocItemContainer::Trait(_)))
660665
&& convert_to_def_in_trait(self.sema.db, def) == self.def =>
661666
{
@@ -764,15 +769,21 @@ impl<'a> FindUsages<'a> {
764769
false
765770
}
766771
Some(NameClass::Definition(def)) if def != self.def => {
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-
{
775-
return false;
772+
match (&self.assoc_item_container, self.def) {
773+
// for type aliases we always want to reference the trait def and all the trait impl counterparts
774+
// FIXME: only until we can resolve them correctly, see FIXME above
775+
(Some(_), Definition::TypeAlias(_))
776+
if convert_to_def_in_trait(self.sema.db, def)
777+
!= convert_to_def_in_trait(self.sema.db, self.def) =>
778+
{
779+
return false
780+
}
781+
(Some(_), Definition::TypeAlias(_)) => {}
782+
// We looking at an assoc item of a trait definition, so reference all the
783+
// corresponding assoc items belonging to this trait's trait implementations
784+
(Some(hir::AssocItemContainer::Trait(_)), _)
785+
if convert_to_def_in_trait(self.sema.db, def) == self.def => {}
786+
_ => return false,
776787
}
777788
let FileRange { file_id, range } = self.sema.original_range(name.syntax());
778789
let reference = FileReference {

crates/ide/src/references.rs

+119
Original file line numberDiff line numberDiff line change
@@ -1897,4 +1897,123 @@ fn f<T: Trait>() {
18971897
"#]],
18981898
);
18991899
}
1900+
1901+
#[test]
1902+
fn name_clashes() {
1903+
check(
1904+
r#"
1905+
trait Foo {
1906+
fn method$0(&self) -> u8;
1907+
}
1908+
1909+
struct Bar {
1910+
method: u8,
1911+
}
1912+
1913+
impl Foo for Bar {
1914+
fn method(&self) -> u8 {
1915+
self.method
1916+
}
1917+
}
1918+
fn method() {}
1919+
"#,
1920+
expect![[r#"
1921+
method Function FileId(0) 16..39 19..25
1922+
1923+
FileId(0) 101..107
1924+
"#]],
1925+
);
1926+
check(
1927+
r#"
1928+
trait Foo {
1929+
fn method(&self) -> u8;
1930+
}
1931+
1932+
struct Bar {
1933+
method$0: u8,
1934+
}
1935+
1936+
impl Foo for Bar {
1937+
fn method(&self) -> u8 {
1938+
self.method
1939+
}
1940+
}
1941+
fn method() {}
1942+
"#,
1943+
expect![[r#"
1944+
method Field FileId(0) 60..70 60..66
1945+
1946+
FileId(0) 136..142 Read
1947+
"#]],
1948+
);
1949+
check(
1950+
r#"
1951+
trait Foo {
1952+
fn method(&self) -> u8;
1953+
}
1954+
1955+
struct Bar {
1956+
method: u8,
1957+
}
1958+
1959+
impl Foo for Bar {
1960+
fn method$0(&self) -> u8 {
1961+
self.method
1962+
}
1963+
}
1964+
fn method() {}
1965+
"#,
1966+
expect![[r#"
1967+
method Function FileId(0) 98..148 101..107
1968+
1969+
(no references)
1970+
"#]],
1971+
);
1972+
check(
1973+
r#"
1974+
trait Foo {
1975+
fn method(&self) -> u8;
1976+
}
1977+
1978+
struct Bar {
1979+
method: u8,
1980+
}
1981+
1982+
impl Foo for Bar {
1983+
fn method(&self) -> u8 {
1984+
self.method$0
1985+
}
1986+
}
1987+
fn method() {}
1988+
"#,
1989+
expect![[r#"
1990+
method Field FileId(0) 60..70 60..66
1991+
1992+
FileId(0) 136..142 Read
1993+
"#]],
1994+
);
1995+
check(
1996+
r#"
1997+
trait Foo {
1998+
fn method(&self) -> u8;
1999+
}
2000+
2001+
struct Bar {
2002+
method: u8,
2003+
}
2004+
2005+
impl Foo for Bar {
2006+
fn method(&self) -> u8 {
2007+
self.method
2008+
}
2009+
}
2010+
fn method$0() {}
2011+
"#,
2012+
expect![[r#"
2013+
method Function FileId(0) 151..165 154..160
2014+
2015+
(no references)
2016+
"#]],
2017+
);
2018+
}
19002019
}

0 commit comments

Comments
 (0)