@@ -259,49 +259,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259
259
hir. body ( hir. maybe_body_owned_by ( self . body_id ) . expect ( "expected item to have body" ) ) ;
260
260
expr_finder. visit_expr ( body. value ) ;
261
261
262
- let fudge_ty = |ty : Ty < ' tcx > | {
263
- use rustc_infer:: infer:: type_variable:: * ;
264
- use rustc_middle:: infer:: unify_key:: * ;
265
- ty. fold_with ( & mut BottomUpFolder {
266
- tcx : self . tcx ,
267
- ty_op : |ty| {
268
- if let ty:: Infer ( infer) = ty. kind ( ) {
269
- match infer {
270
- ty:: InferTy :: TyVar ( _) => self . next_ty_var ( TypeVariableOrigin {
271
- kind : TypeVariableOriginKind :: MiscVariable ,
272
- span : DUMMY_SP ,
273
- } ) ,
274
- ty:: InferTy :: IntVar ( _) => self . next_int_var ( ) ,
275
- ty:: InferTy :: FloatVar ( _) => self . next_float_var ( ) ,
276
- _ => bug ! ( ) ,
277
- }
278
- } else {
279
- ty
280
- }
281
- } ,
282
- lt_op : |_| self . tcx . lifetimes . re_erased ,
283
- ct_op : |ct| {
284
- if let ty:: ConstKind :: Infer ( _) = ct. kind ( ) {
285
- self . next_const_var (
286
- ct. ty ( ) ,
287
- ConstVariableOrigin {
288
- kind : ConstVariableOriginKind :: MiscVariable ,
289
- span : DUMMY_SP ,
290
- } ,
291
- )
292
- } else {
293
- ct
262
+ use rustc_infer:: infer:: type_variable:: * ;
263
+ use rustc_middle:: infer:: unify_key:: * ;
264
+
265
+ let mut fudger = BottomUpFolder {
266
+ tcx : self . tcx ,
267
+ ty_op : |ty| {
268
+ if let ty:: Infer ( infer) = ty. kind ( ) {
269
+ match infer {
270
+ ty:: InferTy :: TyVar ( _) => self . next_ty_var ( TypeVariableOrigin {
271
+ kind : TypeVariableOriginKind :: MiscVariable ,
272
+ span : DUMMY_SP ,
273
+ } ) ,
274
+ ty:: InferTy :: IntVar ( _) => self . next_int_var ( ) ,
275
+ ty:: InferTy :: FloatVar ( _) => self . next_float_var ( ) ,
276
+ _ => bug ! ( ) ,
294
277
}
295
- } ,
296
- } )
297
- } ;
298
-
299
- let fudge_equals_found_ty = |use_ty : Ty < ' tcx > | {
300
- let use_ty = fudge_ty ( use_ty) ;
301
- self . can_eq ( self . param_env , expected_ty, use_ty)
278
+ } else {
279
+ ty
280
+ }
281
+ } ,
282
+ lt_op : |_| self . tcx . lifetimes . re_erased ,
283
+ ct_op : |ct| {
284
+ if let ty:: ConstKind :: Infer ( _) = ct. kind ( ) {
285
+ self . next_const_var (
286
+ ct. ty ( ) ,
287
+ ConstVariableOrigin {
288
+ kind : ConstVariableOriginKind :: MiscVariable ,
289
+ span : DUMMY_SP ,
290
+ } ,
291
+ )
292
+ } else {
293
+ ct
294
+ }
295
+ } ,
302
296
} ;
303
297
304
- if !fudge_equals_found_ty ( init_ty) {
298
+ if !self . can_eq ( self . param_env , expected_ty , init_ty. fold_with ( & mut fudger ) ) {
305
299
return false ;
306
300
}
307
301
@@ -317,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
317
311
318
312
// If the type is not constrained in a way making it not possible to
319
313
// equate with `expected_ty` by this point, skip.
320
- if fudge_equals_found_ty ( next_use_ty) {
314
+ if self . can_eq ( self . param_env , expected_ty , next_use_ty. fold_with ( & mut fudger ) ) {
321
315
continue ;
322
316
}
323
317
@@ -326,26 +320,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
326
320
&& rcvr. hir_id == binding. hir_id
327
321
{
328
322
let Some ( rcvr_ty) = self . node_ty_opt ( rcvr. hir_id ) else { continue ; } ;
329
- let rcvr_ty = fudge_ty ( rcvr_ty) ;
330
- if let Ok ( method) =
323
+ let rcvr_ty = rcvr_ty. fold_with ( & mut fudger ) ;
324
+ let Ok ( method) =
331
325
self . lookup_method ( rcvr_ty, segment, DUMMY_SP , parent_expr, rcvr, args)
326
+ else {
327
+ continue ;
328
+ } ;
329
+
330
+ // NOTE: For future removers of `fudge_inference_if_ok`, you
331
+ // can replace this with another call to `lookup_method` but
332
+ // using `expected_ty` as the rcvr.
333
+ let ideal_method_sig: Result < _ , TypeError < ' tcx > > = self . fudge_inference_if_ok ( || {
334
+ let _ = self . at ( & ObligationCause :: dummy ( ) , self . param_env ) . eq ( rcvr_ty, expected_ty) ?;
335
+ Ok ( method. sig )
336
+ } ) ;
337
+
338
+ for ( idx, ( expected_arg_ty, arg_expr) ) in
339
+ std:: iter:: zip ( & method. sig . inputs ( ) [ 1 ..] , args) . enumerate ( )
332
340
{
333
- for ( expected_arg_ty, arg_expr) in std:: iter:: zip ( & method. sig . inputs ( ) [ 1 ..] , args) {
334
- let Some ( arg_ty) = self . node_ty_opt ( arg_expr. hir_id ) else { continue ; } ;
335
- let arg_ty = fudge_ty ( arg_ty) ;
336
- let _ = self . try_coerce ( arg_expr, arg_ty, * expected_arg_ty, AllowTwoPhase :: No , None ) ;
337
- if !self . can_eq ( self . param_env , rcvr_ty, expected_ty) {
338
- err. span_label (
339
- arg_expr. span ,
340
- format ! ( "this argument has type `{arg_ty}`..." )
341
- ) ;
342
- err. span_label (
343
- binding. span ,
344
- format ! ( "... which constrains `{ident}` to have type `{next_use_ty}`" )
345
- ) ;
346
- return true ;
347
- }
341
+ let Some ( arg_ty) = self . node_ty_opt ( arg_expr. hir_id ) else { continue ; } ;
342
+ let arg_ty = arg_ty. fold_with ( & mut fudger) ;
343
+ let _ = self . try_coerce (
344
+ arg_expr,
345
+ arg_ty,
346
+ * expected_arg_ty,
347
+ AllowTwoPhase :: No ,
348
+ None ,
349
+ ) ;
350
+ if self . can_eq ( self . param_env , rcvr_ty, expected_ty) {
351
+ continue ;
352
+ }
353
+ err. span_label (
354
+ arg_expr. span ,
355
+ format ! ( "this argument has type `{arg_ty}`..." ) ,
356
+ ) ;
357
+ err. span_label (
358
+ binding. span ,
359
+ format ! (
360
+ "... which constrains `{ident}` to have type `{next_use_ty}`"
361
+ ) ,
362
+ ) ;
363
+ if let Ok ( ideal_method_sig) = ideal_method_sig {
364
+ self . emit_type_mismatch_suggestions (
365
+ err,
366
+ arg_expr,
367
+ arg_ty,
368
+ ideal_method_sig. inputs ( ) [ idx + 1 ] ,
369
+ None ,
370
+ None ,
371
+ ) ;
348
372
}
373
+ return true ;
349
374
}
350
375
}
351
376
0 commit comments