77use std:: { convert:: TryInto , mem, sync:: Arc } ;
88
99use base_db:: { FileId , FileRange , SourceDatabase , SourceDatabaseExt } ;
10- use hir:: {
11- AsAssocItem , DefWithBody , HasAttrs , HasSource , InFile , ModuleSource , Semantics , Visibility ,
12- } ;
10+ use hir:: { DefWithBody , HasAttrs , HasSource , InFile , ModuleSource , Semantics , Visibility } ;
1311use once_cell:: unsync:: Lazy ;
1412use rustc_hash:: FxHashMap ;
1513use syntax:: { ast, match_ast, AstNode , TextRange , TextSize } ;
1614
1715use crate :: {
1816 defs:: { Definition , NameClass , NameRefClass } ,
19- traits:: convert_to_def_in_trait,
17+ traits:: { as_trait_assoc_def , convert_to_def_in_trait} ,
2018 RootDatabase ,
2119} ;
2220
@@ -314,6 +312,7 @@ impl Definition {
314312 _ => None ,
315313 } ,
316314 def : self ,
315+ trait_assoc_def : as_trait_assoc_def ( sema. db , self ) ,
317316 sema,
318317 scope : None ,
319318 include_self_kw_refs : None ,
@@ -325,6 +324,8 @@ impl Definition {
325324#[ derive( Clone ) ]
326325pub struct FindUsages < ' a > {
327326 def : Definition ,
327+ /// If def is an assoc item from a trait or trait impl, this is the corresponding item of the trait definition
328+ trait_assoc_def : Option < Definition > ,
328329 sema : & ' a Semantics < ' a , RootDatabase > ,
329330 scope : Option < SearchScope > ,
330331 include_self_kw_refs : Option < hir:: Type > ,
@@ -375,7 +376,7 @@ impl<'a> FindUsages<'a> {
375376 let sema = self . sema ;
376377
377378 let search_scope = {
378- let base = self . def . search_scope ( sema. db ) ;
379+ let base = self . trait_assoc_def . unwrap_or ( self . def ) . search_scope ( sema. db ) ;
379380 match & self . scope {
380381 None => base,
381382 Some ( scope) => base. intersection ( scope) ,
@@ -621,7 +622,13 @@ impl<'a> FindUsages<'a> {
621622 sink ( file_id, reference)
622623 }
623624 Some ( NameRefClass :: Definition ( def) )
624- if convert_to_def_in_trait ( self . sema . db , def) == self . def =>
625+ if match self . trait_assoc_def {
626+ Some ( trait_assoc_def) => {
627+ // we have a trait assoc item, so force resolve all assoc items to their trait version
628+ convert_to_def_in_trait ( self . sema . db , def) == trait_assoc_def
629+ }
630+ None => self . def == def,
631+ } =>
625632 {
626633 let FileRange { file_id, range } = self . sema . original_range ( name_ref. syntax ( ) ) ;
627634 let reference = FileReference {
@@ -711,30 +718,22 @@ impl<'a> FindUsages<'a> {
711718 }
712719 false
713720 }
714- // Resolve trait impl function definitions to the trait definition's version if self.def is the trait definition's
715721 Some ( NameClass :: Definition ( def) ) if def != self . def => {
716- /* poor man's try block */
717- ( || {
718- let this_trait = self
719- . def
720- . as_assoc_item ( self . sema . db ) ?
721- . containing_trait_or_trait_impl ( self . sema . db ) ?;
722- let trait_ = def
723- . as_assoc_item ( self . sema . db ) ?
724- . containing_trait_or_trait_impl ( self . sema . db ) ?;
725- ( trait_ == this_trait && self . def . name ( self . sema . db ) == def. name ( self . sema . db ) )
726- . then ( || {
727- let FileRange { file_id, range } =
728- self . sema . original_range ( name. syntax ( ) ) ;
729- let reference = FileReference {
730- range,
731- name : ast:: NameLike :: Name ( name. clone ( ) ) ,
732- category : None ,
733- } ;
734- sink ( file_id, reference)
735- } )
736- } ) ( )
737- . unwrap_or ( false )
722+ // 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
723+ if !matches ! (
724+ self . trait_assoc_def,
725+ Some ( trait_assoc_def)
726+ if convert_to_def_in_trait( self . sema. db, def) == trait_assoc_def
727+ ) {
728+ return false ;
729+ }
730+ let FileRange { file_id, range } = self . sema . original_range ( name. syntax ( ) ) ;
731+ let reference = FileReference {
732+ range,
733+ name : ast:: NameLike :: Name ( name. clone ( ) ) ,
734+ category : None ,
735+ } ;
736+ sink ( file_id, reference)
738737 }
739738 _ => false ,
740739 }
0 commit comments