Skip to content

Commit 6ad9f44

Browse files
committed
Clarify specialization into two steps
First is checking for constructor overlap, second is extracting the resulting fields.
1 parent 7c4f94b commit 6ad9f44

File tree

1 file changed

+48
-56
lines changed
  • compiler/rustc_mir_build/src/thir/pattern

1 file changed

+48
-56
lines changed

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

Lines changed: 48 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -2527,9 +2527,9 @@ fn pat_constructor<'tcx>(
25272527
fn specialize_one_pattern<'p, 'tcx>(
25282528
cx: &MatchCheckCtxt<'p, 'tcx>,
25292529
pat: &'p Pat<'tcx>,
2530-
constructor: &Constructor<'tcx>,
2530+
ctor: &Constructor<'tcx>,
25312531
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
2532-
is_its_own_ctor: bool, // Whether `constructor` is known to be derived from `pat`
2532+
is_its_own_ctor: bool, // Whether `ctor` is known to be derived from `pat`
25332533
) -> Option<Fields<'p, 'tcx>> {
25342534
if pat.is_wildcard() {
25352535
return Some(ctor_wild_subpatterns.clone());
@@ -2539,57 +2539,34 @@ fn specialize_one_pattern<'p, 'tcx>(
25392539
// `unwrap` is safe because `pat` is not a wildcard.
25402540
let pat_ctor = pat_constructor(cx.tcx, cx.param_env, pat).unwrap();
25412541

2542-
let result = match (constructor, &pat_ctor, pat.kind.as_ref()) {
2543-
(Single, Single, PatKind::Leaf { subpatterns }) => {
2544-
Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
2545-
}
2546-
(Single, Single, PatKind::Deref { subpattern }) => {
2547-
Some(Fields::from_single_pattern(subpattern))
2548-
}
2549-
(Variant(_), Variant(_), _) if constructor != &pat_ctor => None,
2550-
(Variant(_), Variant(_), PatKind::Variant { subpatterns, .. }) => {
2551-
Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
2552-
}
2542+
let ctor_covered_by_pat = match (ctor, &pat_ctor) {
2543+
(Single, Single) => true,
2544+
(Variant(ctor_id), Variant(pat_id)) => ctor_id == pat_id,
25532545

2554-
(IntRange(ctor_range), IntRange(pat_range), _) => {
2555-
ctor_range.intersection(cx.tcx, &pat_range)?;
2556-
// Constructor splitting should ensure that all intersections we encounter
2557-
// are actually inclusions.
2558-
assert!(ctor_range.is_subrange(&pat_range));
2559-
Some(Fields::empty())
2546+
(IntRange(ctor_range), IntRange(pat_range)) => {
2547+
if ctor_range.intersection(cx.tcx, pat_range).is_some() {
2548+
// Constructor splitting should ensure that all intersections we encounter
2549+
// are actually inclusions.
2550+
assert!(ctor_range.is_subrange(pat_range));
2551+
true
2552+
} else {
2553+
false
2554+
}
25602555
}
2561-
(FloatRange(ctor_from, ctor_to, ctor_end), FloatRange(pat_from, pat_to, pat_end), _) => {
2556+
(FloatRange(ctor_from, ctor_to, ctor_end), FloatRange(pat_from, pat_to, pat_end)) => {
25622557
let to = compare_const_vals(cx.tcx, ctor_to, pat_to, cx.param_env, ty)?;
25632558
let from = compare_const_vals(cx.tcx, ctor_from, pat_from, cx.param_env, ty)?;
2564-
let intersects = (from == Ordering::Greater || from == Ordering::Equal)
2565-
&& (to == Ordering::Less || (pat_end == ctor_end && to == Ordering::Equal));
2566-
if intersects { Some(Fields::empty()) } else { None }
2559+
(from == Ordering::Greater || from == Ordering::Equal)
2560+
&& (to == Ordering::Less || (pat_end == ctor_end && to == Ordering::Equal))
25672561
}
2568-
(Str(ctor_val), Str(pat_val), _) => {
2562+
(Str(ctor_val), Str(pat_val)) => {
25692563
// FIXME: there's probably a more direct way of comparing for equality
25702564
let comparison = compare_const_vals(cx.tcx, ctor_val, pat_val, cx.param_env, ty)?;
2571-
if comparison == Ordering::Equal { Some(Fields::empty()) } else { None }
2572-
}
2573-
2574-
(Slice(ctor_slice), Slice(pat_slice), _)
2575-
if !pat_slice.pattern_kind().covers_length(ctor_slice.arity()) =>
2576-
{
2577-
None
2565+
comparison == Ordering::Equal
25782566
}
2579-
(
2580-
Slice(ctor_slice),
2581-
Slice(_),
2582-
PatKind::Array { prefix, suffix, .. } | PatKind::Slice { prefix, suffix, .. },
2583-
) => {
2584-
// Number of subpatterns for the constructor
2585-
let ctor_arity = ctor_slice.arity();
25862567

2587-
// Replace the prefix and the suffix with the given patterns, leaving wildcards in
2588-
// the middle if there was a subslice pattern `..`.
2589-
let prefix = prefix.iter().enumerate();
2590-
let suffix =
2591-
suffix.iter().enumerate().map(|(i, p)| (ctor_arity as usize - suffix.len() + i, p));
2592-
Some(ctor_wild_subpatterns.replace_fields_indexed(prefix.chain(suffix)))
2568+
(Slice(ctor_slice), Slice(pat_slice)) => {
2569+
pat_slice.pattern_kind().covers_length(ctor_slice.arity())
25932570
}
25942571

25952572
// Only a wildcard pattern can match an opaque constant, unless we're specializing the
@@ -2611,23 +2588,38 @@ fn specialize_one_pattern<'p, 'tcx>(
26112588
// (FOO, false) => {}
26122589
// }
26132590
// ```
2614-
(Opaque, Opaque, _) if is_its_own_ctor => Some(Fields::empty()),
2591+
(Opaque, Opaque) if is_its_own_ctor => true,
26152592
// We are trying to inspect an opaque constant. Thus we skip the row.
2616-
(Opaque, _, _) | (_, Opaque, _) => None,
2593+
(Opaque, _) | (_, Opaque) => false,
26172594
// Only a wildcard pattern can match the special extra constructor.
2618-
(NonExhaustive, _, _) => None,
2595+
(NonExhaustive, _) => false,
26192596

2620-
_ => bug!("trying to specialize pattern {:?} with constructor {:?}", pat, constructor),
2597+
_ => bug!("trying to specialize pattern {:?} with constructor {:?}", pat, ctor),
26212598
};
26222599

2623-
debug!(
2624-
"specialize({:#?}, {:#?}, {:#?}) = {:#?}",
2625-
pat, constructor, ctor_wild_subpatterns, result
2626-
);
2627-
2628-
if let Some(fields) = &result {
2629-
debug_assert_eq!(fields.len(), ctor_wild_subpatterns.len());
2600+
if !ctor_covered_by_pat {
2601+
return None;
26302602
}
26312603

2632-
result
2604+
let fields = match pat.kind.as_ref() {
2605+
PatKind::Deref { subpattern } => Fields::from_single_pattern(subpattern),
2606+
PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
2607+
ctor_wild_subpatterns.replace_with_fieldpats(subpatterns)
2608+
}
2609+
PatKind::Array { prefix, suffix, .. } | PatKind::Slice { prefix, suffix, .. } => {
2610+
// Number of subpatterns for the constructor
2611+
let ctor_arity = ctor_wild_subpatterns.len();
2612+
2613+
// Replace the prefix and the suffix with the given patterns, leaving wildcards in
2614+
// the middle if there was a subslice pattern `..`.
2615+
let prefix = prefix.iter().enumerate();
2616+
let suffix = suffix.iter().enumerate().map(|(i, p)| (ctor_arity - suffix.len() + i, p));
2617+
ctor_wild_subpatterns.replace_fields_indexed(prefix.chain(suffix))
2618+
}
2619+
_ => ctor_wild_subpatterns.clone(),
2620+
};
2621+
2622+
debug!("specialize({:#?}, {:#?}, {:#?}) = {:#?}", pat, ctor, ctor_wild_subpatterns, fields);
2623+
2624+
Some(fields)
26332625
}

0 commit comments

Comments
 (0)