@@ -11,7 +11,6 @@ use rustc_hir::{
11
11
Expr , ExprKind , GenericBound , Node , Path , QPath , Stmt , StmtKind , TyKind , WherePredicate ,
12
12
} ;
13
13
use rustc_hir_analysis:: astconv:: AstConv ;
14
- use rustc_infer:: infer;
15
14
use rustc_infer:: traits:: { self , StatementAsExpression } ;
16
15
use rustc_middle:: lint:: in_external_macro;
17
16
use rustc_middle:: ty:: {
@@ -23,9 +22,9 @@ use rustc_span::source_map::Spanned;
23
22
use rustc_span:: symbol:: { sym, Ident } ;
24
23
use rustc_span:: { Span , Symbol } ;
25
24
use rustc_trait_selection:: infer:: InferCtxtExt ;
25
+ use rustc_trait_selection:: traits:: error_reporting:: suggestions:: TypeErrCtxtExt ;
26
26
use rustc_trait_selection:: traits:: error_reporting:: DefIdOrName ;
27
27
use rustc_trait_selection:: traits:: query:: evaluate_obligation:: InferCtxtExt as _;
28
- use rustc_trait_selection:: traits:: NormalizeExt ;
29
28
30
29
impl < ' a , ' tcx > FnCtxt < ' a , ' tcx > {
31
30
pub ( crate ) fn body_fn_sig ( & self ) -> Option < ty:: FnSig < ' tcx > > {
@@ -94,7 +93,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
94
93
found : Ty < ' tcx > ,
95
94
can_satisfy : impl FnOnce ( Ty < ' tcx > ) -> bool ,
96
95
) -> bool {
97
- let Some ( ( def_id_or_name, output, inputs) ) = self . extract_callable_info ( expr , found)
96
+ let Some ( ( def_id_or_name, output, inputs) ) = self . extract_callable_info ( found)
98
97
else { return false ; } ;
99
98
if can_satisfy ( output) {
100
99
let ( sugg_call, mut applicability) = match inputs. len ( ) {
@@ -163,99 +162,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
163
162
/// because the callable type must also be well-formed to be called.
164
163
pub ( in super :: super ) fn extract_callable_info (
165
164
& self ,
166
- expr : & Expr < ' _ > ,
167
- found : Ty < ' tcx > ,
165
+ ty : Ty < ' tcx > ,
168
166
) -> Option < ( DefIdOrName , Ty < ' tcx > , Vec < Ty < ' tcx > > ) > {
169
- // Autoderef is useful here because sometimes we box callables, etc.
170
- let Some ( ( def_id_or_name, output, inputs) ) = self . autoderef ( expr. span , found) . silence_errors ( ) . find_map ( |( found, _) | {
171
- match * found. kind ( ) {
172
- ty:: FnPtr ( fn_sig) =>
173
- Some ( ( DefIdOrName :: Name ( "function pointer" ) , fn_sig. output ( ) , fn_sig. inputs ( ) ) ) ,
174
- ty:: FnDef ( def_id, _) => {
175
- let fn_sig = found. fn_sig ( self . tcx ) ;
176
- Some ( ( DefIdOrName :: DefId ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) ) )
177
- }
178
- ty:: Closure ( def_id, substs) => {
179
- let fn_sig = substs. as_closure ( ) . sig ( ) ;
180
- Some ( ( DefIdOrName :: DefId ( def_id) , fn_sig. output ( ) , fn_sig. inputs ( ) . map_bound ( |inputs| & inputs[ 1 ..] ) ) )
181
- }
182
- ty:: Alias ( ty:: Opaque , ty:: AliasTy { def_id, substs, .. } ) => {
183
- self . tcx . bound_item_bounds ( def_id) . subst ( self . tcx , substs) . iter ( ) . find_map ( |pred| {
184
- if let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj) ) = pred. kind ( ) . skip_binder ( )
185
- && Some ( proj. projection_ty . def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
186
- // args tuple will always be substs[1]
187
- && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
188
- {
189
- Some ( (
190
- DefIdOrName :: DefId ( def_id) ,
191
- pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
192
- pred. kind ( ) . rebind ( args. as_slice ( ) ) ,
193
- ) )
194
- } else {
195
- None
196
- }
197
- } )
198
- }
199
- ty:: Dynamic ( data, _, ty:: Dyn ) => {
200
- data. iter ( ) . find_map ( |pred| {
201
- if let ty:: ExistentialPredicate :: Projection ( proj) = pred. skip_binder ( )
202
- && Some ( proj. def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
203
- // for existential projection, substs are shifted over by 1
204
- && let ty:: Tuple ( args) = proj. substs . type_at ( 0 ) . kind ( )
205
- {
206
- Some ( (
207
- DefIdOrName :: Name ( "trait object" ) ,
208
- pred. rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
209
- pred. rebind ( args. as_slice ( ) ) ,
210
- ) )
211
- } else {
212
- None
213
- }
214
- } )
215
- }
216
- ty:: Param ( param) => {
217
- let def_id = self . tcx . generics_of ( self . body_id . owner ) . type_param ( & param, self . tcx ) . def_id ;
218
- self . tcx . predicates_of ( self . body_id . owner ) . predicates . iter ( ) . find_map ( |( pred, _) | {
219
- if let ty:: PredicateKind :: Clause ( ty:: Clause :: Projection ( proj) ) = pred. kind ( ) . skip_binder ( )
220
- && Some ( proj. projection_ty . def_id ) == self . tcx . lang_items ( ) . fn_once_output ( )
221
- && proj. projection_ty . self_ty ( ) == found
222
- // args tuple will always be substs[1]
223
- && let ty:: Tuple ( args) = proj. projection_ty . substs . type_at ( 1 ) . kind ( )
224
- {
225
- Some ( (
226
- DefIdOrName :: DefId ( def_id) ,
227
- pred. kind ( ) . rebind ( proj. term . ty ( ) . unwrap ( ) ) ,
228
- pred. kind ( ) . rebind ( args. as_slice ( ) ) ,
229
- ) )
230
- } else {
231
- None
232
- }
233
- } )
234
- }
235
- _ => None ,
236
- }
237
- } ) else { return None ; } ;
238
-
239
- let output = self . replace_bound_vars_with_fresh_vars ( expr. span , infer:: FnCall , output) ;
240
- let inputs = inputs
241
- . skip_binder ( )
242
- . iter ( )
243
- . map ( |ty| {
244
- self . replace_bound_vars_with_fresh_vars (
245
- expr. span ,
246
- infer:: FnCall ,
247
- inputs. rebind ( * ty) ,
248
- )
249
- } )
250
- . collect ( ) ;
251
-
252
- // We don't want to register any extra obligations, which should be
253
- // implied by wf, but also because that would possibly result in
254
- // erroneous errors later on.
255
- let infer:: InferOk { value : output, obligations : _ } =
256
- self . at ( & self . misc ( expr. span ) , self . param_env ) . normalize ( output) ;
257
-
258
- if output. is_ty_var ( ) { None } else { Some ( ( def_id_or_name, output, inputs) ) }
167
+ self . err_ctxt ( ) . extract_callable_info ( self . body_id , self . param_env , ty)
259
168
}
260
169
261
170
pub fn suggest_two_fn_call (
@@ -267,9 +176,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
267
176
rhs_ty : Ty < ' tcx > ,
268
177
can_satisfy : impl FnOnce ( Ty < ' tcx > , Ty < ' tcx > ) -> bool ,
269
178
) -> bool {
270
- let Some ( ( _, lhs_output_ty, lhs_inputs) ) = self . extract_callable_info ( lhs_expr , lhs_ty)
179
+ let Some ( ( _, lhs_output_ty, lhs_inputs) ) = self . extract_callable_info ( lhs_ty)
271
180
else { return false ; } ;
272
- let Some ( ( _, rhs_output_ty, rhs_inputs) ) = self . extract_callable_info ( rhs_expr , rhs_ty)
181
+ let Some ( ( _, rhs_output_ty, rhs_inputs) ) = self . extract_callable_info ( rhs_ty)
273
182
else { return false ; } ;
274
183
275
184
if can_satisfy ( lhs_output_ty, rhs_output_ty) {
0 commit comments