@@ -440,30 +440,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
440
440
call_expr : & hir:: Expr < ' tcx > ,
441
441
) {
442
442
// Next, let's construct the error
443
- let ( error_span, full_call_span, ctor_of) = match & call_expr. kind {
443
+ let ( error_span, full_call_span, ctor_of, is_method ) = match & call_expr. kind {
444
444
hir:: ExprKind :: Call (
445
445
hir:: Expr { hir_id, span, kind : hir:: ExprKind :: Path ( qpath) , .. } ,
446
446
_,
447
447
) => {
448
448
if let Res :: Def ( DefKind :: Ctor ( of, _) , _) =
449
449
self . typeck_results . borrow ( ) . qpath_res ( qpath, * hir_id)
450
450
{
451
- ( call_span, * span, Some ( of) )
451
+ ( call_span, * span, Some ( of) , false )
452
452
} else {
453
- ( call_span, * span, None )
453
+ ( call_span, * span, None , false )
454
454
}
455
455
}
456
- hir:: ExprKind :: Call ( hir:: Expr { span, .. } , _) => ( call_span, * span, None ) ,
456
+ hir:: ExprKind :: Call ( hir:: Expr { span, .. } , _) => ( call_span, * span, None , false ) ,
457
457
hir:: ExprKind :: MethodCall ( path_segment, _, span) => {
458
458
let ident_span = path_segment. ident . span ;
459
459
let ident_span = if let Some ( args) = path_segment. args {
460
460
ident_span. with_hi ( args. span_ext . hi ( ) )
461
461
} else {
462
462
ident_span
463
463
} ;
464
- (
465
- * span, ident_span, None , // methods are never ctors
466
- )
464
+ // methods are never ctors
465
+ ( * span, ident_span, None , true )
467
466
}
468
467
k => span_bug ! ( call_span, "checking argument types on a non-call: `{:?}`" , k) ,
469
468
} ;
@@ -545,7 +544,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
545
544
let coerced_ty = expectation. only_has_type ( self ) . unwrap_or ( formal_input_ty) ;
546
545
let can_coerce = self . can_coerce ( arg_ty, coerced_ty) ;
547
546
if !can_coerce {
548
- return Compatibility :: Incompatible ( None ) ;
547
+ return Compatibility :: Incompatible ( Some ( ty:: error:: TypeError :: Sorts (
548
+ ty:: error:: ExpectedFound :: new ( true , coerced_ty, arg_ty) ,
549
+ ) ) ) ;
549
550
}
550
551
551
552
// Using probe here, since we don't want this subtyping to affect inference.
@@ -659,7 +660,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
659
660
Applicability :: MachineApplicable ,
660
661
) ;
661
662
} ;
662
- self . label_fn_like ( & mut err, fn_def_id, callee_ty) ;
663
+ self . label_fn_like ( & mut err, fn_def_id, callee_ty, Some ( mismatch_idx ) , is_method ) ;
663
664
err. emit ( ) ;
664
665
return ;
665
666
}
@@ -701,16 +702,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
701
702
}
702
703
703
704
errors. drain_filter ( |error| {
704
- let Error :: Invalid ( provided_idx, expected_idx, Compatibility :: Incompatible ( error ) ) = error else { return false } ;
705
+ let Error :: Invalid ( provided_idx, expected_idx, Compatibility :: Incompatible ( Some ( e ) ) ) = error else { return false } ;
705
706
let ( provided_ty, provided_span) = provided_arg_tys[ * provided_idx] ;
706
707
let ( expected_ty, _) = formal_and_expected_inputs[ * expected_idx] ;
707
708
let cause = & self . misc ( provided_span) ;
708
709
let trace = TypeTrace :: types ( cause, true , expected_ty, provided_ty) ;
709
- if let Some ( e) = error {
710
- if !matches ! ( trace. cause. as_failure_code( e) , FailureCode :: Error0308 ( _) ) {
711
- self . report_and_explain_type_error ( trace, e) . emit ( ) ;
712
- return true ;
713
- }
710
+ if !matches ! ( trace. cause. as_failure_code( e) , FailureCode :: Error0308 ( _) ) {
711
+ self . report_and_explain_type_error ( trace, e) . emit ( ) ;
712
+ return true ;
714
713
}
715
714
false
716
715
} ) ;
@@ -749,7 +748,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
749
748
format ! ( "arguments to this {} are incorrect" , call_name) ,
750
749
) ;
751
750
// Call out where the function is defined
752
- self . label_fn_like ( & mut err, fn_def_id, callee_ty) ;
751
+ self . label_fn_like (
752
+ & mut err,
753
+ fn_def_id,
754
+ callee_ty,
755
+ Some ( expected_idx. as_usize ( ) ) ,
756
+ is_method,
757
+ ) ;
753
758
err. emit ( ) ;
754
759
return ;
755
760
}
@@ -1031,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1031
1036
}
1032
1037
1033
1038
// Call out where the function is defined
1034
- self . label_fn_like ( & mut err, fn_def_id, callee_ty) ;
1039
+ self . label_fn_like ( & mut err, fn_def_id, callee_ty, None , is_method ) ;
1035
1040
1036
1041
// And add a suggestion block for all of the parameters
1037
1042
let suggestion_text = match suggestion_text {
@@ -1781,6 +1786,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1781
1786
err : & mut Diagnostic ,
1782
1787
callable_def_id : Option < DefId > ,
1783
1788
callee_ty : Option < Ty < ' tcx > > ,
1789
+ // A specific argument should be labeled, instead of all of them
1790
+ expected_idx : Option < usize > ,
1791
+ is_method : bool ,
1784
1792
) {
1785
1793
let Some ( mut def_id) = callable_def_id else {
1786
1794
return ;
@@ -1881,14 +1889,30 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1881
1889
. get_if_local ( def_id)
1882
1890
. and_then ( |node| node. body_id ( ) )
1883
1891
. into_iter ( )
1884
- . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params ) ;
1892
+ . flat_map ( |id| self . tcx . hir ( ) . body ( id) . params )
1893
+ . skip ( if is_method { 1 } else { 0 } ) ;
1885
1894
1886
- for param in params {
1895
+ for ( _, param) in params
1896
+ . into_iter ( )
1897
+ . enumerate ( )
1898
+ . filter ( |( idx, _) | expected_idx. map_or ( true , |expected_idx| expected_idx == * idx) )
1899
+ {
1887
1900
spans. push_span_label ( param. span , "" ) ;
1888
1901
}
1889
1902
1890
1903
let def_kind = self . tcx . def_kind ( def_id) ;
1891
1904
err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
1905
+ } else if let Some ( hir:: Node :: Expr ( e) ) = self . tcx . hir ( ) . get_if_local ( def_id)
1906
+ && let hir:: ExprKind :: Closure ( hir:: Closure { body, .. } ) = & e. kind
1907
+ {
1908
+ let param = expected_idx
1909
+ . and_then ( |expected_idx| self . tcx . hir ( ) . body ( * body) . params . get ( expected_idx) ) ;
1910
+ let ( kind, span) = if let Some ( param) = param {
1911
+ ( "closure parameter" , param. span )
1912
+ } else {
1913
+ ( "closure" , self . tcx . def_span ( def_id) )
1914
+ } ;
1915
+ err. span_note ( span, & format ! ( "{} defined here" , kind) ) ;
1892
1916
} else {
1893
1917
let def_kind = self . tcx . def_kind ( def_id) ;
1894
1918
err. span_note (
0 commit comments