@@ -555,6 +555,155 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
555
555
}
556
556
}
557
557
558
+ fn highlight_outer ( & self ,
559
+ value : & mut Vec < ( String , bool ) > ,
560
+ other_value : & mut Vec < ( String , bool ) > ,
561
+ name : String ,
562
+ sub : & ty:: subst:: Substs < ' tcx > ,
563
+ pos : usize ,
564
+ other_ty : & ty:: Ty < ' tcx > ) {
565
+ value. push ( ( name, true ) ) ;
566
+ let len = sub. len ( ) ;
567
+ if len > 0 {
568
+ value. push ( ( "<" . to_string ( ) , true ) ) ;
569
+ }
570
+
571
+ let sts = sub. regions ( ) ;
572
+ for ( i, st) in sts. enumerate ( ) {
573
+ value. push ( ( format ! ( "{}" , st) , false ) ) ;
574
+
575
+ if len > 0 && i != len - 1 {
576
+ value. push ( ( format ! ( ", " ) , false ) ) ;
577
+ }
578
+ }
579
+
580
+ let sts = sub. types ( ) ;
581
+ for ( i, st) in sts. enumerate ( ) {
582
+ if i == pos {
583
+ let ( v, o_v) = self . cmp ( st, other_ty) ;
584
+ value. extend ( v) ;
585
+ other_value. extend ( o_v) ;
586
+ } else {
587
+ value. push ( ( format ! ( "{}" , st) , true ) ) ;
588
+ }
589
+
590
+ if len > 0 && i != len - 1 {
591
+ value. push ( ( format ! ( ", " ) , true ) ) ;
592
+ }
593
+ }
594
+ if len > 0 {
595
+ value. push ( ( ">" . to_string ( ) , true ) ) ;
596
+ }
597
+ }
598
+
599
+
600
+ fn cmp ( & self , t1 : ty:: Ty < ' tcx > , t2 : ty:: Ty < ' tcx > )
601
+ -> ( Vec < ( String , bool ) > , Vec < ( String , bool ) > )
602
+ {
603
+ match ( & t1. sty , & t2. sty ) {
604
+ ( & ty:: TyAdt ( def1, sub1) , & ty:: TyAdt ( def2, sub2) ) => {
605
+ let mut values: ( Vec < ( String , bool ) > , Vec < ( String , bool ) > ) = ( vec ! [ ] , vec ! [ ] ) ;
606
+ let name1 = self . tcx . item_path_str ( def1. did . clone ( ) ) ;
607
+ let name2 = self . tcx . item_path_str ( def2. did . clone ( ) ) ;
608
+ if name1 == name2 {
609
+ // Easy case, replace same types with `_` to shorten the output
610
+ // and highlight only the differing types.
611
+ values. 0 . push ( ( name1. to_string ( ) , false ) ) ;
612
+ values. 1 . push ( ( name2. to_string ( ) , false ) ) ;
613
+
614
+ let len = sub1. len ( ) ;
615
+ if len > 0 {
616
+ values. 0 . push ( ( "<" . to_string ( ) , false ) ) ;
617
+ values. 1 . push ( ( "<" . to_string ( ) , false ) ) ;
618
+ }
619
+
620
+ let sts1 = sub1. regions ( ) ;
621
+ let sts2 = sub2. regions ( ) ;
622
+ let x = sts1. zip ( sts2) ;
623
+ for ( i, ( st1, st2) ) in x. enumerate ( ) {
624
+ values. 0 . push ( ( format ! ( "{}" , st1) , st1 != st2) ) ;
625
+ values. 1 . push ( ( format ! ( "{}" , st2) , st1 != st2) ) ;
626
+
627
+ if len > 0 && i != len - 1 {
628
+ values. 0 . push ( ( format ! ( ", " ) , false ) ) ;
629
+ values. 1 . push ( ( format ! ( ", " ) , false ) ) ;
630
+ }
631
+ }
632
+
633
+ let sts1 = sub1. types ( ) ;
634
+ let sts2 = sub2. types ( ) ;
635
+ let x = sts1. zip ( sts2) ;
636
+ for ( i, ( st1, st2) ) in x. enumerate ( ) {
637
+ if st1 == st2 {
638
+ values. 0 . push ( ( "_" . to_string ( ) , false ) ) ;
639
+ values. 1 . push ( ( "_" . to_string ( ) , false ) ) ;
640
+ } else {
641
+ let ( x1, x2) = self . cmp ( st1, st2) ;
642
+ values. 0 . extend ( x1) ;
643
+ values. 1 . extend ( x2) ;
644
+ }
645
+ if len > 0 && i != len - 1 {
646
+ values. 0 . push ( ( format ! ( ", " ) , false ) ) ;
647
+ values. 1 . push ( ( format ! ( ", " ) , false ) ) ;
648
+ }
649
+ }
650
+ if len > 0 {
651
+ values. 0 . push ( ( ">" . to_string ( ) , false ) ) ;
652
+ values. 1 . push ( ( ">" . to_string ( ) , false ) ) ;
653
+ }
654
+ values
655
+ } else {
656
+ // Check for simple composition
657
+ for ( i, st) in sub1. types ( ) . enumerate ( ) {
658
+ if st == t2 {
659
+ self . highlight_outer ( & mut values. 0 , & mut values. 1 , name1, sub1, i, & t2) ;
660
+ return values;
661
+ }
662
+ if let & ty:: TyAdt ( def, _) = & st. sty {
663
+ let name = self . tcx . item_path_str ( def. did . clone ( ) ) ;
664
+ if name == name2 {
665
+ self . highlight_outer ( & mut values. 0 ,
666
+ & mut values. 1 ,
667
+ name1,
668
+ sub1,
669
+ i,
670
+ & t2) ;
671
+ return values;
672
+ }
673
+ }
674
+ }
675
+ for ( i, st) in sub2. types ( ) . enumerate ( ) {
676
+ if st == t1 {
677
+ self . highlight_outer ( & mut values. 1 , & mut values. 0 , name2, sub2, i, & t1) ;
678
+ return values;
679
+ }
680
+ if let & ty:: TyAdt ( def, _) = & st. sty {
681
+ let name = self . tcx . item_path_str ( def. did . clone ( ) ) ;
682
+ if name == name1 {
683
+ self . highlight_outer ( & mut values. 1 ,
684
+ & mut values. 0 ,
685
+ name2,
686
+ sub2,
687
+ i,
688
+ & t1) ;
689
+ return values;
690
+ }
691
+ }
692
+ }
693
+
694
+ ( vec ! [ ( format!( "{}" , t1) , true ) ] , vec ! [ ( format!( "{}" , t2) , true ) ] )
695
+ }
696
+ }
697
+ _ => {
698
+ if t1 == t2 {
699
+ ( vec ! [ ( "_" . to_string( ) , false ) ] , vec ! [ ( "_" . to_string( ) , false ) ] )
700
+ } else {
701
+ ( vec ! [ ( format!( "{}" , t1) , true ) ] , vec ! [ ( format!( "{}" , t2) , true ) ] )
702
+ }
703
+ }
704
+ }
705
+ }
706
+
558
707
pub fn note_type_err ( & self ,
559
708
diag : & mut DiagnosticBuilder < ' tcx > ,
560
709
cause : & ObligationCause < ' tcx > ,
@@ -665,26 +814,64 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
665
814
diag
666
815
}
667
816
668
- /// Returns a string of the form "expected `{}`, found `{}`".
669
- fn values_str ( & self , values : & ValuePairs < ' tcx > ) -> Option < ( String , String ) > {
817
+ /// Returns two `Vec`s representing portions of a type with a flag on wether it should
818
+ /// be highlighted in the output.
819
+ ///
820
+ /// For given types `X<String, usize>` and `X<usize, usize>`, this method would return
821
+ ///
822
+ /// ```nocode
823
+ /// Some((vec![
824
+ /// ("X", false),
825
+ /// ("<", false),
826
+ /// ("String", true),
827
+ /// (",", false),
828
+ /// ("_", false),
829
+ /// (">", false)
830
+ /// ], vec![
831
+ /// ("X", false),
832
+ /// ("<", false),
833
+ /// ("usize", true),
834
+ /// (",", false),
835
+ /// ("_", false),
836
+ /// (">", false)
837
+ /// ]))
838
+ /// ```
839
+ fn values_str ( & self , values : & ValuePairs < ' tcx > )
840
+ -> Option < ( Vec < ( String , bool ) > , Vec < ( String , bool ) > ) >
841
+ {
670
842
match * values {
671
- infer:: Types ( ref exp_found) => self . expected_found_str ( exp_found) ,
843
+ infer:: Types ( ref exp_found) => self . expected_found_str_ty ( exp_found) ,
672
844
infer:: TraitRefs ( ref exp_found) => self . expected_found_str ( exp_found) ,
673
845
infer:: PolyTraitRefs ( ref exp_found) => self . expected_found_str ( exp_found) ,
674
846
}
675
847
}
676
848
849
+ fn expected_found_str_ty (
850
+ & self ,
851
+ exp_found : & ty:: error:: ExpectedFound < ty:: Ty < ' tcx > > )
852
+ -> Option < ( Vec < ( String , bool ) > , Vec < ( String , bool ) > ) >
853
+ {
854
+ let exp_found = self . resolve_type_vars_if_possible ( exp_found) ;
855
+ if exp_found. references_error ( ) {
856
+ return None ;
857
+ }
858
+
859
+ Some ( self . cmp ( exp_found. expected , exp_found. found ) )
860
+ }
861
+
862
+
677
863
fn expected_found_str < T : fmt:: Display + TypeFoldable < ' tcx > > (
678
864
& self ,
679
865
exp_found : & ty:: error:: ExpectedFound < T > )
680
- -> Option < ( String , String ) >
866
+ -> Option < ( Vec < ( String , bool ) > , Vec < ( String , bool ) > ) >
681
867
{
682
868
let exp_found = self . resolve_type_vars_if_possible ( exp_found) ;
683
869
if exp_found. references_error ( ) {
684
870
return None ;
685
871
}
686
872
687
- Some ( ( format ! ( "{}" , exp_found. expected) , format ! ( "{}" , exp_found. found) ) )
873
+ Some ( ( vec ! [ ( format!( "{}" , exp_found. expected) , true ) ] ,
874
+ vec ! [ ( format!( "{}" , exp_found. found) , true ) ] ) )
688
875
}
689
876
690
877
fn report_generic_bound_failure ( & self ,
@@ -1140,6 +1327,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
1140
1327
match * origin {
1141
1328
infer:: Subtype ( ref trace) => {
1142
1329
if let Some ( ( expected, found) ) = self . values_str ( & trace. values ) {
1330
+ let expected = expected. iter ( ) . map ( |x| x. 0 . to_owned ( ) ) . collect :: < String > ( ) ;
1331
+ let found = found. iter ( ) . map ( |x| x. 0 . to_owned ( ) ) . collect :: < String > ( ) ;
1143
1332
// FIXME: do we want a "the" here?
1144
1333
err. span_note (
1145
1334
trace. cause . span ,
0 commit comments