@@ -21,7 +21,8 @@ use hir_def::{
21
21
path:: { ModPath , Path , PathKind } ,
22
22
resolver:: { resolver_for_scope, Resolver , TypeNs , ValueNs } ,
23
23
type_ref:: Mutability ,
24
- AsMacroCall , DefWithBodyId , FieldId , FunctionId , LocalFieldId , Lookup , ModuleDefId , VariantId ,
24
+ AsMacroCall , AssocItemId , DefWithBodyId , FieldId , FunctionId , ItemContainerId , LocalFieldId ,
25
+ Lookup , ModuleDefId , VariantId ,
25
26
} ;
26
27
use hir_expand:: {
27
28
builtin_fn_macro:: BuiltinFnLikeExpander , hygiene:: Hygiene , name:: AsName , HirFileId , InFile ,
@@ -31,8 +32,8 @@ use hir_ty::{
31
32
record_literal_missing_fields, record_pattern_missing_fields, unsafe_expressions,
32
33
UnsafeExpr ,
33
34
} ,
34
- Adjust , Adjustment , AutoBorrow , InferenceResult , Interner , Substitution , TyExt ,
35
- TyLoweringContext ,
35
+ method_resolution , Adjust , Adjustment , AutoBorrow , InferenceResult , Interner , Substitution ,
36
+ TyExt , TyKind , TyLoweringContext ,
36
37
} ;
37
38
use smallvec:: SmallVec ;
38
39
use syntax:: {
@@ -42,8 +43,8 @@ use syntax::{
42
43
43
44
use crate :: {
44
45
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 ,
47
48
} ;
48
49
49
50
/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
@@ -232,13 +233,29 @@ impl SourceAnalyzer {
232
233
)
233
234
}
234
235
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
+
235
250
pub ( crate ) fn resolve_method_call (
236
251
& self ,
237
252
db : & dyn HirDatabase ,
238
253
call : & ast:: MethodCallExpr ,
239
- ) -> Option < ( FunctionId , Substitution ) > {
254
+ ) -> Option < FunctionId > {
240
255
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) )
242
259
}
243
260
244
261
pub ( crate ) fn resolve_field (
@@ -336,6 +353,25 @@ impl SourceAnalyzer {
336
353
let expr_id = self . expr_id ( db, & path_expr. into ( ) ) ?;
337
354
let infer = self . infer . as_ref ( ) ?;
338
355
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
+
339
375
return Some ( PathResolution :: Def ( AssocItem :: from ( assoc) . into ( ) ) ) ;
340
376
}
341
377
if let Some ( VariantId :: EnumVariantId ( variant) ) =
@@ -563,6 +599,30 @@ impl SourceAnalyzer {
563
599
}
564
600
false
565
601
}
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
+ }
566
626
}
567
627
568
628
fn scope_for (
0 commit comments