Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir/src/source_analyzer.rs')
| -rw-r--r-- | crates/hir/src/source_analyzer.rs | 99 |
1 files changed, 48 insertions, 51 deletions
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( |