@@ -407,20 +407,51 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
407
407
}
408
408
409
409
/// This computes `S(constructor, self)`. See top of the file for explanations.
410
+ ///
411
+ /// This is the main specialization step. It expands the pattern
412
+ /// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
413
+ /// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
414
+ /// Returns `None` if the pattern does not have the given constructor.
415
+ ///
416
+ /// OTOH, slice patterns with a subslice pattern (tail @ ..) can be expanded into multiple
417
+ /// different patterns.
418
+ /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
419
+ /// fields filled with wild patterns.
420
+ ///
421
+ /// This is roughly the inverse of `Constructor::apply`.
410
422
fn specialize_constructor (
411
423
& self ,
412
424
cx : & MatchCheckCtxt < ' p , ' tcx > ,
413
- constructor : & Constructor < ' tcx > ,
425
+ ctor : & Constructor < ' tcx > ,
414
426
ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
415
427
is_my_head_ctor : bool ,
416
428
) -> Option < PatStack < ' p , ' tcx > > {
417
- let new_fields = specialize_one_pattern (
418
- cx,
429
+ // 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.
433
+ // Note that this shortcut is also necessary for correctness: a pattern should always be
434
+ // specializable with its own constructor, even in cases where we refuse to inspect values like
435
+ // 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 ( ) ;
439
+ if !ctor. is_covered_by ( cx, & head_ctor, self . head ( ) . ty ) {
440
+ return None ;
441
+ }
442
+ }
443
+ let new_fields = ctor_wild_subpatterns. replace_with_pattern_arguments ( self . head ( ) ) ;
444
+
445
+ debug ! (
446
+ "specialize_constructor({:#?}, {:#?}, {:#?}) = {:#?}" ,
419
447
self . head( ) ,
420
- constructor ,
448
+ ctor ,
421
449
ctor_wild_subpatterns,
422
- is_my_head_ctor,
423
- ) ?;
450
+ new_fields
451
+ ) ;
452
+
453
+ // We pop the head pattern and push the new fields extracted from the arguments of
454
+ // `self.head()`.
424
455
Some ( new_fields. push_on_patstack ( & self . 0 [ 1 ..] ) )
425
456
}
426
457
}
@@ -971,7 +1002,7 @@ impl Slice {
971
1002
/// the constructor. See also `Fields`.
972
1003
///
973
1004
/// `pat_constructor` retrieves the constructor corresponding to a pattern.
974
- /// `specialize_one_pattern ` returns the list of fields corresponding to a pattern, given a
1005
+ /// `specialize_constructor ` returns the list of fields corresponding to a pattern, given a
975
1006
/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
976
1007
/// `Fields`.
977
1008
#[ derive( Clone , Debug , PartialEq ) ]
@@ -1195,7 +1226,7 @@ impl<'tcx> Constructor<'tcx> {
1195
1226
/// Apply a constructor to a list of patterns, yielding a new pattern. `pats`
1196
1227
/// must have as many elements as this constructor's arity.
1197
1228
///
1198
- /// This is roughly the inverse of `specialize_one_pattern `.
1229
+ /// This is roughly the inverse of `specialize_constructor `.
1199
1230
///
1200
1231
/// Examples:
1201
1232
/// `self`: `Constructor::Single`
@@ -2607,46 +2638,3 @@ fn pat_constructor<'tcx>(
2607
2638
PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
2608
2639
}
2609
2640
}
2610
-
2611
- /// This is the main specialization step. It expands the pattern
2612
- /// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
2613
- /// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
2614
- /// Returns `None` if the pattern does not have the given constructor.
2615
- ///
2616
- /// OTOH, slice patterns with a subslice pattern (tail @ ..) can be expanded into multiple
2617
- /// different patterns.
2618
- /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
2619
- /// fields filled with wild patterns.
2620
- ///
2621
- /// This is roughly the inverse of `Constructor::apply`.
2622
- fn specialize_one_pattern < ' p , ' tcx > (
2623
- cx : & MatchCheckCtxt < ' p , ' tcx > ,
2624
- pat : & ' p Pat < ' tcx > ,
2625
- ctor : & Constructor < ' tcx > ,
2626
- ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
2627
- is_its_own_ctor : bool , // Whether `ctor` is known to be derived from `pat`
2628
- ) -> Option < Fields < ' p , ' tcx > > {
2629
- if pat. is_wildcard ( ) {
2630
- return Some ( ctor_wild_subpatterns. clone ( ) ) ;
2631
- }
2632
-
2633
- // We return `None` if `ctor` is not covered by `pat`. If `ctor` is known to be derived from
2634
- // `pat` then we don't need to check; otherwise, we compute the constructor of `pat` and check
2635
- // for constructor inclusion.
2636
- // Note that this shortcut is also necessary for correctness: a pattern should always be
2637
- // specializable with its own constructor, even in cases where we refuse to inspect values like
2638
- // opaque constants.
2639
- if !is_its_own_ctor {
2640
- // `unwrap` is safe because `pat` is not a wildcard.
2641
- let pat_ctor = pat_constructor ( cx. tcx , cx. param_env , pat) . unwrap ( ) ;
2642
- if !ctor. is_covered_by ( cx, & pat_ctor, pat. ty ) {
2643
- return None ;
2644
- }
2645
- }
2646
-
2647
- let fields = ctor_wild_subpatterns. replace_with_pattern_arguments ( pat) ;
2648
-
2649
- debug ! ( "specialize({:#?}, {:#?}, {:#?}) = {:#?}" , pat, ctor, ctor_wild_subpatterns, fields) ;
2650
-
2651
- Some ( fields)
2652
- }
0 commit comments