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 { - self.imp.resolve_impl_method(call).map(Function::from) - } pub fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option { 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 { - self.analyze(call.syntax())?.resolve_impl_method(self.db, call) - } - fn resolve_method_call_as_callable(&self, call: &ast::MethodCallExpr) -> Option { 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 { - 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 { + 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, - token: &SyntaxToken, - ) -> Option { - 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 { let mut res = ArrayVec::new(); match self { @@ -433,29 +417,6 @@ impl NameRefClass { } } - fn classify_to_impl( - sema: &Semantics, - name_ref: ast::NameRef, - ) -> Option { - 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, 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, def: &Definition, - token: &SyntaxToken, ) -> Option> { 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,