@@ -60,13 +60,13 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa
60
60
use super :: region_constraints:: GenericKind ;
61
61
use super :: lexical_region_resolve:: RegionResolutionError ;
62
62
63
- use std:: fmt;
63
+ use std:: { cmp , fmt} ;
64
64
use hir;
65
65
use hir:: map as hir_map;
66
66
use hir:: def_id:: DefId ;
67
67
use middle:: region;
68
68
use traits:: { ObligationCause , ObligationCauseCode } ;
69
- use ty:: { self , Region , Ty , TyCtxt , TypeFoldable , TypeVariants } ;
69
+ use ty:: { self , subst :: Subst , Region , Ty , TyCtxt , TypeFoldable , TypeVariants } ;
70
70
use ty:: error:: TypeError ;
71
71
use syntax:: ast:: DUMMY_NODE_ID ;
72
72
use syntax_pos:: { Pos , Span } ;
@@ -193,32 +193,12 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
193
193
194
194
let scope = region. free_region_binding_scope ( self ) ;
195
195
let node = self . hir . as_local_node_id ( scope) . unwrap_or ( DUMMY_NODE_ID ) ;
196
- let unknown;
197
196
let tag = match self . hir . find ( node) {
198
197
Some ( hir_map:: NodeBlock ( _) ) | Some ( hir_map:: NodeExpr ( _) ) => "body" ,
199
198
Some ( hir_map:: NodeItem ( it) ) => Self :: item_scope_tag ( & it) ,
200
199
Some ( hir_map:: NodeTraitItem ( it) ) => Self :: trait_item_scope_tag ( & it) ,
201
200
Some ( hir_map:: NodeImplItem ( it) ) => Self :: impl_item_scope_tag ( & it) ,
202
-
203
- // this really should not happen, but it does:
204
- // FIXME(#27942)
205
- Some ( _) => {
206
- unknown = format ! (
207
- "unexpected node ({}) for scope {:?}. \
208
- Please report a bug.",
209
- self . hir. node_to_string( node) ,
210
- scope
211
- ) ;
212
- & unknown
213
- }
214
- None => {
215
- unknown = format ! (
216
- "unknown node for scope {:?}. \
217
- Please report a bug.",
218
- scope
219
- ) ;
220
- & unknown
221
- }
201
+ _ => unreachable ! ( )
222
202
} ;
223
203
let ( prefix, span) = match * region {
224
204
ty:: ReEarlyBound ( ref br) => {
@@ -672,6 +652,43 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
672
652
}
673
653
}
674
654
655
+ /// For generic types with parameters with defaults, remove the parameters corresponding to
656
+ /// the defaults. This repeats a lot of the logic found in `PrintContext::parameterized`.
657
+ fn strip_generic_default_params (
658
+ & self ,
659
+ def_id : DefId ,
660
+ substs : & ty:: subst:: Substs < ' tcx >
661
+ ) -> & ' tcx ty:: subst:: Substs < ' tcx > {
662
+ let generics = self . tcx . generics_of ( def_id) ;
663
+ let mut num_supplied_defaults = 0 ;
664
+ let mut type_params = generics. params . iter ( ) . rev ( ) . filter_map ( |param| match param. kind {
665
+ ty:: GenericParamDefKind :: Lifetime => None ,
666
+ ty:: GenericParamDefKind :: Type { has_default, .. } => {
667
+ Some ( ( param. def_id , has_default) )
668
+ }
669
+ } ) . peekable ( ) ;
670
+ let has_default = {
671
+ let has_default = type_params. peek ( ) . map ( |( _, has_default) | has_default) ;
672
+ * has_default. unwrap_or ( & false )
673
+ } ;
674
+ if has_default {
675
+ let types = substs. types ( ) . rev ( ) ;
676
+ for ( ( def_id, has_default) , actual) in type_params. zip ( types) {
677
+ if !has_default {
678
+ break ;
679
+ }
680
+ if self . tcx . type_of ( def_id) . subst ( self . tcx , substs) != actual {
681
+ break ;
682
+ }
683
+ num_supplied_defaults += 1 ;
684
+ }
685
+ }
686
+ let len = generics. params . len ( ) ;
687
+ let mut generics = generics. clone ( ) ;
688
+ generics. params . truncate ( len - num_supplied_defaults) ;
689
+ substs. truncate_to ( self . tcx , & generics)
690
+ }
691
+
675
692
/// Compare two given types, eliding parts that are the same between them and highlighting
676
693
/// relevant differences, and return two representation of those types for highlighted printing.
677
694
fn cmp ( & self , t1 : Ty < ' tcx > , t2 : Ty < ' tcx > ) -> ( DiagnosticStyledString , DiagnosticStyledString ) {
@@ -713,6 +730,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
713
730
714
731
match ( & t1. sty , & t2. sty ) {
715
732
( & ty:: TyAdt ( def1, sub1) , & ty:: TyAdt ( def2, sub2) ) => {
733
+ let sub_no_defaults_1 = self . strip_generic_default_params ( def1. did , sub1) ;
734
+ let sub_no_defaults_2 = self . strip_generic_default_params ( def2. did , sub2) ;
716
735
let mut values = ( DiagnosticStyledString :: new ( ) , DiagnosticStyledString :: new ( ) ) ;
717
736
let path1 = self . tcx . item_path_str ( def1. did . clone ( ) ) ;
718
737
let path2 = self . tcx . item_path_str ( def2. did . clone ( ) ) ;
@@ -728,8 +747,19 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
728
747
values. 0 . push_normal ( path1) ;
729
748
values. 1 . push_normal ( path2) ;
730
749
750
+ // Avoid printing out default generic parameters that are common to both
751
+ // types.
752
+ let len1 = sub_no_defaults_1. len ( ) ;
753
+ let len2 = sub_no_defaults_2. len ( ) ;
754
+ let common_len = cmp:: min ( len1, len2) ;
755
+ let remainder1: Vec < _ > = sub1. types ( ) . skip ( common_len) . collect ( ) ;
756
+ let remainder2: Vec < _ > = sub2. types ( ) . skip ( common_len) . collect ( ) ;
757
+ let common_default_params =
758
+ remainder1. iter ( ) . rev ( ) . zip ( remainder2. iter ( ) . rev ( ) )
759
+ . filter ( |( a, b) | a == b) . count ( ) ;
760
+ let len = sub1. len ( ) - common_default_params;
761
+
731
762
// Only draw `<...>` if there're lifetime/type arguments.
732
- let len = sub1. len ( ) ;
733
763
if len > 0 {
734
764
values. 0 . push_normal ( "<" ) ;
735
765
values. 1 . push_normal ( "<" ) ;
@@ -774,7 +804,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
774
804
// ^ elided type as this type argument was the same in both sides
775
805
let type_arguments = sub1. types ( ) . zip ( sub2. types ( ) ) ;
776
806
let regions_len = sub1. regions ( ) . collect :: < Vec < _ > > ( ) . len ( ) ;
777
- for ( i, ( ta1, ta2) ) in type_arguments. enumerate ( ) {
807
+ for ( i, ( ta1, ta2) ) in type_arguments. take ( len ) . enumerate ( ) {
778
808
let i = i + regions_len;
779
809
if ta1 == ta2 {
780
810
values. 0 . push_normal ( "_" ) ;
@@ -804,7 +834,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
804
834
& mut values. 0 ,
805
835
& mut values. 1 ,
806
836
path1. clone ( ) ,
807
- sub1 ,
837
+ sub_no_defaults_1 ,
808
838
path2. clone ( ) ,
809
839
& t2,
810
840
) . is_some ( )
@@ -816,8 +846,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
816
846
// Bar<Qux>
817
847
// Foo<Bar<Qux>>
818
848
// ------- this type argument is exactly the same as the other type
819
- if self . cmp_type_arg ( & mut values. 1 , & mut values. 0 , path2, sub2, path1, & t1)
820
- . is_some ( )
849
+ if self . cmp_type_arg (
850
+ & mut values. 1 ,
851
+ & mut values. 0 ,
852
+ path2,
853
+ sub_no_defaults_2,
854
+ path1,
855
+ & t1,
856
+ ) . is_some ( )
821
857
{
822
858
return values;
823
859
}
0 commit comments