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 | 61 |
1 files changed, 58 insertions, 3 deletions
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs index d624d37577..4d8d6a1460 100644 --- a/crates/hir/src/source_analyzer.rs +++ b/crates/hir/src/source_analyzer.rs @@ -21,7 +21,8 @@ use hir_def::{ path::{ModPath, Path, PathKind}, resolver::{resolver_for_scope, Resolver, TypeNs, ValueNs}, type_ref::Mutability, - AsMacroCall, DefWithBodyId, FieldId, FunctionId, LocalFieldId, Lookup, ModuleDefId, VariantId, + AsMacroCall, DefWithBodyId, FieldId, FunctionId, ItemContainerId, LocalFieldId, Lookup, + ModuleDefId, VariantId, }; use hir_expand::{ builtin_fn_macro::BuiltinFnLikeExpander, hygiene::Hygiene, name::AsName, HirFileId, InFile, @@ -31,8 +32,8 @@ use hir_ty::{ record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions, UnsafeExpr, }, - Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution, TyExt, - TyLoweringContext, + method_resolution, Adjust, Adjustment, AutoBorrow, InferenceResult, Interner, Substitution, + TyExt, TyKind, TyLoweringContext, }; use smallvec::SmallVec; use syntax::{ @@ -247,6 +248,60 @@ impl SourceAnalyzer { 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 implied_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_trait_m_for_self_ty( + &self_ty, + db, + trait_env, + implied_trait, + &fun_data.name, + ) + } + pub(crate) fn resolve_field( &self, db: &dyn HirDatabase, |