@@ -24,7 +24,7 @@ use rustc_infer::infer::TypeTrace;
24
24
use rustc_middle:: ty:: adjustment:: AllowTwoPhase ;
25
25
use rustc_middle:: ty:: error:: TypeError ;
26
26
use rustc_middle:: ty:: fold:: TypeFoldable ;
27
- use rustc_middle:: ty:: { self , Ty } ;
27
+ use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
28
28
use rustc_session:: Session ;
29
29
use rustc_span:: symbol:: Ident ;
30
30
use rustc_span:: { self , Span } ;
@@ -394,6 +394,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
394
394
break ' errors;
395
395
}
396
396
397
+ self . set_tainted_by_errors ( ) ;
398
+
397
399
// The algorithm here is inspired by levenshtein distance and longest common subsequence.
398
400
// We'll try to detect 4 different types of mistakes:
399
401
// - An extra parameter has been provided that doesn't satisfy *any* of the other inputs
@@ -502,6 +504,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
502
504
TupleMatchFound :: Single => {
503
505
let expected_ty = expected_input_tys[ 0 ] ;
504
506
let provided_ty = final_arg_types[ 0 ] . map ( |ty| ty. 0 ) . unwrap ( ) ;
507
+ let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
508
+ let provided_ty = self . resolve_vars_if_possible ( provided_ty) ;
505
509
let cause = & self . misc ( provided_args[ 0 ] . span ) ;
506
510
let compatibility = demand_compatible ( 0 , & mut final_arg_types) ;
507
511
let type_error = match compatibility {
@@ -523,24 +527,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
523
527
format ! ( "arguments to this {} are incorrect" , call_name) ,
524
528
) ;
525
529
// Call out where the function is defined
526
- if let Some ( def_id) = fn_def_id && let Some ( def_span) = tcx. def_ident_span ( def_id) {
527
- let mut spans: MultiSpan = def_span. into ( ) ;
528
-
529
- let params = tcx
530
- . hir ( )
531
- . get_if_local ( def_id)
532
- . and_then ( |node| node. body_id ( ) )
533
- . into_iter ( )
534
- . map ( |id| tcx. hir ( ) . body ( id) . params )
535
- . flatten ( ) ;
536
-
537
- for param in params {
538
- spans. push_span_label ( param. span , String :: new ( ) ) ;
539
- }
540
-
541
- let def_kind = tcx. def_kind ( def_id) ;
542
- err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
543
- }
530
+ label_fn_like ( tcx, & mut err, fn_def_id) ;
544
531
err. emit ( ) ;
545
532
break ' errors;
546
533
}
@@ -558,24 +545,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
558
545
DiagnosticId :: Error ( err_code. to_owned ( ) ) ,
559
546
) ;
560
547
// Call out where the function is defined
561
- if let Some ( def_id) = fn_def_id && let Some ( def_span) = tcx. def_ident_span ( def_id) {
562
- let mut spans: MultiSpan = def_span. into ( ) ;
563
-
564
- let params = tcx
565
- . hir ( )
566
- . get_if_local ( def_id)
567
- . and_then ( |node| node. body_id ( ) )
568
- . into_iter ( )
569
- . map ( |id| tcx. hir ( ) . body ( id) . params )
570
- . flatten ( ) ;
571
-
572
- for param in params {
573
- spans. push_span_label ( param. span , String :: new ( ) ) ;
574
- }
575
-
576
- let def_kind = tcx. def_kind ( def_id) ;
577
- err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
578
- }
548
+ label_fn_like ( tcx, & mut err, fn_def_id) ;
579
549
err. multipart_suggestion (
580
550
"use parentheses to construct a tuple" ,
581
551
vec ! [ ( start, '(' . to_string( ) ) , ( end, ')' . to_string( ) ) ] ,
@@ -597,13 +567,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
597
567
{
598
568
let expected_ty = expected_input_tys[ * input_idx] ;
599
569
let provided_ty = final_arg_types[ * input_idx] . map ( |ty| ty. 0 ) . unwrap ( ) ;
570
+ let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
571
+ let provided_ty = self . resolve_vars_if_possible ( provided_ty) ;
600
572
let cause = & self . misc ( provided_args[ * input_idx] . span ) ;
601
573
let trace = TypeTrace :: types ( cause, true , expected_ty, provided_ty) ;
602
574
let mut err = self . report_and_explain_type_error ( trace, error) ;
603
575
self . emit_coerce_suggestions (
604
576
& mut err,
605
577
& provided_args[ * input_idx] ,
606
- final_arg_types [ * input_idx ] . map ( |ty| ty . 0 ) . unwrap ( ) ,
578
+ provided_ty ,
607
579
final_arg_types[ * input_idx] . map ( |ty| ty. 1 ) . unwrap ( ) ,
608
580
None ,
609
581
None ,
@@ -613,24 +585,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
613
585
format ! ( "arguments to this {} are incorrect" , call_name) ,
614
586
) ;
615
587
// Call out where the function is defined
616
- if let Some ( def_id) = fn_def_id && let Some ( def_span) = tcx. def_ident_span ( def_id) {
617
- let mut spans: MultiSpan = def_span. into ( ) ;
618
-
619
- let params = tcx
620
- . hir ( )
621
- . get_if_local ( def_id)
622
- . and_then ( |node| node. body_id ( ) )
623
- . into_iter ( )
624
- . map ( |id| tcx. hir ( ) . body ( id) . params )
625
- . flatten ( ) ;
626
-
627
- for param in params {
628
- spans. push_span_label ( param. span , String :: new ( ) ) ;
629
- }
630
-
631
- let def_kind = tcx. def_kind ( def_id) ;
632
- err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
633
- }
588
+ label_fn_like ( tcx, & mut err, fn_def_id) ;
634
589
err. emit ( ) ;
635
590
break ' errors;
636
591
}
@@ -678,12 +633,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
678
633
match error {
679
634
Error :: Invalid ( input_idx, compatibility) => {
680
635
let expected_ty = expected_input_tys[ input_idx] ;
636
+ let provided_ty = final_arg_types
637
+ . get ( input_idx)
638
+ . and_then ( |x| x. as_ref ( ) )
639
+ . map ( |ty| ty. 0 )
640
+ . unwrap_or ( tcx. ty_error ( ) ) ;
641
+ let expected_ty = self . resolve_vars_if_possible ( expected_ty) ;
642
+ let provided_ty = self . resolve_vars_if_possible ( provided_ty) ;
681
643
if let Compatibility :: Incompatible ( error) = & compatibility {
682
- let provided_ty = final_arg_types
683
- . get ( input_idx)
684
- . and_then ( |x| x. as_ref ( ) )
685
- . map ( |ty| ty. 0 )
686
- . unwrap_or ( tcx. ty_error ( ) ) ;
687
644
let cause = & self . misc (
688
645
provided_args. get ( input_idx) . map ( |i| i. span ) . unwrap_or ( call_span) ,
689
646
) ;
@@ -948,24 +905,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
948
905
}
949
906
950
907
// Call out where the function is defined
951
- if let Some ( def_id) = fn_def_id && let Some ( def_span) = tcx. def_ident_span ( def_id) {
952
- let mut spans: MultiSpan = def_span. into ( ) ;
953
-
954
- let params = tcx
955
- . hir ( )
956
- . get_if_local ( def_id)
957
- . and_then ( |node| node. body_id ( ) )
958
- . into_iter ( )
959
- . flat_map ( |id| tcx. hir ( ) . body ( id) . params )
960
- ;
961
-
962
- for param in params {
963
- spans. push_span_label ( param. span , String :: new ( ) ) ;
964
- }
965
-
966
- let def_kind = tcx. def_kind ( def_id) ;
967
- err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
968
- }
908
+ label_fn_like ( tcx, & mut err, fn_def_id) ;
969
909
970
910
// And add a suggestion block for all of the parameters
971
911
let suggestion_text = match suggestion_text {
@@ -1790,3 +1730,47 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
1790
1730
}
1791
1731
}
1792
1732
}
1733
+
1734
+ fn label_fn_like < ' tcx > (
1735
+ tcx : TyCtxt < ' tcx > ,
1736
+ err : & mut rustc_errors:: DiagnosticBuilder < ' tcx , rustc_errors:: ErrorGuaranteed > ,
1737
+ def_id : Option < DefId > ,
1738
+ ) {
1739
+ let Some ( def_id) = def_id else {
1740
+ return ;
1741
+ } ;
1742
+
1743
+ if let Some ( def_span) = tcx. def_ident_span ( def_id) {
1744
+ let mut spans: MultiSpan = def_span. into ( ) ;
1745
+
1746
+ let params = tcx
1747
+ . hir ( )
1748
+ . get_if_local ( def_id)
1749
+ . and_then ( |node| node. body_id ( ) )
1750
+ . into_iter ( )
1751
+ . map ( |id| tcx. hir ( ) . body ( id) . params )
1752
+ . flatten ( ) ;
1753
+
1754
+ for param in params {
1755
+ spans. push_span_label ( param. span , String :: new ( ) ) ;
1756
+ }
1757
+
1758
+ let def_kind = tcx. def_kind ( def_id) ;
1759
+ err. span_note ( spans, & format ! ( "{} defined here" , def_kind. descr( def_id) ) ) ;
1760
+ } else {
1761
+ match tcx. hir ( ) . get_if_local ( def_id) {
1762
+ Some ( hir:: Node :: Expr ( hir:: Expr {
1763
+ kind : hir:: ExprKind :: Closure ( _, _, _, span, ..) ,
1764
+ ..
1765
+ } ) ) => {
1766
+ let spans: MultiSpan = ( * span) . into ( ) ;
1767
+
1768
+ // Note: We don't point to param spans here because they overlap
1769
+ // with the closure span itself
1770
+
1771
+ err. span_note ( spans, "closure defined here" ) ;
1772
+ }
1773
+ _ => { }
1774
+ }
1775
+ }
1776
+ }
0 commit comments