39
39
//!
40
40
//! Splitting is implemented in the [`Constructor::split`] function. We don't do splitting for
41
41
//! or-patterns; instead we just try the alternatives one-by-one. For details on splitting
42
- //! wildcards, see [`SplitWildcard`]; for integer ranges, see [`SplitIntRange `]; for slices, see
42
+ //! wildcards, see [`SplitWildcard`]; for integer ranges, see [`IntRange::split `]; for slices, see
43
43
//! [`SplitVarLenSlice`].
44
44
45
45
use std:: cell:: Cell ;
@@ -186,6 +186,93 @@ impl IntRange {
186
186
( lo == other_hi || hi == other_lo) && !self . is_singleton ( ) && !other. is_singleton ( )
187
187
}
188
188
189
+ /// See `Constructor::is_covered_by`
190
+ fn is_covered_by ( & self , other : & Self ) -> bool {
191
+ if self . intersection ( other) . is_some ( ) {
192
+ // Constructor splitting should ensure that all intersections we encounter are actually
193
+ // inclusions.
194
+ assert ! ( self . is_subrange( other) ) ;
195
+ true
196
+ } else {
197
+ false
198
+ }
199
+ }
200
+
201
+ /// Partition a range of integers into disjoint subranges. This does constructor splitting for
202
+ /// integer ranges as explained at the top of the file.
203
+ ///
204
+ /// This returns an output that covers `self`. The output is split so that the only
205
+ /// intersections between an output range and a column range are inclusions. No output range
206
+ /// straddles the boundary of one of the inputs.
207
+ ///
208
+ /// The following input:
209
+ /// ```text
210
+ /// |-------------------------| // `self`
211
+ /// |------| |----------| |----|
212
+ /// |-------| |-------|
213
+ /// ```
214
+ /// would be iterated over as follows:
215
+ /// ```text
216
+ /// ||---|--||-|---|---|---|--|
217
+ /// ```
218
+ fn split (
219
+ & self ,
220
+ column_ranges : impl Iterator < Item = IntRange > ,
221
+ ) -> impl Iterator < Item = IntRange > {
222
+ /// Represents a boundary between 2 integers. Because the intervals spanning boundaries must be
223
+ /// able to cover every integer, we need to be able to represent 2^128 + 1 such boundaries.
224
+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
225
+ enum IntBoundary {
226
+ JustBefore ( u128 ) ,
227
+ AfterMax ,
228
+ }
229
+
230
+ fn unpack_intrange ( range : IntRange ) -> [ IntBoundary ; 2 ] {
231
+ use IntBoundary :: * ;
232
+ let ( lo, hi) = range. boundaries ( ) ;
233
+ let lo = JustBefore ( lo) ;
234
+ let hi = match hi. checked_add ( 1 ) {
235
+ Some ( m) => JustBefore ( m) ,
236
+ None => AfterMax ,
237
+ } ;
238
+ [ lo, hi]
239
+ }
240
+
241
+ // The boundaries of ranges in `column_ranges` intersected with `self`.
242
+ let mut boundaries: Vec < IntBoundary > = column_ranges
243
+ . filter_map ( |r| self . intersection ( & r) )
244
+ . map ( unpack_intrange)
245
+ . flat_map ( |[ lo, hi] | [ lo, hi] )
246
+ . collect ( ) ;
247
+ boundaries. sort_unstable ( ) ;
248
+
249
+ let [ self_start, self_end] = unpack_intrange ( self . clone ( ) ) ;
250
+ // Gather pairs of adjacent boundaries.
251
+ let mut prev_bdy = self_start;
252
+ boundaries
253
+ . into_iter ( )
254
+ // End with the end of the range.
255
+ . chain ( once ( self_end) )
256
+ // List pairs of adjacent boundaries.
257
+ . map ( move |bdy| {
258
+ let ret = ( prev_bdy, bdy) ;
259
+ prev_bdy = bdy;
260
+ ret
261
+ } )
262
+ // Skip duplicates.
263
+ . filter ( |& ( prev_bdy, bdy) | prev_bdy != bdy)
264
+ // Convert back to ranges.
265
+ . map ( move |( prev_bdy, bdy) | {
266
+ use IntBoundary :: * ;
267
+ let range = match ( prev_bdy, bdy) {
268
+ ( JustBefore ( n) , JustBefore ( m) ) if n < m => n..=( m - 1 ) ,
269
+ ( JustBefore ( n) , AfterMax ) => n..=u128:: MAX ,
270
+ _ => unreachable ! ( ) , // Ruled out by the sorting and filtering we did
271
+ } ;
272
+ IntRange { range }
273
+ } )
274
+ }
275
+
189
276
/// Only used for displaying the range properly.
190
277
fn to_pat < ' tcx > ( & self , tcx : TyCtxt < ' tcx > , ty : Ty < ' tcx > ) -> Pat < ' tcx > {
191
278
let ( lo, hi) = self . boundaries ( ) ;
@@ -254,18 +341,6 @@ impl IntRange {
254
341
) ;
255
342
}
256
343
}
257
-
258
- /// See `Constructor::is_covered_by`
259
- fn is_covered_by ( & self , other : & Self ) -> bool {
260
- if self . intersection ( other) . is_some ( ) {
261
- // Constructor splitting should ensure that all intersections we encounter are actually
262
- // inclusions.
263
- assert ! ( self . is_subrange( other) ) ;
264
- true
265
- } else {
266
- false
267
- }
268
- }
269
344
}
270
345
271
346
/// Note: this is often not what we want: e.g. `false` is converted into the range `0..=0` and
@@ -279,101 +354,6 @@ impl fmt::Debug for IntRange {
279
354
}
280
355
}
281
356
282
- /// Represents a border between 2 integers. Because the intervals spanning borders must be able to
283
- /// cover every integer, we need to be able to represent 2^128 + 1 such borders.
284
- #[ derive( Debug , Clone , Copy , PartialEq , Eq , PartialOrd , Ord ) ]
285
- enum IntBorder {
286
- JustBefore ( u128 ) ,
287
- AfterMax ,
288
- }
289
-
290
- /// A range of integers that is partitioned into disjoint subranges. This does constructor
291
- /// splitting for integer ranges as explained at the top of the file.
292
- ///
293
- /// This is fed multiple ranges, and returns an output that covers the input, but is split so that
294
- /// the only intersections between an output range and a seen range are inclusions. No output range
295
- /// straddles the boundary of one of the inputs.
296
- ///
297
- /// The following input:
298
- /// ```text
299
- /// |-------------------------| // `self`
300
- /// |------| |----------| |----|
301
- /// |-------| |-------|
302
- /// ```
303
- /// would be iterated over as follows:
304
- /// ```text
305
- /// ||---|--||-|---|---|---|--|
306
- /// ```
307
- #[ derive( Debug , Clone ) ]
308
- struct SplitIntRange {
309
- /// The range we are splitting
310
- range : IntRange ,
311
- /// The borders of ranges we have seen. They are all contained within `range`. This is kept
312
- /// sorted.
313
- borders : Vec < IntBorder > ,
314
- }
315
-
316
- impl SplitIntRange {
317
- fn new ( range : IntRange ) -> Self {
318
- SplitIntRange { range, borders : Vec :: new ( ) }
319
- }
320
-
321
- /// Internal use
322
- fn to_borders ( r : IntRange ) -> [ IntBorder ; 2 ] {
323
- use IntBorder :: * ;
324
- let ( lo, hi) = r. boundaries ( ) ;
325
- let lo = JustBefore ( lo) ;
326
- let hi = match hi. checked_add ( 1 ) {
327
- Some ( m) => JustBefore ( m) ,
328
- None => AfterMax ,
329
- } ;
330
- [ lo, hi]
331
- }
332
-
333
- /// Add ranges relative to which we split.
334
- fn split ( & mut self , ranges : impl Iterator < Item = IntRange > ) {
335
- let this_range = & self . range ;
336
- let included_ranges = ranges. filter_map ( |r| this_range. intersection ( & r) ) ;
337
- let included_borders = included_ranges. flat_map ( |r| {
338
- let borders = Self :: to_borders ( r) ;
339
- once ( borders[ 0 ] ) . chain ( once ( borders[ 1 ] ) )
340
- } ) ;
341
- self . borders . extend ( included_borders) ;
342
- self . borders . sort_unstable ( ) ;
343
- }
344
-
345
- /// Iterate over the contained ranges.
346
- fn iter ( & self ) -> impl Iterator < Item = IntRange > + Captures < ' _ > {
347
- use IntBorder :: * ;
348
-
349
- let self_range = Self :: to_borders ( self . range . clone ( ) ) ;
350
- // Start with the start of the range.
351
- let mut prev_border = self_range[ 0 ] ;
352
- self . borders
353
- . iter ( )
354
- . copied ( )
355
- // End with the end of the range.
356
- . chain ( once ( self_range[ 1 ] ) )
357
- // List pairs of adjacent borders.
358
- . map ( move |border| {
359
- let ret = ( prev_border, border) ;
360
- prev_border = border;
361
- ret
362
- } )
363
- // Skip duplicates.
364
- . filter ( |( prev_border, border) | prev_border != border)
365
- // Finally, convert to ranges.
366
- . map ( move |( prev_border, border) | {
367
- let range = match ( prev_border, border) {
368
- ( JustBefore ( n) , JustBefore ( m) ) if n < m => n..=( m - 1 ) ,
369
- ( JustBefore ( n) , AfterMax ) => n..=u128:: MAX ,
370
- _ => unreachable ! ( ) , // Ruled out by the sorting and filtering we did
371
- } ;
372
- IntRange { range }
373
- } )
374
- }
375
- }
376
-
377
357
#[ derive( Copy , Clone , Debug , PartialEq , Eq ) ]
378
358
enum SliceKind {
379
359
/// Patterns of length `n` (`[x, y]`).
@@ -733,10 +713,8 @@ impl<'tcx> Constructor<'tcx> {
733
713
// Fast-track if the range is trivial. In particular, we don't do the overlapping
734
714
// ranges check.
735
715
IntRange ( ctor_range) if !ctor_range. is_singleton ( ) => {
736
- let mut split_range = SplitIntRange :: new ( ctor_range. clone ( ) ) ;
737
- let int_ranges = ctors. filter_map ( |ctor| ctor. as_int_range ( ) ) ;
738
- split_range. split ( int_ranges. cloned ( ) ) ;
739
- split_range. iter ( ) . map ( IntRange ) . collect ( )
716
+ let int_ranges = ctors. filter_map ( |ctor| ctor. as_int_range ( ) ) . cloned ( ) ;
717
+ ctor_range. split ( int_ranges) . map ( IntRange ) . collect ( )
740
718
}
741
719
& Slice ( Slice { kind : VarLen ( self_prefix, self_suffix) , array_len } ) => {
742
720
let mut split_self = SplitVarLenSlice :: new ( self_prefix, self_suffix, array_len) ;
0 commit comments