137
137
//! S(c, (r_1, p_2, .., p_n))
138
138
//! S(c, (r_2, p_2, .., p_n))
139
139
//!
140
- //! 2. We can pop a wildcard off the top of the stack. This is called `D( p)`, where `p` is
141
- //! a pattern-stack.
140
+ //! 2. We can pop a wildcard off the top of the stack. This is called `S(_, p)`, where `p` is
141
+ //! a pattern-stack. Note: the paper calls this `D(p)`.
142
142
//! This is used when we know there are missing constructor cases, but there might be
143
143
//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check
144
144
//! all its *other* components.
150
150
//! p_2, .., p_n
151
151
//! 2.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
152
152
//! stack.
153
- //! D( (r_1, p_2, .., p_n))
154
- //! D( (r_2, p_2, .., p_n))
153
+ //! S(_, (r_1, p_2, .., p_n))
154
+ //! S(_, (r_2, p_2, .., p_n))
155
155
//!
156
156
//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
157
157
//! exhaustive integer matching rules, so they're written here for posterity.
205
205
//! That's almost correct, but only works if there were no wildcards in those first
206
206
//! components. So we need to check that `p` is useful with respect to the rows that
207
207
//! start with a wildcard, if there are any. This is where `D` comes in:
208
- //! `U(P, p) := U(D( P), D( p))`
208
+ //! `U(P, p) := U(S(_, P), S(_, p))`
209
209
//!
210
210
//! For example, if `P` is:
211
211
//!
@@ -358,10 +358,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
358
358
PatStack ( vec)
359
359
}
360
360
361
- fn from_slice ( s : & [ & ' p Pat < ' tcx > ] ) -> Self {
362
- PatStack ( SmallVec :: from_slice ( s) )
363
- }
364
-
365
361
fn is_empty ( & self ) -> bool {
366
362
self . 0 . is_empty ( )
367
363
}
@@ -374,10 +370,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
374
370
self . 0 [ 0 ]
375
371
}
376
372
377
- fn to_tail ( & self ) -> Self {
378
- PatStack :: from_slice ( & self . 0 [ 1 ..] )
379
- }
380
-
381
373
fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
382
374
self . 0 . iter ( ) . copied ( )
383
375
}
@@ -401,11 +393,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
401
393
}
402
394
}
403
395
404
- /// This computes `D(self)`. See top of the file for explanations.
405
- fn specialize_wildcard ( & self ) -> Option < Self > {
406
- if self . head ( ) . is_wildcard ( ) { Some ( self . to_tail ( ) ) } else { None }
407
- }
408
-
409
396
/// This computes `S(constructor, self)`. See top of the file for explanations.
410
397
///
411
398
/// This is the main specialization step. It expands the pattern
@@ -427,15 +414,13 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
427
414
is_my_head_ctor : bool ,
428
415
) -> Option < PatStack < ' p , ' tcx > > {
429
416
// We return `None` if `ctor` is not covered by `self.head()`. If `ctor` is known to be
430
- // derived from `self.head()`, or if `self.head()` is a wildcard, then we don't need to
431
- // check; otherwise, we compute the constructor of `self.head()` and check for constructor
432
- // inclusion.
417
+ // derived from `self.head()`, then we don't need to check; otherwise, we compute the
418
+ // constructor of `self.head()` and check for constructor inclusion.
433
419
// Note that this shortcut is also necessary for correctness: a pattern should always be
434
420
// specializable with its own constructor, even in cases where we refuse to inspect values like
435
421
// opaque constants.
436
- if !self . head ( ) . is_wildcard ( ) && !is_my_head_ctor {
437
- // `unwrap` is safe because `pat` is not a wildcard.
438
- let head_ctor = pat_constructor ( cx. tcx , cx. param_env , self . head ( ) ) . unwrap ( ) ;
422
+ if !is_my_head_ctor {
423
+ let head_ctor = pat_constructor ( cx. tcx , cx. param_env , self . head ( ) ) ;
439
424
if !ctor. is_covered_by ( cx, & head_ctor, self . head ( ) . ty ) {
440
425
return None ;
441
426
}
@@ -480,8 +465,8 @@ enum SpecializationCache {
480
465
/// so it is possible to precompute the result of `Matrix::specialize_constructor` at a
481
466
/// lower computational complexity.
482
467
/// `lookup` is responsible for holding the precomputed result of
483
- /// `Matrix::specialize_constructor` , while `wilds` is used for two purposes: the first one is
484
- /// the precomputed result of `Matrix::specialize_wildcard` , and the second is to be used as a
468
+ /// specialization , while `wilds` is used for two purposes: the first one is
469
+ /// the precomputed result of specialization with a wildcard , and the second is to be used as a
485
470
/// fallback for `Matrix::specialize_constructor` when it tries to apply a constructor that
486
471
/// has not been seen in the `Matrix`. See `update_cache` for further explanations.
487
472
Variants { lookup : FxHashMap < DefId , SmallVec < [ usize ; 1 ] > > , wilds : SmallVec < [ usize ; 1 ] > } ,
@@ -553,9 +538,9 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
553
538
v. push ( idx) ;
554
539
}
555
540
// Per rule 2.1 and 2.2 in the top-level comments, only wildcard patterns
556
- // are included in the result of `specialize_wildcard` .
541
+ // are included in the result of specialization with a wildcard .
557
542
// What we do here is to track the wildcards we have seen; so in addition to
558
- // acting as the precomputed result of `specialize_wildcard` , `wilds` also
543
+ // acting as the precomputed result of specialization with a wildcard , `wilds` also
559
544
// serves as the default value of `specialize_constructor` for constructors
560
545
// that are not in `lookup`.
561
546
wilds. push ( idx) ;
@@ -585,30 +570,6 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
585
570
self . patterns . iter ( ) . map ( |r| r. head ( ) )
586
571
}
587
572
588
- /// This computes `D(self)`. See top of the file for explanations.
589
- fn specialize_wildcard ( & self ) -> Self {
590
- match & self . cache {
591
- SpecializationCache :: Variants { wilds, .. } => {
592
- let result =
593
- wilds. iter ( ) . filter_map ( |& i| self . patterns [ i] . specialize_wildcard ( ) ) . collect ( ) ;
594
- // When debug assertions are enabled, check the results against the "slow path"
595
- // result.
596
- debug_assert_eq ! (
597
- result,
598
- Self {
599
- patterns: self . patterns. clone( ) ,
600
- cache: SpecializationCache :: Incompatible
601
- }
602
- . specialize_wildcard( )
603
- ) ;
604
- result
605
- }
606
- SpecializationCache :: Incompatible => {
607
- self . patterns . iter ( ) . filter_map ( |r| r. specialize_wildcard ( ) ) . collect ( )
608
- }
609
- }
610
- }
611
-
612
573
/// This computes `S(constructor, self)`. See top of the file for explanations.
613
574
fn specialize_constructor (
614
575
& self ,
@@ -618,24 +579,30 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
618
579
) -> Matrix < ' p , ' tcx > {
619
580
match & self . cache {
620
581
SpecializationCache :: Variants { lookup, wilds } => {
621
- let result : Self = if let Constructor :: Variant ( id) = constructor {
582
+ let cached = if let Constructor :: Variant ( id) = constructor {
622
583
lookup
623
584
. get ( id)
624
585
// Default to `wilds` for absent keys. See `update_cache` for an explanation.
625
586
. unwrap_or ( & wilds)
626
- . iter ( )
627
- . filter_map ( |& i| {
628
- self . patterns [ i] . specialize_constructor (
629
- cx,
630
- constructor,
631
- ctor_wild_subpatterns,
632
- false ,
633
- )
634
- } )
635
- . collect ( )
587
+ } else if let Wildcard = constructor {
588
+ & wilds
636
589
} else {
637
- unreachable ! ( )
590
+ bug ! (
591
+ "unexpected constructor encountered while dealing with matrix cache: {:?}" ,
592
+ constructor
593
+ ) ;
638
594
} ;
595
+ let result: Self = cached
596
+ . iter ( )
597
+ . filter_map ( |& i| {
598
+ self . patterns [ i] . specialize_constructor (
599
+ cx,
600
+ constructor,
601
+ ctor_wild_subpatterns,
602
+ false ,
603
+ )
604
+ } )
605
+ . collect ( ) ;
639
606
// When debug assertions are enabled, check the results against the "slow path"
640
607
// result.
641
608
debug_assert_eq ! (
@@ -939,8 +906,10 @@ impl Slice {
939
906
_ => return smallvec ! [ Slice ( self ) ] ,
940
907
} ;
941
908
942
- let head_ctors =
943
- matrix. heads ( ) . filter_map ( |pat| pat_constructor ( cx. tcx , cx. param_env , pat) ) ;
909
+ let head_ctors = matrix
910
+ . heads ( )
911
+ . map ( |p| pat_constructor ( cx. tcx , cx. param_env , p) )
912
+ . filter ( |c| !c. is_wildcard ( ) ) ;
944
913
945
914
let mut max_prefix_len = self_prefix;
946
915
let mut max_suffix_len = self_suffix;
@@ -1026,9 +995,18 @@ enum Constructor<'tcx> {
1026
995
Opaque ,
1027
996
/// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
1028
997
NonExhaustive ,
998
+ /// Wildcard pattern.
999
+ Wildcard ,
1029
1000
}
1030
1001
1031
1002
impl < ' tcx > Constructor < ' tcx > {
1003
+ fn is_wildcard ( & self ) -> bool {
1004
+ match self {
1005
+ Wildcard => true ,
1006
+ _ => false ,
1007
+ }
1008
+ }
1009
+
1032
1010
fn variant_index_for_adt ( & self , adt : & ' tcx ty:: AdtDef ) -> VariantIdx {
1033
1011
match * self {
1034
1012
Variant ( id) => adt. variant_index_with_id ( id) ,
@@ -1120,7 +1098,8 @@ impl<'tcx> Constructor<'tcx> {
1120
1098
}
1121
1099
// This constructor is never covered by anything else
1122
1100
NonExhaustive => vec ! [ NonExhaustive ] ,
1123
- Opaque => bug ! ( "unexpected opaque ctor {:?} found in all_ctors" , self ) ,
1101
+ Opaque => bug ! ( "found unexpected opaque ctor in all_ctors" ) ,
1102
+ Wildcard => bug ! ( "found unexpected wildcard ctor in all_ctors" ) ,
1124
1103
}
1125
1104
}
1126
1105
@@ -1173,6 +1152,11 @@ impl<'tcx> Constructor<'tcx> {
1173
1152
ty : Ty < ' tcx > ,
1174
1153
) -> bool {
1175
1154
match ( self , other) {
1155
+ // Wildcards cover anything
1156
+ ( _, Wildcard ) => true ,
1157
+ // Wildcards are only covered by wildcards
1158
+ ( Wildcard , _) => false ,
1159
+
1176
1160
( Single , Single ) => true ,
1177
1161
( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
1178
1162
@@ -1302,7 +1286,8 @@ impl<'tcx> Constructor<'tcx> {
1302
1286
& FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
1303
1287
IntRange ( range) => return range. to_pat ( cx. tcx ) ,
1304
1288
NonExhaustive => PatKind :: Wild ,
1305
- Opaque => bug ! ( "we should not try to apply an opaque constructor {:?}" , self ) ,
1289
+ Opaque => bug ! ( "we should not try to apply an opaque constructor" ) ,
1290
+ Wildcard => bug ! ( "we should not try to apply a wildcard constructor" ) ,
1306
1291
} ;
1307
1292
1308
1293
Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1454,7 +1439,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
1454
1439
}
1455
1440
_ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
1456
1441
} ,
1457
- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque => Fields :: empty ( ) ,
1442
+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1443
+ Fields :: empty ( )
1444
+ }
1458
1445
} ;
1459
1446
debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
1460
1447
ret
@@ -2011,19 +1998,7 @@ impl<'tcx> IntRange<'tcx> {
2011
1998
) -> Option < IntRange < ' tcx > > {
2012
1999
// This MUST be kept in sync with `pat_constructor`.
2013
2000
match * pat. kind {
2014
- PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2015
- PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
2016
-
2017
- PatKind :: Binding { .. }
2018
- | PatKind :: Wild
2019
- | PatKind :: Leaf { .. }
2020
- | PatKind :: Deref { .. }
2021
- | PatKind :: Variant { .. }
2022
- | PatKind :: Array { .. }
2023
- | PatKind :: Slice { .. } => None ,
2024
-
2025
2001
PatKind :: Constant { value } => Self :: from_const ( tcx, param_env, value, pat. span ) ,
2026
-
2027
2002
PatKind :: Range ( PatRange { lo, hi, end } ) => {
2028
2003
let ty = lo. ty ;
2029
2004
Self :: from_range (
@@ -2035,6 +2010,7 @@ impl<'tcx> IntRange<'tcx> {
2035
2010
pat. span ,
2036
2011
)
2037
2012
}
2013
+ _ => None ,
2038
2014
}
2039
2015
}
2040
2016
@@ -2436,7 +2412,8 @@ crate fn is_useful<'p, 'tcx>(
2436
2412
2437
2413
debug ! ( "is_useful_expand_first_col: pcx={:#?}, expanding {:#?}" , pcx, v. head( ) ) ;
2438
2414
2439
- let ret = if let Some ( constructor) = pat_constructor ( cx. tcx , cx. param_env , v. head ( ) ) {
2415
+ let constructor = pat_constructor ( cx. tcx , cx. param_env , v. head ( ) ) ;
2416
+ let ret = if !constructor. is_wildcard ( ) {
2440
2417
debug ! ( "is_useful - expanding constructor: {:#?}" , constructor) ;
2441
2418
constructor
2442
2419
. split ( cx, pcx, matrix, Some ( hir_id) )
@@ -2458,8 +2435,11 @@ crate fn is_useful<'p, 'tcx>(
2458
2435
} else {
2459
2436
debug ! ( "is_useful - expanding wildcard" ) ;
2460
2437
2461
- let used_ctors: Vec < Constructor < ' _ > > =
2462
- matrix. heads ( ) . filter_map ( |p| pat_constructor ( cx. tcx , cx. param_env , p) ) . collect ( ) ;
2438
+ let used_ctors: Vec < Constructor < ' _ > > = matrix
2439
+ . heads ( )
2440
+ . map ( |p| pat_constructor ( cx. tcx , cx. param_env , p) )
2441
+ . filter ( |c| !c. is_wildcard ( ) )
2442
+ . collect ( ) ;
2463
2443
debug ! ( "is_useful_used_ctors = {:#?}" , used_ctors) ;
2464
2444
// `all_ctors` are all the constructors for the given type, which
2465
2445
// should all be represented (or caught with the wild pattern `_`).
@@ -2501,8 +2481,11 @@ crate fn is_useful<'p, 'tcx>(
2501
2481
. find ( |result| result. is_useful ( ) )
2502
2482
. unwrap_or ( NotUseful )
2503
2483
} else {
2504
- let matrix = matrix. specialize_wildcard ( ) ;
2505
- let v = v. to_tail ( ) ;
2484
+ let ctor_wild_subpatterns = Fields :: empty ( ) ;
2485
+ let matrix = matrix. specialize_constructor ( cx, & constructor, & ctor_wild_subpatterns) ;
2486
+ // Unwrap is ok: v can always be specialized with its own constructor.
2487
+ let v =
2488
+ v. specialize_constructor ( cx, & constructor, & ctor_wild_subpatterns, true ) . unwrap ( ) ;
2506
2489
let usefulness =
2507
2490
is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
2508
2491
@@ -2584,26 +2567,26 @@ fn pat_constructor<'tcx>(
2584
2567
tcx : TyCtxt < ' tcx > ,
2585
2568
param_env : ty:: ParamEnv < ' tcx > ,
2586
2569
pat : & Pat < ' tcx > ,
2587
- ) -> Option < Constructor < ' tcx > > {
2570
+ ) -> Constructor < ' tcx > {
2588
2571
// This MUST be kept in sync with `IntRange::from_pat`.
2589
2572
match * pat. kind {
2590
2573
PatKind :: AscribeUserType { .. } => bug ! ( ) , // Handled by `expand_pattern`
2591
- PatKind :: Binding { .. } | PatKind :: Wild => None ,
2592
- PatKind :: Leaf { .. } | PatKind :: Deref { .. } => Some ( Single ) ,
2574
+ PatKind :: Binding { .. } | PatKind :: Wild => Wildcard ,
2575
+ PatKind :: Leaf { .. } | PatKind :: Deref { .. } => Single ,
2593
2576
PatKind :: Variant { adt_def, variant_index, .. } => {
2594
- Some ( Variant ( adt_def. variants [ variant_index] . def_id ) )
2577
+ Variant ( adt_def. variants [ variant_index] . def_id )
2595
2578
}
2596
2579
PatKind :: Constant { value } => {
2597
2580
if let Some ( int_range) = IntRange :: from_const ( tcx, param_env, value, pat. span ) {
2598
- Some ( IntRange ( int_range) )
2581
+ IntRange ( int_range)
2599
2582
} else {
2600
2583
match value. ty . kind ( ) {
2601
- ty:: Float ( _) => Some ( FloatRange ( value, value, RangeEnd :: Included ) ) ,
2602
- ty:: Ref ( _, t, _) if t. is_str ( ) => Some ( Str ( value) ) ,
2584
+ ty:: Float ( _) => FloatRange ( value, value, RangeEnd :: Included ) ,
2585
+ ty:: Ref ( _, t, _) if t. is_str ( ) => Str ( value) ,
2603
2586
// All constants that can be structurally matched have already been expanded
2604
2587
// into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
2605
2588
// opaque.
2606
- _ => Some ( Opaque ) ,
2589
+ _ => Opaque ,
2607
2590
}
2608
2591
}
2609
2592
}
@@ -2617,9 +2600,9 @@ fn pat_constructor<'tcx>(
2617
2600
& end,
2618
2601
pat. span ,
2619
2602
) {
2620
- Some ( IntRange ( int_range) )
2603
+ IntRange ( int_range)
2621
2604
} else {
2622
- Some ( FloatRange ( lo, hi, end) )
2605
+ FloatRange ( lo, hi, end)
2623
2606
}
2624
2607
}
2625
2608
PatKind :: Array { ref prefix, ref slice, ref suffix }
@@ -2633,7 +2616,7 @@ fn pat_constructor<'tcx>(
2633
2616
let suffix = suffix. len ( ) as u64 ;
2634
2617
let kind =
2635
2618
if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
2636
- Some ( Slice ( Slice { array_len, kind } ) )
2619
+ Slice ( Slice { array_len, kind } )
2637
2620
}
2638
2621
PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
2639
2622
}
0 commit comments