@@ -21,7 +21,8 @@ use hir_def::{
2121 path:: { ModPath , Path , PathKind } ,
2222 resolver:: { resolver_for_scope, Resolver , TypeNs , ValueNs } ,
2323 type_ref:: Mutability ,
24- AsMacroCall , DefWithBodyId , FieldId , FunctionId , LocalFieldId , Lookup , ModuleDefId , VariantId ,
24+ AsMacroCall , AssocItemId , DefWithBodyId , FieldId , FunctionId , ItemContainerId , LocalFieldId ,
25+ Lookup , ModuleDefId , VariantId ,
2526} ;
2627use hir_expand:: {
2728 builtin_fn_macro:: BuiltinFnLikeExpander , hygiene:: Hygiene , name:: AsName , HirFileId , InFile ,
@@ -31,8 +32,8 @@ use hir_ty::{
3132 record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
3233 UnsafeExpr ,
3334 } ,
34- Adjust , Adjustment , AutoBorrow , InferenceResult , Interner , Substitution , TyExt ,
35- TyLoweringContext ,
35+ method_resolution , Adjust , Adjustment , AutoBorrow , InferenceResult , Interner , Substitution ,
36+ TyExt , TyKind , TyLoweringContext ,
3637} ;
3738use smallvec:: SmallVec ;
3839use syntax:: {
@@ -42,8 +43,8 @@ use syntax::{
4243
4344use crate :: {
4445 db:: HirDatabase , semantics:: PathResolution , Adt , AssocItem , BindingMode , BuiltinAttr ,
45- BuiltinType , Const , Field , Function , Local , Macro , ModuleDef , Static , Struct , ToolModule ,
46- Trait , Type , TypeAlias , Variant ,
46+ BuiltinType , Callable , Const , Field , Function , Local , Macro , ModuleDef , Static , Struct ,
47+ ToolModule , Trait , Type , TypeAlias , Variant ,
4748} ;
4849
4950/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -232,13 +233,29 @@ impl SourceAnalyzer {
232233 )
233234 }
234235
236+ pub ( crate ) fn resolve_method_call_as_callable (
237+ & self ,
238+ db : & dyn HirDatabase ,
239+ call : & ast:: MethodCallExpr ,
240+ ) -> Option < Callable > {
241+ let expr_id = self . expr_id ( db, & call. clone ( ) . into ( ) ) ?;
242+ let ( func, substs) = self . infer . as_ref ( ) ?. method_resolution ( expr_id) ?;
243+ let ty = db. value_ty ( func. into ( ) ) . substitute ( Interner , & substs) ;
244+ let ty = Type :: new_with_resolver ( db, & self . resolver , ty) ;
245+ let mut res = ty. as_callable ( db) ?;
246+ res. is_bound_method = true ;
247+ Some ( res)
248+ }
249+
235250 pub ( crate ) fn resolve_method_call (
236251 & self ,
237252 db : & dyn HirDatabase ,
238253 call : & ast:: MethodCallExpr ,
239- ) -> Option < ( FunctionId , Substitution ) > {
254+ ) -> Option < FunctionId > {
240255 let expr_id = self . expr_id ( db, & call. clone ( ) . into ( ) ) ?;
241- self . infer . as_ref ( ) ?. method_resolution ( expr_id)
256+ let ( f_in_trait, substs) = self . infer . as_ref ( ) ?. method_resolution ( expr_id) ?;
257+ let f_in_impl = self . resolve_impl_method ( db, f_in_trait, & substs) ;
258+ f_in_impl. or ( Some ( f_in_trait) )
242259 }
243260
244261 pub ( crate ) fn resolve_field (
@@ -336,6 +353,25 @@ impl SourceAnalyzer {
336353 let expr_id = self . expr_id ( db, & path_expr. into ( ) ) ?;
337354 let infer = self . infer . as_ref ( ) ?;
338355 if let Some ( assoc) = infer. assoc_resolutions_for_expr ( expr_id) {
356+ let assoc = match assoc {
357+ AssocItemId :: FunctionId ( f_in_trait) => {
358+ match infer. type_of_expr . get ( expr_id) {
359+ None => assoc,
360+ Some ( func_ty) => {
361+ if let TyKind :: FnDef ( _fn_def, subs) = func_ty. kind ( Interner ) {
362+ self . resolve_impl_method ( db, f_in_trait, subs)
363+ . map ( AssocItemId :: FunctionId )
364+ . unwrap_or ( assoc)
365+ } else {
366+ assoc
367+ }
368+ }
369+ }
370+ }
371+
372+ _ => assoc,
373+ } ;
374+
339375 return Some ( PathResolution :: Def ( AssocItem :: from ( assoc) . into ( ) ) ) ;
340376 }
341377 if let Some ( VariantId :: EnumVariantId ( variant) ) =
@@ -563,6 +599,30 @@ impl SourceAnalyzer {
563599 }
564600 false
565601 }
602+
603+ fn resolve_impl_method (
604+ & self ,
605+ db : & dyn HirDatabase ,
606+ func : FunctionId ,
607+ substs : & Substitution ,
608+ ) -> Option < FunctionId > {
609+ let impled_trait = match func. lookup ( db. upcast ( ) ) . container {
610+ ItemContainerId :: TraitId ( trait_id) => trait_id,
611+ _ => return None ,
612+ } ;
613+ if substs. is_empty ( Interner ) {
614+ return None ;
615+ }
616+ let self_ty = substs. at ( Interner , 0 ) . ty ( Interner ) ?;
617+ let krate = self . resolver . krate ( ) ;
618+ let trait_env = self . resolver . body_owner ( ) ?. as_generic_def_id ( ) . map_or_else (
619+ || Arc :: new ( hir_ty:: TraitEnvironment :: empty ( krate) ) ,
620+ |d| db. trait_environment ( d) ,
621+ ) ;
622+
623+ let fun_data = db. function_data ( func) ;
624+ method_resolution:: lookup_impl_method ( self_ty, db, trait_env, impled_trait, & fun_data. name )
625+ }
566626}
567627
568628fn scope_for (
0 commit comments