@@ -37,14 +37,12 @@ use std::ops::RangeInclusive;
37
37
///
38
38
/// `IntRange` is never used to encode an empty range or a "range" that wraps
39
39
/// around the (offset) space: i.e., `range.lo <= range.hi`.
40
- #[ derive( Clone , Debug ) ]
41
- pub ( super ) struct IntRange < ' tcx > {
40
+ #[ derive( Clone , Debug , PartialEq , Eq ) ]
41
+ pub ( super ) struct IntRange {
42
42
range : RangeInclusive < u128 > ,
43
- ty : Ty < ' tcx > ,
44
- span : Span ,
45
43
}
46
44
47
- impl < ' tcx > IntRange < ' tcx > {
45
+ impl IntRange {
48
46
#[ inline]
49
47
fn is_integral ( ty : Ty < ' _ > ) -> bool {
50
48
matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Bool )
@@ -59,7 +57,7 @@ impl<'tcx> IntRange<'tcx> {
59
57
}
60
58
61
59
#[ inline]
62
- fn integral_size_and_signed_bias ( tcx : TyCtxt < ' tcx > , ty : Ty < ' _ > ) -> Option < ( Size , u128 ) > {
60
+ fn integral_size_and_signed_bias ( tcx : TyCtxt < ' _ > , ty : Ty < ' _ > ) -> Option < ( Size , u128 ) > {
63
61
match * ty. kind ( ) {
64
62
ty:: Bool => Some ( ( Size :: from_bytes ( 1 ) , 0 ) ) ,
65
63
ty:: Char => Some ( ( Size :: from_bytes ( 4 ) , 0 ) ) ,
@@ -73,12 +71,11 @@ impl<'tcx> IntRange<'tcx> {
73
71
}
74
72
75
73
#[ inline]
76
- fn from_const (
74
+ fn from_const < ' tcx > (
77
75
tcx : TyCtxt < ' tcx > ,
78
76
param_env : ty:: ParamEnv < ' tcx > ,
79
77
value : & Const < ' tcx > ,
80
- span : Span ,
81
- ) -> Option < IntRange < ' tcx > > {
78
+ ) -> Option < IntRange > {
82
79
if let Some ( ( target_size, bias) ) = Self :: integral_size_and_signed_bias ( tcx, value. ty ) {
83
80
let ty = value. ty ;
84
81
let val = ( || {
@@ -95,21 +92,20 @@ impl<'tcx> IntRange<'tcx> {
95
92
value. try_eval_bits ( tcx, param_env, ty)
96
93
} ) ( ) ?;
97
94
let val = val ^ bias;
98
- Some ( IntRange { range : val..=val, ty , span } )
95
+ Some ( IntRange { range : val..=val } )
99
96
} else {
100
97
None
101
98
}
102
99
}
103
100
104
101
#[ inline]
105
- fn from_range (
102
+ fn from_range < ' tcx > (
106
103
tcx : TyCtxt < ' tcx > ,
107
104
lo : u128 ,
108
105
hi : u128 ,
109
106
ty : Ty < ' tcx > ,
110
107
end : & RangeEnd ,
111
- span : Span ,
112
- ) -> Option < IntRange < ' tcx > > {
108
+ ) -> Option < IntRange > {
113
109
if Self :: is_integral ( ty) {
114
110
// Perform a shift if the underlying types are signed,
115
111
// which makes the interval arithmetic simpler.
@@ -120,14 +116,14 @@ impl<'tcx> IntRange<'tcx> {
120
116
// This should have been caught earlier by E0030.
121
117
bug ! ( "malformed range pattern: {}..={}" , lo, ( hi - offset) ) ;
122
118
}
123
- Some ( IntRange { range : lo..=( hi - offset) , ty , span } )
119
+ Some ( IntRange { range : lo..=( hi - offset) } )
124
120
} else {
125
121
None
126
122
}
127
123
}
128
124
129
125
// The return value of `signed_bias` should be XORed with an endpoint to encode/decode it.
130
- fn signed_bias ( tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> u128 {
126
+ fn signed_bias ( tcx : TyCtxt < ' _ > , ty : Ty < ' _ > ) -> u128 {
131
127
match * ty. kind ( ) {
132
128
ty:: Int ( ity) => {
133
129
let bits = Integer :: from_attr ( & tcx, SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
@@ -142,12 +138,10 @@ impl<'tcx> IntRange<'tcx> {
142
138
}
143
139
144
140
fn intersection ( & self , other : & Self ) -> Option < Self > {
145
- let ty = self . ty ;
146
141
let ( lo, hi) = self . boundaries ( ) ;
147
142
let ( other_lo, other_hi) = other. boundaries ( ) ;
148
143
if lo <= other_hi && other_lo <= hi {
149
- let span = other. span ;
150
- Some ( IntRange { range : max ( lo, other_lo) ..=min ( hi, other_hi) , ty, span } )
144
+ Some ( IntRange { range : max ( lo, other_lo) ..=min ( hi, other_hi) } )
151
145
} else {
152
146
None
153
147
}
@@ -170,24 +164,23 @@ impl<'tcx> IntRange<'tcx> {
170
164
lo == other_hi || hi == other_lo
171
165
}
172
166
173
- fn to_pat ( & self , tcx : TyCtxt < ' tcx > ) -> Pat < ' tcx > {
167
+ fn to_pat < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Pat < ' tcx > {
174
168
let ( lo, hi) = self . boundaries ( ) ;
175
169
176
- let bias = IntRange :: signed_bias ( tcx, self . ty ) ;
170
+ let bias = IntRange :: signed_bias ( tcx, ty) ;
177
171
let ( lo, hi) = ( lo ^ bias, hi ^ bias) ;
178
172
179
- let ty = ty:: ParamEnv :: empty ( ) . and ( self . ty ) ;
180
- let lo_const = ty:: Const :: from_bits ( tcx, lo, ty ) ;
181
- let hi_const = ty:: Const :: from_bits ( tcx, hi, ty ) ;
173
+ let env = ty:: ParamEnv :: empty ( ) . and ( ty) ;
174
+ let lo_const = ty:: Const :: from_bits ( tcx, lo, env ) ;
175
+ let hi_const = ty:: Const :: from_bits ( tcx, hi, env ) ;
182
176
183
177
let kind = if lo == hi {
184
178
PatKind :: Constant { value : lo_const }
185
179
} else {
186
180
PatKind :: Range ( PatRange { lo : lo_const, hi : hi_const, end : RangeEnd :: Included } )
187
181
} ;
188
182
189
- // This is a brand new pattern, so we don't reuse `self.span`.
190
- Pat { ty : self . ty , span : DUMMY_SP , kind : Box :: new ( kind) }
183
+ Pat { ty, span : DUMMY_SP , kind : Box :: new ( kind) }
191
184
}
192
185
193
186
/// For exhaustive integer matching, some constructors are grouped within other constructors
@@ -222,13 +215,11 @@ impl<'tcx> IntRange<'tcx> {
222
215
/// boundaries for each interval range, sort them, then create constructors for each new interval
223
216
/// between every pair of boundary points. (This essentially sums up to performing the intuitive
224
217
/// merging operation depicted above.)
225
- fn split < ' p > (
218
+ fn split < ' p , ' tcx > (
226
219
& self ,
227
220
pcx : PatCtxt < ' _ , ' p , ' tcx > ,
228
221
hir_id : Option < HirId > ,
229
222
) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
230
- let ty = pcx. ty ;
231
-
232
223
/// Represents a border between 2 integers. Because the intervals spanning borders
233
224
/// must be able to cover every integer, we need to be able to represent
234
225
/// 2^128 + 1 such borders.
@@ -239,7 +230,7 @@ impl<'tcx> IntRange<'tcx> {
239
230
}
240
231
241
232
// A function for extracting the borders of an integer interval.
242
- fn range_borders ( r : IntRange < ' _ > ) -> impl Iterator < Item = Border > {
233
+ fn range_borders ( r : IntRange ) -> impl Iterator < Item = Border > {
243
234
let ( lo, hi) = r. range . into_inner ( ) ;
244
235
let from = Border :: JustBefore ( lo) ;
245
236
let to = match hi. checked_add ( 1 ) {
@@ -257,21 +248,23 @@ impl<'tcx> IntRange<'tcx> {
257
248
// class lies between 2 borders.
258
249
let row_borders = pcx
259
250
. matrix
260
- . head_ctors ( pcx. cx )
261
- . filter_map ( |ctor| ctor. as_int_range ( ) )
262
- . filter_map ( |range| {
251
+ . head_ctors_and_spans ( pcx. cx )
252
+ . filter_map ( |( ctor, span ) | Some ( ( ctor. as_int_range ( ) ? , span ) ) )
253
+ . filter_map ( |( range, span ) | {
263
254
let intersection = self . intersection ( & range) ;
264
255
let should_lint = self . suspicious_intersection ( & range) ;
265
256
if let ( Some ( range) , 1 , true ) = ( & intersection, row_len, should_lint) {
266
257
// FIXME: for now, only check for overlapping ranges on simple range
267
258
// patterns. Otherwise with the current logic the following is detected
268
259
// as overlapping:
269
- // match (10u8, true) {
270
- // (0 ..= 125, false) => {}
271
- // (126 ..= 255, false) => {}
272
- // (0 ..= 255, true) => {}
273
- // }
274
- overlaps. push ( range. clone ( ) ) ;
260
+ // ```
261
+ // match (0u8, true) {
262
+ // (0 ..= 125, false) => {}
263
+ // (125 ..= 255, true) => {}
264
+ // _ => {}
265
+ // }
266
+ // ```
267
+ overlaps. push ( ( range. clone ( ) , span) ) ;
275
268
}
276
269
intersection
277
270
} )
@@ -280,7 +273,7 @@ impl<'tcx> IntRange<'tcx> {
280
273
let mut borders: Vec < _ > = row_borders. chain ( self_borders) . collect ( ) ;
281
274
borders. sort_unstable ( ) ;
282
275
283
- self . lint_overlapping_patterns ( pcx. cx . tcx , hir_id, ty , overlaps) ;
276
+ self . lint_overlapping_patterns ( pcx, hir_id, overlaps) ;
284
277
285
278
// We're going to iterate through every adjacent pair of borders, making sure that
286
279
// each represents an interval of nonnegative length, and convert each such
@@ -298,33 +291,32 @@ impl<'tcx> IntRange<'tcx> {
298
291
[ Border :: JustBefore ( n) , Border :: AfterMax ] => Some ( n..=u128:: MAX ) ,
299
292
[ Border :: AfterMax , _] => None ,
300
293
} )
301
- . map ( |range| IntRange { range, ty , span : pcx . span } )
294
+ . map ( |range| IntRange { range } )
302
295
. map ( IntRange )
303
296
. collect ( )
304
297
}
305
298
306
299
fn lint_overlapping_patterns (
307
300
& self ,
308
- tcx : TyCtxt < ' tcx > ,
301
+ pcx : PatCtxt < ' _ , ' _ , ' _ > ,
309
302
hir_id : Option < HirId > ,
310
- ty : Ty < ' tcx > ,
311
- overlaps : Vec < IntRange < ' tcx > > ,
303
+ overlaps : Vec < ( IntRange , Span ) > ,
312
304
) {
313
305
if let ( true , Some ( hir_id) ) = ( !overlaps. is_empty ( ) , hir_id) {
314
- tcx. struct_span_lint_hir (
306
+ pcx . cx . tcx . struct_span_lint_hir (
315
307
lint:: builtin:: OVERLAPPING_PATTERNS ,
316
308
hir_id,
317
- self . span ,
309
+ pcx . span ,
318
310
|lint| {
319
311
let mut err = lint. build ( "multiple patterns covering the same range" ) ;
320
- err. span_label ( self . span , "overlapping patterns" ) ;
321
- for int_range in overlaps {
312
+ err. span_label ( pcx . span , "overlapping patterns" ) ;
313
+ for ( int_range, span ) in overlaps {
322
314
// Use the real type for user display of the ranges:
323
315
err. span_label (
324
- int_range . span ,
316
+ span,
325
317
& format ! (
326
318
"this range overlaps on `{}`" ,
327
- IntRange { range : int_range. range , ty , span : DUMMY_SP } . to_pat( tcx) ,
319
+ int_range. to_pat( pcx . cx . tcx, pcx . ty ) ,
328
320
) ,
329
321
) ;
330
322
}
@@ -347,13 +339,6 @@ impl<'tcx> IntRange<'tcx> {
347
339
}
348
340
}
349
341
350
- /// Ignore spans when comparing, they don't carry semantic information as they are only for lints.
351
- impl < ' tcx > std:: cmp:: PartialEq for IntRange < ' tcx > {
352
- fn eq ( & self , other : & Self ) -> bool {
353
- self . range == other. range && self . ty == other. ty
354
- }
355
- }
356
-
357
342
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
358
343
enum SliceKind {
359
344
/// Patterns of length `n` (`[x, y]`).
@@ -547,7 +532,7 @@ pub(super) enum Constructor<'tcx> {
547
532
/// Enum variants.
548
533
Variant ( DefId ) ,
549
534
/// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
550
- IntRange ( IntRange < ' tcx > ) ,
535
+ IntRange ( IntRange ) ,
551
536
/// Ranges of floating-point literal values (`2.0..=5.2`).
552
537
FloatRange ( & ' tcx ty:: Const < ' tcx > , & ' tcx ty:: Const < ' tcx > , RangeEnd ) ,
553
538
/// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
@@ -570,7 +555,7 @@ impl<'tcx> Constructor<'tcx> {
570
555
matches ! ( self , Wildcard )
571
556
}
572
557
573
- fn as_int_range ( & self ) -> Option < & IntRange < ' tcx > > {
558
+ fn as_int_range ( & self ) -> Option < & IntRange > {
574
559
match self {
575
560
IntRange ( range) => Some ( range) ,
576
561
_ => None ,
@@ -605,8 +590,7 @@ impl<'tcx> Constructor<'tcx> {
605
590
Variant ( adt_def. variants [ variant_index] . def_id )
606
591
}
607
592
PatKind :: Constant { value } => {
608
- if let Some ( int_range) = IntRange :: from_const ( cx. tcx , cx. param_env , value, pat. span )
609
- {
593
+ if let Some ( int_range) = IntRange :: from_const ( cx. tcx , cx. param_env , value) {
610
594
IntRange ( int_range)
611
595
} else {
612
596
match pat. ty . kind ( ) {
@@ -630,7 +614,6 @@ impl<'tcx> Constructor<'tcx> {
630
614
hi. eval_bits ( cx. tcx , cx. param_env , hi. ty ) ,
631
615
ty,
632
616
& end,
633
- pat. span ,
634
617
) {
635
618
IntRange ( int_range)
636
619
} else {
@@ -815,8 +798,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
815
798
let make_range = |start, end| {
816
799
IntRange (
817
800
// `unwrap()` is ok because we know the type is an integer.
818
- IntRange :: from_range ( cx. tcx , start, end, pcx. ty , & RangeEnd :: Included , pcx. span )
819
- . unwrap ( ) ,
801
+ IntRange :: from_range ( cx. tcx , start, end, pcx. ty , & RangeEnd :: Included ) . unwrap ( ) ,
820
802
)
821
803
} ;
822
804
match pcx. ty . kind ( ) {
@@ -1221,7 +1203,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1221
1203
} ,
1222
1204
& Str ( value) => PatKind :: Constant { value } ,
1223
1205
& FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1224
- IntRange ( range) => return range. to_pat ( pcx. cx . tcx ) ,
1206
+ IntRange ( range) => return range. to_pat ( pcx. cx . tcx , pcx . ty ) ,
1225
1207
NonExhaustive => PatKind :: Wild ,
1226
1208
Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
1227
1209
Wildcard => bug ! (
0 commit comments