7
7
use std:: { mem, sync:: Arc } ;
8
8
9
9
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
+ } ;
11
13
use memchr:: memmem:: Finder ;
12
14
use once_cell:: unsync:: Lazy ;
13
15
use parser:: SyntaxKind ;
@@ -311,15 +313,15 @@ impl Definition {
311
313
312
314
pub fn usages < ' a > ( self , sema : & ' a Semantics < ' _ , RootDatabase > ) -> FindUsages < ' a > {
313
315
FindUsages {
314
- local_repr : match self {
315
- Definition :: Local ( local) => Some ( local. representative ( sema. db ) ) ,
316
- _ => None ,
317
- } ,
318
316
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 ) ) ,
320
318
sema,
321
319
scope : None ,
322
320
include_self_kw_refs : None ,
321
+ local_repr : match self {
322
+ Definition :: Local ( local) => Some ( local. representative ( sema. db ) ) ,
323
+ _ => None ,
324
+ } ,
323
325
search_self_mod : false ,
324
326
}
325
327
}
@@ -328,8 +330,7 @@ impl Definition {
328
330
#[ derive( Clone ) ]
329
331
pub struct FindUsages < ' a > {
330
332
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 > ,
333
334
sema : & ' a Semantics < ' a , RootDatabase > ,
334
335
scope : Option < SearchScope > ,
335
336
include_self_kw_refs : Option < hir:: Type > ,
@@ -380,7 +381,9 @@ impl<'a> FindUsages<'a> {
380
381
let sema = self . sema ;
381
382
382
383
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 ) ;
384
387
match & self . scope {
385
388
None => base,
386
389
Some ( scope) => base. intersection ( scope) ,
@@ -651,13 +654,26 @@ impl<'a> FindUsages<'a> {
651
654
sink ( file_id, reference)
652
655
}
653
656
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 ) =>
661
677
{
662
678
let FileRange { file_id, range } = self . sema . original_range ( name_ref. syntax ( ) ) ;
663
679
let reference = FileReference {
@@ -748,12 +764,14 @@ impl<'a> FindUsages<'a> {
748
764
false
749
765
}
750
766
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
+ {
757
775
return false ;
758
776
}
759
777
let FileRange { file_id, range } = self . sema . original_range ( name. syntax ( ) ) ;
0 commit comments