@@ -451,7 +451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
451
451
call_expr : & ' tcx hir:: Expr < ' tcx > ,
452
452
) -> ErrorGuaranteed {
453
453
// Next, let's construct the error
454
- let ( error_span, full_call_span, call_name, is_method) = match & call_expr. kind {
454
+ let ( error_span, call_ident , full_call_span, call_name, is_method) = match & call_expr. kind {
455
455
hir:: ExprKind :: Call (
456
456
hir:: Expr { hir_id, span, kind : hir:: ExprKind :: Path ( qpath) , .. } ,
457
457
_,
@@ -463,20 +463,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
463
463
CtorOf :: Struct => "struct" ,
464
464
CtorOf :: Variant => "enum variant" ,
465
465
} ;
466
- ( call_span, * span, name, false )
466
+ ( call_span, None , * span, name, false )
467
467
} else {
468
- ( call_span, * span, "function" , false )
468
+ ( call_span, None , * span, "function" , false )
469
469
}
470
470
}
471
- hir:: ExprKind :: Call ( hir:: Expr { span, .. } , _) => ( call_span, * span, "function" , false ) ,
471
+ hir:: ExprKind :: Call ( hir:: Expr { span, .. } , _) => {
472
+ ( call_span, None , * span, "function" , false )
473
+ }
472
474
hir:: ExprKind :: MethodCall ( path_segment, _, _, span) => {
473
475
let ident_span = path_segment. ident . span ;
474
476
let ident_span = if let Some ( args) = path_segment. args {
475
477
ident_span. with_hi ( args. span_ext . hi ( ) )
476
478
} else {
477
479
ident_span
478
480
} ;
479
- ( * span, ident_span, "method" , true )
481
+ ( * span, Some ( path_segment . ident ) , ident_span, "method" , true )
480
482
}
481
483
k => span_bug ! ( call_span, "checking argument types on a non-call: `{:?}`" , k) ,
482
484
} ;
@@ -530,6 +532,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
530
532
let callee_ty = callee_expr
531
533
. and_then ( |callee_expr| self . typeck_results . borrow ( ) . expr_ty_adjusted_opt ( callee_expr) ) ;
532
534
535
+ let suggest_confusable = |err : & mut Diagnostic | {
536
+ if let Some ( call_name) = call_ident
537
+ && let Some ( callee_ty) = callee_ty
538
+ {
539
+ // FIXME: check in the following order
540
+ // - methods marked as `rustc_confusables` with the provided arguments (done)
541
+ // - methods marked as `rustc_confusables` with the right number of arguments
542
+ // - methods marked as `rustc_confusables` (done)
543
+ // - methods with the same argument type/count and short levenshtein distance
544
+ // - methods with short levenshtein distance
545
+ // - methods with the same argument type/count
546
+ self . confusable_method_name (
547
+ err,
548
+ callee_ty. peel_refs ( ) ,
549
+ call_name,
550
+ Some ( provided_arg_tys. iter ( ) . map ( |( ty, _) | * ty) . collect ( ) ) ,
551
+ )
552
+ . or_else ( || {
553
+ self . confusable_method_name ( err, callee_ty. peel_refs ( ) , call_name, None )
554
+ } ) ;
555
+ }
556
+ } ;
533
557
// A "softer" version of the `demand_compatible`, which checks types without persisting them,
534
558
// and treats error types differently
535
559
// This will allow us to "probe" for other argument orders that would likely have been correct
@@ -694,6 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
694
718
Some ( mismatch_idx) ,
695
719
is_method,
696
720
) ;
721
+ suggest_confusable ( & mut err) ;
697
722
return err. emit ( ) ;
698
723
}
699
724
}
@@ -718,7 +743,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
718
743
if cfg ! ( debug_assertions) {
719
744
span_bug ! ( error_span, "expected errors from argument matrix" ) ;
720
745
} else {
721
- return tcx. dcx ( ) . emit_err ( errors:: ArgMismatchIndeterminate { span : error_span } ) ;
746
+ let mut err =
747
+ tcx. dcx ( ) . create_err ( errors:: ArgMismatchIndeterminate { span : error_span } ) ;
748
+ suggest_confusable ( & mut err) ;
749
+ return err. emit ( ) ;
722
750
}
723
751
}
724
752
@@ -733,7 +761,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
733
761
let trace =
734
762
mk_trace ( provided_span, formal_and_expected_inputs[ * expected_idx] , provided_ty) ;
735
763
if !matches ! ( trace. cause. as_failure_code( * e) , FailureCode :: Error0308 ) {
736
- reported = Some ( self . err_ctxt ( ) . report_and_explain_type_error ( trace, * e) . emit ( ) ) ;
764
+ let mut err = self . err_ctxt ( ) . report_and_explain_type_error ( trace, * e) ;
765
+ suggest_confusable ( & mut err) ;
766
+ reported = Some ( err. emit ( ) ) ;
737
767
return false ;
738
768
}
739
769
true
@@ -801,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
801
831
Some ( expected_idx. as_usize ( ) ) ,
802
832
is_method,
803
833
) ;
834
+ suggest_confusable ( & mut err) ;
804
835
return err. emit ( ) ;
805
836
}
806
837
@@ -828,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
828
859
. with_code ( err_code. to_owned ( ) )
829
860
} ;
830
861
862
+ suggest_confusable ( & mut err) ;
831
863
// As we encounter issues, keep track of what we want to provide for the suggestion
832
864
let mut labels = vec ! [ ] ;
833
865
// If there is a single error, we give a specific suggestion; otherwise, we change to
0 commit comments