Unnamed repository; edit this file 'description' to name the repository.
functions resolve to impl
bitgaoshu 2022-06-24
parent 36fadc4 · commit 6ecabe3
-rw-r--r--crates/hir/src/semantics.rs7
-rw-r--r--crates/hir/src/source_analyzer.rs99
-rw-r--r--crates/ide-db/src/defs.rs39
-rw-r--r--crates/ide/src/goto_definition.rs7
4 files changed, 50 insertions, 102 deletions
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index 2574adb35a..aa10b0f878 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -348,9 +348,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
self.imp.resolve_method_call(call).map(Function::from)
}
- pub fn resolve_impl_method(&self, call: &ast::Expr) -> Option<Function> {
- self.imp.resolve_impl_method(call).map(Function::from)
- }
pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
self.imp.resolve_method_call_as_callable(call)
}
@@ -981,10 +978,6 @@ impl<'db> SemanticsImpl<'db> {
self.analyze(call.syntax())?.resolve_method_call(self.db, call).map(|(id, _)| id)
}
- fn resolve_impl_method(&self, call: &ast::Expr) -> Option<FunctionId> {
- self.analyze(call.syntax())?.resolve_impl_method(self.db, call)
- }
-
fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option<Callable> {
let source_analyzer = self.analyze(call.syntax())?;
let (func, subst) = source_analyzer.resolve_method_call(self.db, call)?;
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 62bcc9de39..3faae8fc4b 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -21,8 +21,8 @@ use hir_def::{
path::{ModPath, Path, PathKind},
resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs},
type_ref::Mutability,
- AsMacroCall, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId, Lookup,
- ModuleDefId, VariantId,
+ AsMacroCall, AssocItemId, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId,
+ Lookup, ModuleDefId, VariantId,
};
use hir_expand::{
builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name::AsName, HirFileId, InFile,
@@ -245,55 +245,9 @@ impl SourceAnalyzer {
call: &ast::MethodCallExpr,
) -> Option<(FunctionId, Substitution)> {
let expr_id = self.expr_id(db, &call.clone().into())?;
- self.infer.as_ref()?.method_resolution(expr_id)
- }
-
- pub(crate) fn resolve_impl_method(
- &self,
- db: &dyn HirDatabase,
- call: &ast::Expr,
- ) -> Option<FunctionId> {
- let infered = self.infer.as_ref()?;
- let expr_id = self.expr_id(db, call)?;
-
- let mut fun_info = None;
- match call {
- &ast::Expr::MethodCallExpr(..) => {
- let (func, subs) = infered.method_resolution(expr_id)?;
- if subs.is_empty(Interner) {
- return None;
- }
- fun_info.replace((func, subs.at(Interner, 0).ty(Interner)?.clone()));
- }
- &ast::Expr::PathExpr(..) => {
- let func_ty = infered.type_of_expr.get(expr_id)?;
- if let TyKind::FnDef(fn_def, subs) = func_ty.kind(Interner) {
- if subs.is_empty(Interner) {
- return None;
- }
- if let hir_ty::CallableDefId::FunctionId(f_id) =
- db.lookup_intern_callable_def(fn_def.clone().into())
- {
- fun_info.replace((f_id, subs.at(Interner, 0).ty(Interner)?.clone()));
- }
- }
- }
- _ => (),
- };
- let (func, self_ty) = fun_info?;
- let impled_trait = match func.lookup(db.upcast()).container {
- ItemContainerId::TraitId(trait_id) => trait_id,
- _ => return None,
- };
-
- let krate = self.resolver.krate();
- let trait_env = self.resolver.body_owner()?.as_generic_def_id().map_or_else(
- || Arc::new(hir_ty::TraitEnvironment::empty(krate)),
- |d| db.trait_environment(d),
- );
-
- let fun_data = db.function_data(func);
- method_resolution::lookup_impl_method(&self_ty, db, trait_env, impled_trait, &fun_data.name)
+ let (f_in_trait, substs) = self.infer.as_ref()?.method_resolution(expr_id)?;
+ let f_in_impl = self.resolve_impl_method(db, f_in_trait, &substs);
+ Some((f_in_impl.unwrap_or(f_in_trait), substs))
}
pub(crate) fn resolve_field(
@@ -391,6 +345,25 @@ impl SourceAnalyzer {
let expr_id = self.expr_id(db, &path_expr.into())?;
let infer = self.infer.as_ref()?;
if let Some(assoc) = infer.assoc_resolutions_for_expr(expr_id) {
+ let assoc = match assoc {
+ AssocItemId::FunctionId(f_in_trait) => {
+ match infer.type_of_expr.get(expr_id) {
+ None => assoc,
+ Some(func_ty) => {
+ if let TyKind::FnDef(_fn_def, subs) = func_ty.kind(Interner) {
+ self.resolve_impl_method(db, f_in_trait, subs)
+ .map(AssocItemId::FunctionId)
+ .unwrap_or(assoc)
+ } else {
+ assoc
+ }
+ }
+ }
+ }
+
+ _ => assoc,
+ };
+
return Some(PathResolution::Def(AssocItem::from(assoc).into()));
}
if let Some(VariantId::EnumVariantId(variant)) =
@@ -616,6 +589,30 @@ impl SourceAnalyzer {
}
false
}
+
+ fn resolve_impl_method(
+ &self,
+ db: &dyn HirDatabase,
+ func: FunctionId,
+ substs: &Substitution,
+ ) -> Option<FunctionId> {
+ let impled_trait = match func.lookup(db.upcast()).container {
+ ItemContainerId::TraitId(trait_id) => trait_id,
+ _ => return None,
+ };
+ if substs.is_empty(Interner) {
+ return None;
+ }
+ let self_ty = substs.at(Interner, 0).ty(Interner)?;
+ let krate = self.resolver.krate();
+ let trait_env = self.resolver.body_owner()?.as_generic_def_id().map_or_else(
+ || Arc::new(hir_ty::TraitEnvironment::empty(krate)),
+ |d| db.trait_environment(d),
+ );
+
+ let fun_data = db.function_data(func);
+ method_resolution::lookup_impl_method(self_ty, db, trait_env, impled_trait, &fun_data.name)
+ }
}
fn scope_for(
diff --git a/crates/ide-db/src/defs.rs b/crates/ide-db/src/defs.rs
index 2b1e8e325e..540cc70dd5 100644
--- a/crates/ide-db/src/defs.rs
+++ b/crates/ide-db/src/defs.rs
@@ -162,22 +162,6 @@ impl IdentClass {
.or_else(|| NameClass::classify_lifetime(sema, lifetime).map(IdentClass::NameClass))
}
- pub fn classify_token_to_impl(
- sema: &Semantics<RootDatabase>,
- token: &SyntaxToken,
- ) -> Option<Definition> {
- let p = token.parent()?;
- match_ast! {
- match p {
- ast::NameRef(name_ref) => match NameRefClass::classify_to_impl(sema, name_ref)? {
- NameRefClass::Definition(d) => Some(d),
- _ => None,
- },
- _ => None,
- }
- }
- }
-
pub fn definitions(self) -> ArrayVec<Definition, 2> {
let mut res = ArrayVec::new();
match self {
@@ -433,29 +417,6 @@ impl NameRefClass {
}
}
- fn classify_to_impl(
- sema: &Semantics<RootDatabase>,
- name_ref: ast::NameRef,
- ) -> Option<NameRefClass> {
- let parent = name_ref.syntax().parent()?;
- let expr = match_ast! {
- match parent {
- ast::MethodCallExpr(method_call) => {
- Some(ast::Expr::MethodCallExpr(method_call))
- },
- ast::PathSegment(..) => {
- parent.ancestors()
- .find_map(ast::PathExpr::cast)
- .map(ast::Expr::PathExpr)
- },
- _=> None
- }
- };
- expr.as_ref()
- .and_then(|e| sema.resolve_impl_method(e))
- .map(Definition::Function)
- .map(NameRefClass::Definition)
- }
pub fn classify_lifetime(
sema: &Semantics<RootDatabase>,
lifetime: &ast::Lifetime,
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index c3afe14fa3..e44b5020c3 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -65,7 +65,7 @@ pub(crate) fn goto_definition(
.definitions()
.into_iter()
.flat_map(|def| {
- try_filter_trait_item_definition(sema, &def, &token)
+ try_filter_trait_item_definition(sema, &def)
.unwrap_or_else(|| def_to_nav(sema.db, def))
})
.collect(),
@@ -114,14 +114,11 @@ fn try_lookup_include_path(
fn try_filter_trait_item_definition(
sema: &Semantics<RootDatabase>,
def: &Definition,
- token: &SyntaxToken,
) -> Option<Vec<NavigationTarget>> {
let db = sema.db;
let assoc = def.as_assoc_item(db)?;
match assoc {
- AssocItem::Function(..) => {
- IdentClass::classify_token_to_impl(sema, &token).map(|def| def_to_nav(db, def))
- }
+ AssocItem::Function(..) => None,
AssocItem::Const(..) | AssocItem::TypeAlias(..) => {
let imp = match assoc.container(db) {
hir::AssocItemContainer::Impl(imp) => imp,