X-Git-Url: https://git.lizzy.rs/?a=blobdiff_plain;f=crates%2Fide-db%2Fsrc%2Fsearch.rs;h=f02e096350556f9de220ef9adea35fcbe3f5f606;hb=bb4bfae42294dea4c0f97f2cea42817110caa809;hp=4a11fb73cd6d987aab3e1a84e4ea29873ac4b6d2;hpb=96481b7786fb1a987c2e912769ee5269fffbea0c;p=rust.git diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs index 4a11fb73cd6..f02e0963505 100644 --- a/crates/ide-db/src/search.rs +++ b/crates/ide-db/src/search.rs @@ -7,15 +7,14 @@ use std::{convert::TryInto, mem, sync::Arc}; use base_db::{FileId, FileRange, SourceDatabase, SourceDatabaseExt}; -use hir::{ - AsAssocItem, DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility, -}; +use hir::{DefWithBody, HasAttrs, HasSource, InFile, ModuleSource, Semantics, Visibility}; use once_cell::unsync::Lazy; use rustc_hash::FxHashMap; use syntax::{ast, match_ast, AstNode, TextRange, TextSize}; use crate::{ defs::{Definition, NameClass, NameRefClass}, + traits::{as_trait_assoc_def, convert_to_def_in_trait}, RootDatabase, }; @@ -313,6 +312,7 @@ pub fn usages<'a>(self, sema: &'a Semantics) -> FindUsages<'a> { _ => None, }, def: self, + trait_assoc_def: as_trait_assoc_def(sema.db, self), sema, scope: None, include_self_kw_refs: None, @@ -324,6 +324,8 @@ pub fn usages<'a>(self, sema: &'a Semantics) -> FindUsages<'a> { #[derive(Clone)] pub struct FindUsages<'a> { def: Definition, + /// If def is an assoc item from a trait or trait impl, this is the corresponding item of the trait definition + trait_assoc_def: Option, sema: &'a Semantics<'a, RootDatabase>, scope: Option, include_self_kw_refs: Option, @@ -374,7 +376,7 @@ fn search(&self, sink: &mut dyn FnMut(FileId, FileReference) -> bool) { let sema = self.sema; let search_scope = { - let base = self.def.search_scope(sema.db); + let base = self.trait_assoc_def.unwrap_or(self.def).search_scope(sema.db); match &self.scope { None => base, Some(scope) => base.intersection(scope), @@ -619,7 +621,15 @@ fn found_name_ref( }; sink(file_id, reference) } - Some(NameRefClass::Definition(def)) if def == self.def => { + Some(NameRefClass::Definition(def)) + if match self.trait_assoc_def { + Some(trait_assoc_def) => { + // we have a trait assoc item, so force resolve all assoc items to their trait version + convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def + } + None => self.def == def, + } => + { let FileRange { file_id, range } = self.sema.original_range(name_ref.syntax()); let reference = FileReference { range, @@ -708,30 +718,22 @@ fn found_name( } false } - // Resolve trait impl function definitions to the trait definition's version if self.def is the trait definition's Some(NameClass::Definition(def)) if def != self.def => { - /* poor man's try block */ - (|| { - let this_trait = self - .def - .as_assoc_item(self.sema.db)? - .containing_trait_or_trait_impl(self.sema.db)?; - let trait_ = def - .as_assoc_item(self.sema.db)? - .containing_trait_or_trait_impl(self.sema.db)?; - (trait_ == this_trait && self.def.name(self.sema.db) == def.name(self.sema.db)) - .then(|| { - let FileRange { file_id, range } = - self.sema.original_range(name.syntax()); - let reference = FileReference { - range, - name: ast::NameLike::Name(name.clone()), - category: None, - }; - sink(file_id, reference) - }) - })() - .unwrap_or(false) + // 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 + if !matches!( + self.trait_assoc_def, + Some(trait_assoc_def) + if convert_to_def_in_trait(self.sema.db, def) == trait_assoc_def + ) { + return false; + } + let FileRange { file_id, range } = self.sema.original_range(name.syntax()); + let reference = FileReference { + range, + name: ast::NameLike::Name(name.clone()), + category: None, + }; + sink(file_id, reference) } _ => false, }