137137//! S(c, (r_1, p_2, .., p_n))
138138//! S(c, (r_2, p_2, .., p_n))
139139//!
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)`.
142142//! This is used when we know there are missing constructor cases, but there might be
143143//! existing wildcard patterns, so to check the usefulness of the matrix, we have to check
144144//! all its *other* components.
150150//! p_2, .., p_n
151151//! 2.3. `p_1 = r_1 | r_2`. We expand the OR-pattern and then recurse on each resulting
152152//! 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))
155155//!
156156//! Note that the OR-patterns are not always used directly in Rust, but are used to derive the
157157//! exhaustive integer matching rules, so they're written here for posterity.
205205//! That's almost correct, but only works if there were no wildcards in those first
206206//! components. So we need to check that `p` is useful with respect to the rows that
207207//! 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))`
209209//!
210210//! For example, if `P` is:
211211//!
@@ -358,10 +358,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
358358 PatStack ( vec)
359359 }
360360
361- fn from_slice ( s : & [ & ' p Pat < ' tcx > ] ) -> Self {
362- PatStack ( SmallVec :: from_slice ( s) )
363- }
364-
365361 fn is_empty ( & self ) -> bool {
366362 self . 0 . is_empty ( )
367363 }
@@ -374,10 +370,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
374370 self . 0 [ 0 ]
375371 }
376372
377- fn to_tail ( & self ) -> Self {
378- PatStack :: from_slice ( & self . 0 [ 1 ..] )
379- }
380-
381373 fn iter ( & self ) -> impl Iterator < Item = & Pat < ' tcx > > {
382374 self . 0 . iter ( ) . copied ( )
383375 }
@@ -401,11 +393,6 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
401393 }
402394 }
403395
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-
409396 /// This computes `S(constructor, self)`. See top of the file for explanations.
410397 ///
411398 /// This is the main specialization step. It expands the pattern
@@ -427,15 +414,13 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
427414 is_my_head_ctor : bool ,
428415 ) -> Option < PatStack < ' p , ' tcx > > {
429416 // 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.
433419 // Note that this shortcut is also necessary for correctness: a pattern should always be
434420 // specializable with its own constructor, even in cases where we refuse to inspect values like
435421 // 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 ( ) ) ;
439424 if !ctor. is_covered_by ( cx, & head_ctor, self . head ( ) . ty ) {
440425 return None ;
441426 }
@@ -480,8 +465,8 @@ enum SpecializationCache {
480465 /// so it is possible to precompute the result of `Matrix::specialize_constructor` at a
481466 /// lower computational complexity.
482467 /// `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
485470 /// fallback for `Matrix::specialize_constructor` when it tries to apply a constructor that
486471 /// has not been seen in the `Matrix`. See `update_cache` for further explanations.
487472 Variants { lookup : FxHashMap < DefId , SmallVec < [ usize ; 1 ] > > , wilds : SmallVec < [ usize ; 1 ] > } ,
@@ -553,9 +538,9 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
553538 v. push ( idx) ;
554539 }
555540 // 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 .
557542 // 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
559544 // serves as the default value of `specialize_constructor` for constructors
560545 // that are not in `lookup`.
561546 wilds. push ( idx) ;
@@ -585,30 +570,6 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
585570 self . patterns . iter ( ) . map ( |r| r. head ( ) )
586571 }
587572
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-
612573 /// This computes `S(constructor, self)`. See top of the file for explanations.
613574 fn specialize_constructor (
614575 & self ,
@@ -618,24 +579,30 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
618579 ) -> Matrix < ' p , ' tcx > {
619580 match & self . cache {
620581 SpecializationCache :: Variants { lookup, wilds } => {
621- let result : Self = if let Constructor :: Variant ( id) = constructor {
582+ let cached = if let Constructor :: Variant ( id) = constructor {
622583 lookup
623584 . get ( id)
624585 // Default to `wilds` for absent keys. See `update_cache` for an explanation.
625586 . 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
636589 } else {
637- unreachable ! ( )
590+ bug ! (
591+ "unexpected constructor encountered while dealing with matrix cache: {:?}" ,
592+ constructor
593+ ) ;
638594 } ;
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 ( ) ;
639606 // When debug assertions are enabled, check the results against the "slow path"
640607 // result.
641608 debug_assert_eq ! (
@@ -939,8 +906,10 @@ impl Slice {
939906 _ => return smallvec ! [ Slice ( self ) ] ,
940907 } ;
941908
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 ( ) ) ;
944913
945914 let mut max_prefix_len = self_prefix;
946915 let mut max_suffix_len = self_suffix;
@@ -1026,9 +995,18 @@ enum Constructor<'tcx> {
1026995 Opaque ,
1027996 /// Fake extra constructor for enums that aren't allowed to be matched exhaustively.
1028997 NonExhaustive ,
998+ /// Wildcard pattern.
999+ Wildcard ,
10291000}
10301001
10311002impl < ' tcx > Constructor < ' tcx > {
1003+ fn is_wildcard ( & self ) -> bool {
1004+ match self {
1005+ Wildcard => true ,
1006+ _ => false ,
1007+ }
1008+ }
1009+
10321010 fn variant_index_for_adt ( & self , adt : & ' tcx ty:: AdtDef ) -> VariantIdx {
10331011 match * self {
10341012 Variant ( id) => adt. variant_index_with_id ( id) ,
@@ -1120,7 +1098,8 @@ impl<'tcx> Constructor<'tcx> {
11201098 }
11211099 // This constructor is never covered by anything else
11221100 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" ) ,
11241103 }
11251104 }
11261105
@@ -1173,6 +1152,11 @@ impl<'tcx> Constructor<'tcx> {
11731152 ty : Ty < ' tcx > ,
11741153 ) -> bool {
11751154 match ( self , other) {
1155+ // Wildcards cover anything
1156+ ( _, Wildcard ) => true ,
1157+ // Wildcards are only covered by wildcards
1158+ ( Wildcard , _) => false ,
1159+
11761160 ( Single , Single ) => true ,
11771161 ( Variant ( self_id) , Variant ( other_id) ) => self_id == other_id,
11781162
@@ -1302,7 +1286,8 @@ impl<'tcx> Constructor<'tcx> {
13021286 & FloatRange ( lo, hi, end) => PatKind :: Range ( PatRange { lo, hi, end } ) ,
13031287 IntRange ( range) => return range. to_pat ( cx. tcx ) ,
13041288 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" ) ,
13061291 } ;
13071292
13081293 Pat { ty, span : DUMMY_SP , kind : Box :: new ( pat) }
@@ -1454,7 +1439,9 @@ impl<'p, 'tcx> Fields<'p, 'tcx> {
14541439 }
14551440 _ => bug ! ( "bad slice pattern {:?} {:?}" , constructor, ty) ,
14561441 } ,
1457- Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque => Fields :: empty ( ) ,
1442+ Str ( ..) | FloatRange ( ..) | IntRange ( ..) | NonExhaustive | Opaque | Wildcard => {
1443+ Fields :: empty ( )
1444+ }
14581445 } ;
14591446 debug ! ( "Fields::wildcards({:?}, {:?}) = {:#?}" , constructor, ty, ret) ;
14601447 ret
@@ -2011,19 +1998,7 @@ impl<'tcx> IntRange<'tcx> {
20111998 ) -> Option < IntRange < ' tcx > > {
20121999 // This MUST be kept in sync with `pat_constructor`.
20132000 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-
20252001 PatKind :: Constant { value } => Self :: from_const ( tcx, param_env, value, pat. span ) ,
2026-
20272002 PatKind :: Range ( PatRange { lo, hi, end } ) => {
20282003 let ty = lo. ty ;
20292004 Self :: from_range (
@@ -2035,6 +2010,7 @@ impl<'tcx> IntRange<'tcx> {
20352010 pat. span ,
20362011 )
20372012 }
2013+ _ => None ,
20382014 }
20392015 }
20402016
@@ -2436,7 +2412,8 @@ crate fn is_useful<'p, 'tcx>(
24362412
24372413 debug ! ( "is_useful_expand_first_col: pcx={:#?}, expanding {:#?}" , pcx, v. head( ) ) ;
24382414
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 ( ) {
24402417 debug ! ( "is_useful - expanding constructor: {:#?}" , constructor) ;
24412418 constructor
24422419 . split ( cx, pcx, matrix, Some ( hir_id) )
@@ -2458,8 +2435,11 @@ crate fn is_useful<'p, 'tcx>(
24582435 } else {
24592436 debug ! ( "is_useful - expanding wildcard" ) ;
24602437
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 ( ) ;
24632443 debug ! ( "is_useful_used_ctors = {:#?}" , used_ctors) ;
24642444 // `all_ctors` are all the constructors for the given type, which
24652445 // should all be represented (or caught with the wild pattern `_`).
@@ -2501,8 +2481,11 @@ crate fn is_useful<'p, 'tcx>(
25012481 . find ( |result| result. is_useful ( ) )
25022482 . unwrap_or ( NotUseful )
25032483 } 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 ( ) ;
25062489 let usefulness =
25072490 is_useful ( cx, & matrix, & v, witness_preference, hir_id, is_under_guard, false ) ;
25082491
@@ -2584,26 +2567,26 @@ fn pat_constructor<'tcx>(
25842567 tcx : TyCtxt < ' tcx > ,
25852568 param_env : ty:: ParamEnv < ' tcx > ,
25862569 pat : & Pat < ' tcx > ,
2587- ) -> Option < Constructor < ' tcx > > {
2570+ ) -> Constructor < ' tcx > {
25882571 // This MUST be kept in sync with `IntRange::from_pat`.
25892572 match * pat. kind {
25902573 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 ,
25932576 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 )
25952578 }
25962579 PatKind :: Constant { value } => {
25972580 if let Some ( int_range) = IntRange :: from_const ( tcx, param_env, value, pat. span ) {
2598- Some ( IntRange ( int_range) )
2581+ IntRange ( int_range)
25992582 } else {
26002583 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) ,
26032586 // All constants that can be structurally matched have already been expanded
26042587 // into the corresponding `Pat`s by `const_to_pat`. Constants that remain are
26052588 // opaque.
2606- _ => Some ( Opaque ) ,
2589+ _ => Opaque ,
26072590 }
26082591 }
26092592 }
@@ -2617,9 +2600,9 @@ fn pat_constructor<'tcx>(
26172600 & end,
26182601 pat. span ,
26192602 ) {
2620- Some ( IntRange ( int_range) )
2603+ IntRange ( int_range)
26212604 } else {
2622- Some ( FloatRange ( lo, hi, end) )
2605+ FloatRange ( lo, hi, end)
26232606 }
26242607 }
26252608 PatKind :: Array { ref prefix, ref slice, ref suffix }
@@ -2633,7 +2616,7 @@ fn pat_constructor<'tcx>(
26332616 let suffix = suffix. len ( ) as u64 ;
26342617 let kind =
26352618 if slice. is_some ( ) { VarLen ( prefix, suffix) } else { FixedLen ( prefix + suffix) } ;
2636- Some ( Slice ( Slice { array_len, kind } ) )
2619+ Slice ( Slice { array_len, kind } )
26372620 }
26382621 PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
26392622 }
0 commit comments