Skip to content

Commit 41e7ca4

Browse files
committed
Inline specialize_one_pattern
1 parent c511955 commit 41e7ca4

File tree

1 file changed

+39
-51
lines changed
  • compiler/rustc_mir_build/src/thir/pattern

1 file changed

+39
-51
lines changed

compiler/rustc_mir_build/src/thir/pattern/_match.rs

Lines changed: 39 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)