@@ -259,49 +259,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
259259 hir. body ( hir. maybe_body_owned_by ( self . body_id ) . expect ( "expected item to have body" ) ) ;
260260 expr_finder. visit_expr ( body. value ) ;
261261
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 ! ( ) ,
294277 }
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+ } ,
302296 } ;
303297
304- if !fudge_equals_found_ty ( init_ty) {
298+ if !self . can_eq ( self . param_env , expected_ty , init_ty. fold_with ( & mut fudger ) ) {
305299 return false ;
306300 }
307301
@@ -317,7 +311,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
317311
318312 // If the type is not constrained in a way making it not possible to
319313 // 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 ) ) {
321315 continue ;
322316 }
323317
@@ -326,26 +320,57 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
326320 && rcvr. hir_id == binding. hir_id
327321 {
328322 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) =
331325 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 ( )
332340 {
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+ ) ;
348372 }
373+ return true ;
349374 }
350375 }
351376
0 commit comments