77use std:: { mem, sync:: Arc } ;
88
99use 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+ } ;
1113use memchr:: memmem:: Finder ;
1214use once_cell:: unsync:: Lazy ;
1315use 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 ) ]
329331pub 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 ( ) ) ;
0 commit comments