@@ -451,7 +451,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
451451 call_expr : & ' tcx hir:: Expr < ' tcx > ,
452452 ) -> ErrorGuaranteed {
453453 // 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 {
455455 hir:: ExprKind :: Call (
456456 hir:: Expr { hir_id, span, kind : hir:: ExprKind :: Path ( qpath) , .. } ,
457457 _,
@@ -463,20 +463,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
463463 CtorOf :: Struct => "struct" ,
464464 CtorOf :: Variant => "enum variant" ,
465465 } ;
466- ( call_span, * span, name, false )
466+ ( call_span, None , * span, name, false )
467467 } else {
468- ( call_span, * span, "function" , false )
468+ ( call_span, None , * span, "function" , false )
469469 }
470470 }
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+ }
472474 hir:: ExprKind :: MethodCall ( path_segment, _, _, span) => {
473475 let ident_span = path_segment. ident . span ;
474476 let ident_span = if let Some ( args) = path_segment. args {
475477 ident_span. with_hi ( args. span_ext . hi ( ) )
476478 } else {
477479 ident_span
478480 } ;
479- ( * span, ident_span, "method" , true )
481+ ( * span, Some ( path_segment . ident ) , ident_span, "method" , true )
480482 }
481483 k => span_bug ! ( call_span, "checking argument types on a non-call: `{:?}`" , k) ,
482484 } ;
@@ -530,6 +532,28 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
530532 let callee_ty = callee_expr
531533 . and_then ( |callee_expr| self . typeck_results . borrow ( ) . expr_ty_adjusted_opt ( callee_expr) ) ;
532534
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+ } ;
533557 // A "softer" version of the `demand_compatible`, which checks types without persisting them,
534558 // and treats error types differently
535559 // 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> {
694718 Some ( mismatch_idx) ,
695719 is_method,
696720 ) ;
721+ suggest_confusable ( & mut err) ;
697722 return err. emit ( ) ;
698723 }
699724 }
@@ -718,7 +743,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
718743 if cfg ! ( debug_assertions) {
719744 span_bug ! ( error_span, "expected errors from argument matrix" ) ;
720745 } 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 ( ) ;
722750 }
723751 }
724752
@@ -733,7 +761,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
733761 let trace =
734762 mk_trace ( provided_span, formal_and_expected_inputs[ * expected_idx] , provided_ty) ;
735763 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 ( ) ) ;
737767 return false ;
738768 }
739769 true
@@ -801,6 +831,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
801831 Some ( expected_idx. as_usize ( ) ) ,
802832 is_method,
803833 ) ;
834+ suggest_confusable ( & mut err) ;
804835 return err. emit ( ) ;
805836 }
806837
@@ -828,6 +859,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
828859 . with_code ( err_code. to_owned ( ) )
829860 } ;
830861
862+ suggest_confusable ( & mut err) ;
831863 // As we encounter issues, keep track of what we want to provide for the suggestion
832864 let mut labels = vec ! [ ] ;
833865 // If there is a single error, we give a specific suggestion; otherwise, we change to
0 commit comments