@@ -37,14 +37,12 @@ use std::ops::RangeInclusive;
3737///
3838/// `IntRange` is never used to encode an empty range or a "range" that wraps
3939/// 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 {
4242 range : RangeInclusive < u128 > ,
43- ty : Ty < ' tcx > ,
44- span : Span ,
4543}
4644
47- impl < ' tcx > IntRange < ' tcx > {
45+ impl IntRange {
4846 #[ inline]
4947 fn is_integral ( ty : Ty < ' _ > ) -> bool {
5048 matches ! ( ty. kind( ) , ty:: Char | ty:: Int ( _) | ty:: Uint ( _) | ty:: Bool )
@@ -59,7 +57,7 @@ impl<'tcx> IntRange<'tcx> {
5957 }
6058
6159 #[ 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 ) > {
6361 match * ty. kind ( ) {
6462 ty:: Bool => Some ( ( Size :: from_bytes ( 1 ) , 0 ) ) ,
6563 ty:: Char => Some ( ( Size :: from_bytes ( 4 ) , 0 ) ) ,
@@ -73,12 +71,11 @@ impl<'tcx> IntRange<'tcx> {
7371 }
7472
7573 #[ inline]
76- fn from_const (
74+ fn from_const < ' tcx > (
7775 tcx : TyCtxt < ' tcx > ,
7876 param_env : ty:: ParamEnv < ' tcx > ,
7977 value : & Const < ' tcx > ,
80- span : Span ,
81- ) -> Option < IntRange < ' tcx > > {
78+ ) -> Option < IntRange > {
8279 if let Some ( ( target_size, bias) ) = Self :: integral_size_and_signed_bias ( tcx, value. ty ) {
8380 let ty = value. ty ;
8481 let val = ( || {
@@ -95,21 +92,20 @@ impl<'tcx> IntRange<'tcx> {
9592 value. try_eval_bits ( tcx, param_env, ty)
9693 } ) ( ) ?;
9794 let val = val ^ bias;
98- Some ( IntRange { range : val..=val, ty , span } )
95+ Some ( IntRange { range : val..=val } )
9996 } else {
10097 None
10198 }
10299 }
103100
104101 #[ inline]
105- fn from_range (
102+ fn from_range < ' tcx > (
106103 tcx : TyCtxt < ' tcx > ,
107104 lo : u128 ,
108105 hi : u128 ,
109106 ty : Ty < ' tcx > ,
110107 end : & RangeEnd ,
111- span : Span ,
112- ) -> Option < IntRange < ' tcx > > {
108+ ) -> Option < IntRange > {
113109 if Self :: is_integral ( ty) {
114110 // Perform a shift if the underlying types are signed,
115111 // which makes the interval arithmetic simpler.
@@ -120,14 +116,14 @@ impl<'tcx> IntRange<'tcx> {
120116 // This should have been caught earlier by E0030.
121117 bug ! ( "malformed range pattern: {}..={}" , lo, ( hi - offset) ) ;
122118 }
123- Some ( IntRange { range : lo..=( hi - offset) , ty , span } )
119+ Some ( IntRange { range : lo..=( hi - offset) } )
124120 } else {
125121 None
126122 }
127123 }
128124
129125 // 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 {
131127 match * ty. kind ( ) {
132128 ty:: Int ( ity) => {
133129 let bits = Integer :: from_attr ( & tcx, SignedInt ( ity) ) . size ( ) . bits ( ) as u128 ;
@@ -142,12 +138,10 @@ impl<'tcx> IntRange<'tcx> {
142138 }
143139
144140 fn intersection ( & self , other : & Self ) -> Option < Self > {
145- let ty = self . ty ;
146141 let ( lo, hi) = self . boundaries ( ) ;
147142 let ( other_lo, other_hi) = other. boundaries ( ) ;
148143 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) } )
151145 } else {
152146 None
153147 }
@@ -170,24 +164,23 @@ impl<'tcx> IntRange<'tcx> {
170164 lo == other_hi || hi == other_lo
171165 }
172166
173- fn to_pat ( & self , tcx : TyCtxt < ' tcx > ) -> Pat < ' tcx > {
167+ fn to_pat < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Pat < ' tcx > {
174168 let ( lo, hi) = self . boundaries ( ) ;
175169
176- let bias = IntRange :: signed_bias ( tcx, self . ty ) ;
170+ let bias = IntRange :: signed_bias ( tcx, ty) ;
177171 let ( lo, hi) = ( lo ^ bias, hi ^ bias) ;
178172
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 ) ;
182176
183177 let kind = if lo == hi {
184178 PatKind :: Constant { value : lo_const }
185179 } else {
186180 PatKind :: Range ( PatRange { lo : lo_const, hi : hi_const, end : RangeEnd :: Included } )
187181 } ;
188182
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) }
191184 }
192185
193186 /// For exhaustive integer matching, some constructors are grouped within other constructors
@@ -222,13 +215,11 @@ impl<'tcx> IntRange<'tcx> {
222215 /// boundaries for each interval range, sort them, then create constructors for each new interval
223216 /// between every pair of boundary points. (This essentially sums up to performing the intuitive
224217 /// merging operation depicted above.)
225- fn split < ' p > (
218+ fn split < ' p , ' tcx > (
226219 & self ,
227220 pcx : PatCtxt < ' _ , ' p , ' tcx > ,
228221 hir_id : Option < HirId > ,
229222 ) -> SmallVec < [ Constructor < ' tcx > ; 1 ] > {
230- let ty = pcx. ty ;
231-
232223 /// Represents a border between 2 integers. Because the intervals spanning borders
233224 /// must be able to cover every integer, we need to be able to represent
234225 /// 2^128 + 1 such borders.
@@ -239,7 +230,7 @@ impl<'tcx> IntRange<'tcx> {
239230 }
240231
241232 // 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 > {
243234 let ( lo, hi) = r. range . into_inner ( ) ;
244235 let from = Border :: JustBefore ( lo) ;
245236 let to = match hi. checked_add ( 1 ) {
@@ -257,21 +248,23 @@ impl<'tcx> IntRange<'tcx> {
257248 // class lies between 2 borders.
258249 let row_borders = pcx
259250 . 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 ) | {
263254 let intersection = self . intersection ( & range) ;
264255 let should_lint = self . suspicious_intersection ( & range) ;
265256 if let ( Some ( range) , 1 , true ) = ( & intersection, row_len, should_lint) {
266257 // FIXME: for now, only check for overlapping ranges on simple range
267258 // patterns. Otherwise with the current logic the following is detected
268259 // 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) ) ;
275268 }
276269 intersection
277270 } )
@@ -280,7 +273,7 @@ impl<'tcx> IntRange<'tcx> {
280273 let mut borders: Vec < _ > = row_borders. chain ( self_borders) . collect ( ) ;
281274 borders. sort_unstable ( ) ;
282275
283- self . lint_overlapping_patterns ( pcx. cx . tcx , hir_id, ty , overlaps) ;
276+ self . lint_overlapping_patterns ( pcx, hir_id, overlaps) ;
284277
285278 // We're going to iterate through every adjacent pair of borders, making sure that
286279 // each represents an interval of nonnegative length, and convert each such
@@ -298,33 +291,32 @@ impl<'tcx> IntRange<'tcx> {
298291 [ Border :: JustBefore ( n) , Border :: AfterMax ] => Some ( n..=u128:: MAX ) ,
299292 [ Border :: AfterMax , _] => None ,
300293 } )
301- . map ( |range| IntRange { range, ty , span : pcx . span } )
294+ . map ( |range| IntRange { range } )
302295 . map ( IntRange )
303296 . collect ( )
304297 }
305298
306299 fn lint_overlapping_patterns (
307300 & self ,
308- tcx : TyCtxt < ' tcx > ,
301+ pcx : PatCtxt < ' _ , ' _ , ' _ > ,
309302 hir_id : Option < HirId > ,
310- ty : Ty < ' tcx > ,
311- overlaps : Vec < IntRange < ' tcx > > ,
303+ overlaps : Vec < ( IntRange , Span ) > ,
312304 ) {
313305 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 (
315307 lint:: builtin:: OVERLAPPING_PATTERNS ,
316308 hir_id,
317- self . span ,
309+ pcx . span ,
318310 |lint| {
319311 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 {
322314 // Use the real type for user display of the ranges:
323315 err. span_label (
324- int_range . span ,
316+ span,
325317 & format ! (
326318 "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 ) ,
328320 ) ,
329321 ) ;
330322 }
@@ -347,13 +339,6 @@ impl<'tcx> IntRange<'tcx> {
347339 }
348340}
349341
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-
357342#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
358343enum SliceKind {
359344 /// Patterns of length `n` (`[x, y]`).
@@ -547,7 +532,7 @@ pub(super) enum Constructor<'tcx> {
547532 /// Enum variants.
548533 Variant ( DefId ) ,
549534 /// Ranges of integer literal values (`2`, `2..=5` or `2..5`).
550- IntRange ( IntRange < ' tcx > ) ,
535+ IntRange ( IntRange ) ,
551536 /// Ranges of floating-point literal values (`2.0..=5.2`).
552537 FloatRange ( & ' tcx ty:: Const < ' tcx > , & ' tcx ty:: Const < ' tcx > , RangeEnd ) ,
553538 /// String literals. Strings are not quite the same as `&[u8]` so we treat them separately.
@@ -570,7 +555,7 @@ impl<'tcx> Constructor<'tcx> {
570555 matches ! ( self , Wildcard )
571556 }
572557
573- fn as_int_range ( & self ) -> Option < & IntRange < ' tcx > > {
558+ fn as_int_range ( & self ) -> Option < & IntRange > {
574559 match self {
575560 IntRange ( range) => Some ( range) ,
576561 _ => None ,
@@ -605,8 +590,7 @@ impl<'tcx> Constructor<'tcx> {
605590 Variant ( adt_def. variants [ variant_index] . def_id )
606591 }
607592 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) {
610594 IntRange ( int_range)
611595 } else {
612596 match pat. ty . kind ( ) {
@@ -630,7 +614,6 @@ impl<'tcx> Constructor<'tcx> {
630614 hi. eval_bits ( cx. tcx , cx. param_env , hi. ty ) ,
631615 ty,
632616 & end,
633- pat. span ,
634617 ) {
635618 IntRange ( int_range)
636619 } else {
@@ -815,8 +798,7 @@ fn all_constructors<'p, 'tcx>(pcx: PatCtxt<'_, 'p, 'tcx>) -> Vec<Constructor<'tc
815798 let make_range = |start, end| {
816799 IntRange (
817800 // `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 ( ) ,
820802 )
821803 } ;
822804 match pcx. ty . kind ( ) {
@@ -1221,7 +1203,7 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
12211203 } ,
12221204 & Str ( value) => PatKind :: Constant { value } ,
12231205 & 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 ) ,
12251207 NonExhaustive => PatKind :: Wild ,
12261208 Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
12271209 Wildcard => bug ! (
0 commit comments