@@ -15,10 +15,10 @@ use ra_syntax::ast::RangeOp;
15
15
16
16
use crate :: {
17
17
autoderef, method_resolution, op,
18
- traits:: { FnTrait , InEnvironment , SolutionVariables } ,
18
+ traits:: { FnTrait , Guidance , InEnvironment , SolutionVariables } ,
19
19
utils:: { generics, variant_data, Generics } ,
20
- ApplicationTy , Binders , CallableDef , FnSig , InferTy , IntTy , Mutability , Obligation , Rawness ,
21
- Substs , TraitRef , Ty , TypeCtor ,
20
+ ApplicationTy , Binders , CallableDef , InferTy , IntTy , Mutability , Obligation , Rawness , Substs ,
21
+ TraitRef , Ty , TypeCtor ,
22
22
} ;
23
23
24
24
use super :: {
@@ -63,72 +63,70 @@ impl<'a> InferenceContext<'a> {
63
63
self . resolve_ty_as_possible ( ty)
64
64
}
65
65
66
- fn callable_sig_from_fn_trait ( & mut self , ty : & Ty ) -> Option < FnSig > {
67
- if let Some ( krate) = self . resolver . krate ( ) {
68
- let fn_traits: Vec < crate :: TraitId > = [ FnTrait :: FnOnce , FnTrait :: FnMut , FnTrait :: Fn ]
69
- . iter ( )
70
- . filter_map ( |f| f. get_id ( self . db , krate) )
71
- . collect ( ) ;
72
- for fn_trait in fn_traits {
73
- let fn_trait_data = self . db . trait_data ( fn_trait) ;
74
- let generic_params = generics ( self . db . upcast ( ) , fn_trait. into ( ) ) ;
75
- if generic_params. len ( ) != 2 {
76
- continue ;
77
- }
78
-
79
- let arg_ty = self . table . new_type_var ( ) ;
80
- let substs = Substs :: build_for_generics ( & generic_params)
81
- . push ( ty. clone ( ) )
82
- . push ( arg_ty. clone ( ) )
83
- . build ( ) ;
84
-
85
- let trait_ref = TraitRef { trait_ : fn_trait, substs : substs. clone ( ) } ;
86
- let trait_env = Arc :: clone ( & self . trait_env ) ;
87
- let implements_fn_goal =
88
- self . canonicalizer ( ) . canonicalize_obligation ( InEnvironment {
89
- value : Obligation :: Trait ( trait_ref) ,
90
- environment : trait_env,
91
- } ) ;
92
- if let Some ( Solution :: Unique ( SolutionVariables ( solution) ) ) =
93
- self . db . trait_solve ( krate, implements_fn_goal. value . clone ( ) )
94
- {
95
- match solution. value . as_slice ( ) {
96
- [ Ty :: Apply ( ApplicationTy {
97
- ctor : TypeCtor :: Tuple { cardinality : _ } ,
98
- parameters,
99
- } ) ] => {
100
- let output_assoc_type = match fn_trait_data
101
- . associated_types ( )
102
- . collect :: < Vec < hir_def:: TypeAliasId > > ( )
103
- . as_slice ( )
104
- {
105
- [ output] => * output,
106
- _ => {
107
- continue ;
108
- }
109
- } ;
110
- let output_proj_ty = crate :: ProjectionTy {
111
- associated_ty : output_assoc_type,
112
- parameters : substs,
113
- } ;
114
- let return_ty = self . normalize_projection_ty ( output_proj_ty) ;
115
- return Some ( FnSig :: from_params_and_return (
116
- parameters. into_iter ( ) . map ( |ty| ty. clone ( ) ) . collect ( ) ,
117
- return_ty,
118
- ) ) ;
119
- }
120
- _ => ( ) ,
121
- }
122
- }
66
+ fn callable_sig_from_fn_trait ( & mut self , ty : & Ty , num_args : usize ) -> Option < ( Vec < Ty > , Ty ) > {
67
+ let krate = self . resolver . krate ( ) ?;
68
+ let fn_traits: Vec < crate :: TraitId > = [ FnTrait :: FnOnce , FnTrait :: FnMut , FnTrait :: Fn ]
69
+ . iter ( )
70
+ . filter_map ( |f| f. get_id ( self . db , krate) )
71
+ . collect ( ) ;
72
+ let fn_once_trait = FnTrait :: FnOnce . get_id ( self . db , krate) ?;
73
+ let output_assoc_type = match self
74
+ . db
75
+ . trait_data ( fn_once_trait)
76
+ . associated_types ( )
77
+ . collect :: < Vec < hir_def:: TypeAliasId > > ( )
78
+ . as_slice ( )
79
+ {
80
+ [ output] => * output,
81
+ _ => {
82
+ return None ;
123
83
}
124
84
} ;
85
+ for fn_trait in fn_traits {
86
+ let generic_params = generics ( self . db . upcast ( ) , fn_trait. into ( ) ) ;
87
+ if generic_params. len ( ) != 2 {
88
+ continue ;
89
+ }
90
+
91
+ let mut param_builder = Substs :: builder ( num_args) ;
92
+ for _ in 0 ..num_args {
93
+ param_builder = param_builder. push ( self . table . new_type_var ( ) ) ;
94
+ }
95
+ let arg_ty = Ty :: Apply ( ApplicationTy {
96
+ ctor : TypeCtor :: Tuple { cardinality : num_args as u16 } ,
97
+ parameters : param_builder. build ( ) ,
98
+ } ) ;
99
+ let substs = Substs :: build_for_generics ( & generic_params)
100
+ . push ( ty. clone ( ) )
101
+ . push ( arg_ty. clone ( ) )
102
+ . build ( ) ;
103
+
104
+ let trait_ref = TraitRef { trait_ : fn_trait, substs : substs. clone ( ) } ;
105
+ let trait_env = Arc :: clone ( & self . trait_env ) ;
106
+ let implements_fn_goal = self . canonicalizer ( ) . canonicalize_obligation ( InEnvironment {
107
+ value : Obligation :: Trait ( trait_ref) ,
108
+ environment : trait_env,
109
+ } ) ;
110
+ let solution = match self . db . trait_solve ( krate, implements_fn_goal. value . clone ( ) ) {
111
+ Some ( Solution :: Unique ( SolutionVariables ( solution) ) )
112
+ | Some ( Solution :: Ambig ( Guidance :: Definite ( SolutionVariables ( solution) ) ) )
113
+ | Some ( Solution :: Ambig ( Guidance :: Suggested ( SolutionVariables ( solution) ) ) ) => {
114
+ solution
115
+ }
116
+ _ => continue ,
117
+ } ;
118
+ let output_proj_ty =
119
+ crate :: ProjectionTy { associated_ty : output_assoc_type, parameters : substs } ;
120
+ let return_ty = self . normalize_projection_ty ( output_proj_ty) ;
121
+ return Some ( ( solution. value , return_ty) ) ;
122
+ }
125
123
None
126
124
}
127
125
128
- pub fn callable_sig ( & mut self , ty : & Ty ) -> Option < FnSig > {
126
+ pub fn callable_sig ( & mut self , ty : & Ty , num_args : usize ) -> Option < ( Vec < Ty > , Ty ) > {
129
127
match ty. callable_sig ( self . db ) {
130
- result @ Some ( _ ) => result ,
131
- None => self . callable_sig_from_fn_trait ( ty) ,
128
+ Some ( sig ) => Some ( ( sig . params ( ) . to_vec ( ) , sig . ret ( ) . clone ( ) ) ) ,
129
+ None => self . callable_sig_from_fn_trait ( ty, num_args ) ,
132
130
}
133
131
}
134
132
@@ -278,8 +276,10 @@ impl<'a> InferenceContext<'a> {
278
276
) ;
279
277
let ( param_tys, ret_ty) : ( Vec < Ty > , Ty ) = derefs
280
278
. find_map ( |callee_deref_ty| {
281
- self . callable_sig ( & canonicalized. decanonicalize_ty ( callee_deref_ty. value ) )
282
- . map ( |sig| ( sig. params ( ) . to_vec ( ) , sig. ret ( ) . clone ( ) ) )
279
+ self . callable_sig (
280
+ & canonicalized. decanonicalize_ty ( callee_deref_ty. value ) ,
281
+ args. len ( ) ,
282
+ )
283
283
} )
284
284
. unwrap_or ( ( Vec :: new ( ) , Ty :: Unknown ) ) ;
285
285
self . register_obligations_for_call ( & callee_ty) ;
0 commit comments