@@ -407,20 +407,51 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
407407 }
408408
409409 /// 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`.
410422 fn specialize_constructor (
411423 & self ,
412424 cx : & MatchCheckCtxt < ' p , ' tcx > ,
413- constructor : & Constructor < ' tcx > ,
425+ ctor : & Constructor < ' tcx > ,
414426 ctor_wild_subpatterns : & Fields < ' p , ' tcx > ,
415427 is_my_head_ctor : bool ,
416428 ) -> 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({:#?}, {:#?}, {:#?}) = {:#?}" ,
419447 self . head( ) ,
420- constructor ,
448+ ctor ,
421449 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()`.
424455 Some ( new_fields. push_on_patstack ( & self . 0 [ 1 ..] ) )
425456 }
426457}
@@ -971,7 +1002,7 @@ impl Slice {
9711002/// the constructor. See also `Fields`.
9721003///
9731004/// `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
9751006/// constructor. `Constructor::apply` reconstructs the pattern from a pair of `Constructor` and
9761007/// `Fields`.
9771008#[ derive( Clone , Debug , PartialEq ) ]
@@ -1195,7 +1226,7 @@ impl<'tcx> Constructor<'tcx> {
11951226 /// Apply a constructor to a list of patterns, yielding a new pattern. `pats`
11961227 /// must have as many elements as this constructor's arity.
11971228 ///
1198- /// This is roughly the inverse of `specialize_one_pattern `.
1229+ /// This is roughly the inverse of `specialize_constructor `.
11991230 ///
12001231 /// Examples:
12011232 /// `self`: `Constructor::Single`
@@ -2607,46 +2638,3 @@ fn pat_constructor<'tcx>(
26072638 PatKind :: Or { .. } => bug ! ( "Or-pattern should have been expanded earlier on." ) ,
26082639 }
26092640}
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