@@ -22,12 +22,11 @@ use middle::lang_items::SizedTraitLangItem;
22
22
use middle:: resolve_lifetime as rl;
23
23
use middle:: weak_lang_items;
24
24
use rustc:: mir:: mono:: Linkage ;
25
+ use rustc:: ty:: { self , AdtKind , Binder , Predicate , ToPolyTraitRef , Ty , TyCtxt } ;
25
26
use rustc:: ty:: query:: Providers ;
26
27
use rustc:: ty:: query:: queries;
27
28
use rustc:: ty:: subst:: Substs ;
28
- use rustc:: ty:: util:: Discr ;
29
- use rustc:: ty:: util:: IntTypeExt ;
30
- use rustc:: ty:: { self , AdtKind , ToPolyTraitRef , Ty , TyCtxt } ;
29
+ use rustc:: ty:: util:: { Discr , IntTypeExt } ;
31
30
use rustc:: ty:: { ReprOptions , ToPredicate } ;
32
31
use rustc:: util:: captures:: Captures ;
33
32
use rustc:: util:: nodemap:: FxHashMap ;
@@ -50,9 +49,65 @@ use rustc::hir::GenericParamKind;
50
49
use rustc:: hir:: { self , CodegenFnAttrFlags , CodegenFnAttrs , Unsafety } ;
51
50
52
51
use std:: iter;
52
+ use std:: ops:: Range ;
53
53
54
54
struct OnlySelfBounds ( bool ) ;
55
55
56
+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord ) ]
57
+ pub enum LintedBoundVar < ' tcx > {
58
+ DefId ( DefId ) ,
59
+ SelfTy ,
60
+ Ty ( Binder < Ty < ' tcx > > ) ,
61
+ Region ( Binder < ty:: Region < ' tcx > > ) ,
62
+ }
63
+
64
+ #[ derive( Debug , PartialEq , Eq , PartialOrd , Ord ) ]
65
+ pub enum LintedBoundValue < ' tcx > {
66
+ DefId ( DefId ) ,
67
+ Ty ( Binder < Ty < ' tcx > > ) ,
68
+ Region ( Binder < ty:: Region < ' tcx > > ) ,
69
+ }
70
+
71
+ pub fn lint_duplicate_bounds < ' a , ' gcx , ' tcx > (
72
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
73
+ node_id : ast:: NodeId ,
74
+ bounds : impl IntoIterator < Item = ( LintedBoundVar < ' tcx > , LintedBoundValue < ' tcx > , Span ) > ,
75
+ ) {
76
+ let mut bounds: Vec < _ > = bounds. into_iter ( ) . collect ( ) ;
77
+ bounds. sort_unstable ( ) ;
78
+
79
+ let emit_lint = |range : Range < usize > | {
80
+ let bound_name = tcx. sess . source_map ( )
81
+ . span_to_snippet ( bounds[ range. start ] . 2 ) . unwrap ( ) ;
82
+ let mut err = tcx. struct_span_lint_node (
83
+ lint:: builtin:: DUPLICATE_BOUNDS ,
84
+ node_id,
85
+ bounds[ range. clone ( ) ] . iter ( ) . map ( |( _, _, sp) | * sp) . collect :: < Vec < _ > > ( ) ,
86
+ & format ! ( "duplicate bound `{}` found" ,
87
+ bound_name) ) ;
88
+ debug ! ( "zzz: 1: {:?} / {:?}" , bounds[ range. start] . 0 , bounds[ range. start] . 1 ) ;
89
+ err. span_label ( bounds[ range. start ] . 2 , "first use of bound" ) ;
90
+ for i in ( range. start + 1 ) ..range. end {
91
+ debug ! ( "zzz: 2: {:?} / {:?}" , bounds[ i] . 0 , bounds[ i] . 1 ) ;
92
+ err. span_label ( bounds[ i] . 2 , "subsequent use of bound" ) ;
93
+ }
94
+ err. emit ( ) ;
95
+ } ;
96
+
97
+ let mut seq_start = 0 ;
98
+ for i in 1 ..bounds. len ( ) {
99
+ if ( & bounds[ i] . 0 , & bounds[ i] . 1 ) != ( & bounds[ i - 1 ] . 0 , & bounds[ i - 1 ] . 1 ) {
100
+ if i - seq_start > 1 {
101
+ emit_lint ( seq_start..i) ;
102
+ }
103
+ seq_start = i;
104
+ }
105
+ }
106
+ if bounds. len ( ) - seq_start > 1 {
107
+ emit_lint ( seq_start..bounds. len ( ) ) ;
108
+ }
109
+ }
110
+
56
111
///////////////////////////////////////////////////////////////////////////
57
112
// Main entry point
58
113
@@ -336,7 +391,7 @@ impl<'a, 'tcx> ItemCtxt<'a, 'tcx> {
336
391
param_id : ast:: NodeId ,
337
392
ty : Ty < ' tcx > ,
338
393
only_self_bounds : OnlySelfBounds ,
339
- ) -> Vec < ( ty :: Predicate < ' tcx > , Span ) > {
394
+ ) -> Vec < ( Predicate < ' tcx > , Span ) > {
340
395
let from_ty_params = ast_generics
341
396
. params
342
397
. iter ( )
@@ -726,7 +781,7 @@ fn super_predicates_of<'a, 'tcx>(
726
781
// which will, in turn, reach indirect supertraits.
727
782
for & ( pred, span) in & superbounds {
728
783
debug ! ( "superbound: {:?}" , pred) ;
729
- if let ty :: Predicate :: Trait ( bound) = pred {
784
+ if let Predicate :: Trait ( bound) = pred {
730
785
tcx. at ( span) . super_predicates_of ( bound. def_id ( ) ) ;
731
786
}
732
787
}
@@ -1672,8 +1727,8 @@ fn explicit_predicates_of<'a, 'tcx>(
1672
1727
/// Preserving the order of insertion is important here so as not to break
1673
1728
/// compile-fail UI tests.
1674
1729
struct UniquePredicates < ' tcx > {
1675
- predicates : Vec < ( ty :: Predicate < ' tcx > , Span ) > ,
1676
- uniques : FxHashSet < ( ty :: Predicate < ' tcx > , Span ) > ,
1730
+ predicates : Vec < ( Predicate < ' tcx > , Span ) > ,
1731
+ uniques : FxHashSet < ( Predicate < ' tcx > , Span ) > ,
1677
1732
}
1678
1733
1679
1734
impl < ' tcx > UniquePredicates < ' tcx > {
@@ -1684,13 +1739,13 @@ fn explicit_predicates_of<'a, 'tcx>(
1684
1739
}
1685
1740
}
1686
1741
1687
- fn push ( & mut self , value : ( ty :: Predicate < ' tcx > , Span ) ) {
1742
+ fn push ( & mut self , value : ( Predicate < ' tcx > , Span ) ) {
1688
1743
if self . uniques . insert ( value) {
1689
1744
self . predicates . push ( value) ;
1690
1745
}
1691
1746
}
1692
1747
1693
- fn extend < I : IntoIterator < Item = ( ty :: Predicate < ' tcx > , Span ) > > ( & mut self , iter : I ) {
1748
+ fn extend < I : IntoIterator < Item = ( Predicate < ' tcx > , Span ) > > ( & mut self , iter : I ) {
1694
1749
for value in iter {
1695
1750
self . push ( value) ;
1696
1751
}
@@ -1884,7 +1939,7 @@ fn explicit_predicates_of<'a, 'tcx>(
1884
1939
let span = bound_pred. bounded_ty . span ;
1885
1940
let predicate = ty:: OutlivesPredicate ( ty, tcx. mk_region ( ty:: ReEmpty ) ) ;
1886
1941
predicates. push (
1887
- ( ty :: Predicate :: TypeOutlives ( ty:: Binder :: dummy ( predicate) ) , span)
1942
+ ( Predicate :: TypeOutlives ( ty:: Binder :: dummy ( predicate) ) , span)
1888
1943
) ;
1889
1944
}
1890
1945
}
@@ -1910,7 +1965,7 @@ fn explicit_predicates_of<'a, 'tcx>(
1910
1965
& hir:: GenericBound :: Outlives ( ref lifetime) => {
1911
1966
let region = AstConv :: ast_region_to_region ( & icx, lifetime, None ) ;
1912
1967
let pred = ty:: Binder :: bind ( ty:: OutlivesPredicate ( ty, region) ) ;
1913
- predicates. push ( ( ty :: Predicate :: TypeOutlives ( pred) , lifetime. span ) )
1968
+ predicates. push ( ( Predicate :: TypeOutlives ( pred) , lifetime. span ) )
1914
1969
}
1915
1970
}
1916
1971
}
@@ -1927,7 +1982,7 @@ fn explicit_predicates_of<'a, 'tcx>(
1927
1982
} ;
1928
1983
let pred = ty:: Binder :: bind ( ty:: OutlivesPredicate ( r1, r2) ) ;
1929
1984
1930
- ( ty :: Predicate :: RegionOutlives ( pred) , span)
1985
+ ( Predicate :: RegionOutlives ( pred) , span)
1931
1986
} ) )
1932
1987
}
1933
1988
@@ -1983,6 +2038,26 @@ fn explicit_predicates_of<'a, 'tcx>(
1983
2038
) ;
1984
2039
}
1985
2040
2041
+ // Lint duplicate bounds.
2042
+ let bounds = predicates. iter ( ) . filter_map ( |( pred, sp) | {
2043
+ match pred {
2044
+ Predicate :: Trait ( ref pred) =>
2045
+ Some ( ( LintedBoundVar :: Ty ( pred. self_ty ( ) ) ,
2046
+ LintedBoundValue :: DefId ( pred. def_id ( ) ) , * sp) ) ,
2047
+ Predicate :: RegionOutlives ( ref pred) =>
2048
+ Some ( ( LintedBoundVar :: Region ( pred. var ( ) ) ,
2049
+ LintedBoundValue :: Region ( pred. value ( ) ) , * sp) ) ,
2050
+ Predicate :: TypeOutlives ( ref pred) =>
2051
+ Some ( ( LintedBoundVar :: Ty ( pred. var ( ) ) ,
2052
+ LintedBoundValue :: Region ( pred. value ( ) ) , * sp) ) ,
2053
+ Predicate :: Projection ( ref pred) =>
2054
+ Some ( ( LintedBoundVar :: DefId ( pred. item_def_id ( ) ) ,
2055
+ LintedBoundValue :: Ty ( pred. ty ( ) ) , * sp) ) ,
2056
+ _ => None ,
2057
+ }
2058
+ } ) ;
2059
+ lint_duplicate_bounds ( tcx, node_id, bounds) ;
2060
+
1986
2061
let result = Lrc :: new ( ty:: GenericPredicates {
1987
2062
parent : generics. parent ,
1988
2063
predicates,
@@ -2062,7 +2137,7 @@ fn predicates_from_bound<'tcx>(
2062
2137
astconv : & dyn AstConv < ' tcx , ' tcx > ,
2063
2138
param_ty : Ty < ' tcx > ,
2064
2139
bound : & hir:: GenericBound ,
2065
- ) -> Vec < ( ty :: Predicate < ' tcx > , Span ) > {
2140
+ ) -> Vec < ( Predicate < ' tcx > , Span ) > {
2066
2141
match * bound {
2067
2142
hir:: GenericBound :: Trait ( ref tr, hir:: TraitBoundModifier :: None ) => {
2068
2143
let mut projections = Vec :: new ( ) ;
@@ -2076,7 +2151,7 @@ fn predicates_from_bound<'tcx>(
2076
2151
hir:: GenericBound :: Outlives ( ref lifetime) => {
2077
2152
let region = astconv. ast_region_to_region ( lifetime, None ) ;
2078
2153
let pred = ty:: Binder :: bind ( ty:: OutlivesPredicate ( param_ty, region) ) ;
2079
- vec ! [ ( ty :: Predicate :: TypeOutlives ( pred) , lifetime. span) ]
2154
+ vec ! [ ( Predicate :: TypeOutlives ( pred) , lifetime. span) ]
2080
2155
}
2081
2156
hir:: GenericBound :: Trait ( _, hir:: TraitBoundModifier :: Maybe ) => vec ! [ ] ,
2082
2157
}
0 commit comments