Skip to content

Commit 7c4f94b

Browse files
committed
Use pat_constructor to simplify specialize_one_pattern
1 parent feb1e13 commit 7c4f94b

File tree

1 file changed

+71
-105
lines changed
  • compiler/rustc_mir_build/src/thir/pattern

1 file changed

+71
-105
lines changed

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

Lines changed: 71 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -2529,17 +2529,69 @@ fn specialize_one_pattern<'p, 'tcx>(
25292529
pat: &'p Pat<'tcx>,
25302530
constructor: &Constructor<'tcx>,
25312531
ctor_wild_subpatterns: &Fields<'p, 'tcx>,
2532-
is_its_own_ctor: bool, // Whether `ctor` is known to be derived from `pat`
2532+
is_its_own_ctor: bool, // Whether `constructor` is known to be derived from `pat`
25332533
) -> Option<Fields<'p, 'tcx>> {
2534-
if let NonExhaustive = constructor {
2535-
// Only a wildcard pattern can match the special extra constructor.
2536-
if !pat.is_wildcard() {
2537-
return None;
2538-
}
2539-
return Some(Fields::empty());
2534+
if pat.is_wildcard() {
2535+
return Some(ctor_wild_subpatterns.clone());
25402536
}
25412537

2542-
if let Opaque = constructor {
2538+
let ty = pat.ty;
2539+
// `unwrap` is safe because `pat` is not a wildcard.
2540+
let pat_ctor = pat_constructor(cx.tcx, cx.param_env, pat).unwrap();
2541+
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+
}
2553+
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())
2560+
}
2561+
(FloatRange(ctor_from, ctor_to, ctor_end), FloatRange(pat_from, pat_to, pat_end), _) => {
2562+
let to = compare_const_vals(cx.tcx, ctor_to, pat_to, cx.param_env, ty)?;
2563+
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 }
2567+
}
2568+
(Str(ctor_val), Str(pat_val), _) => {
2569+
// FIXME: there's probably a more direct way of comparing for equality
2570+
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
2578+
}
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();
2586+
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)))
2593+
}
2594+
25432595
// Only a wildcard pattern can match an opaque constant, unless we're specializing the
25442596
// value against its own constructor. That happens when we call
25452597
// `v.specialize_constructor(ctor)` with `ctor` obtained from `pat_constructor(v.head())`.
@@ -2559,109 +2611,23 @@ fn specialize_one_pattern<'p, 'tcx>(
25592611
// (FOO, false) => {}
25602612
// }
25612613
// ```
2562-
if is_its_own_ctor || pat.is_wildcard() {
2563-
return Some(Fields::empty());
2564-
} else {
2565-
return None;
2566-
}
2567-
}
2568-
2569-
let result = match *pat.kind {
2570-
PatKind::AscribeUserType { .. } => bug!(), // Handled by `expand_pattern`
2571-
2572-
PatKind::Binding { .. } | PatKind::Wild => Some(ctor_wild_subpatterns.clone()),
2573-
2574-
PatKind::Variant { adt_def, variant_index, ref subpatterns, .. } => {
2575-
let variant = &adt_def.variants[variant_index];
2576-
if constructor != &Variant(variant.def_id) {
2577-
return None;
2578-
}
2579-
Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
2580-
}
2581-
2582-
PatKind::Leaf { ref subpatterns } => {
2583-
Some(ctor_wild_subpatterns.replace_with_fieldpats(subpatterns))
2584-
}
2585-
2586-
PatKind::Deref { ref subpattern } => Some(Fields::from_single_pattern(subpattern)),
2587-
2588-
PatKind::Constant { .. } | PatKind::Range { .. } => {
2589-
match constructor {
2590-
IntRange(ctor) => {
2591-
let pat = IntRange::from_pat(cx.tcx, cx.param_env, pat)?;
2592-
ctor.intersection(cx.tcx, &pat)?;
2593-
// Constructor splitting should ensure that all intersections we encounter
2594-
// are actually inclusions.
2595-
assert!(ctor.is_subrange(&pat));
2596-
}
2597-
FloatRange(ctor_from, ctor_to, ctor_end) => {
2598-
let (pat_from, pat_to, pat_end, ty) = match *pat.kind {
2599-
PatKind::Constant { value } => (value, value, RangeEnd::Included, value.ty),
2600-
PatKind::Range(PatRange { lo, hi, end }) => (lo, hi, end, lo.ty),
2601-
_ => unreachable!(), // This is ensured by the branch we're in
2602-
};
2603-
let to = compare_const_vals(cx.tcx, ctor_to, pat_to, cx.param_env, ty)?;
2604-
let from = compare_const_vals(cx.tcx, ctor_from, pat_from, cx.param_env, ty)?;
2605-
let intersects = (from == Ordering::Greater || from == Ordering::Equal)
2606-
&& (to == Ordering::Less
2607-
|| (pat_end == *ctor_end && to == Ordering::Equal));
2608-
if !intersects {
2609-
return None;
2610-
}
2611-
}
2612-
Str(ctor_value) => {
2613-
let pat_value = match *pat.kind {
2614-
PatKind::Constant { value } => value,
2615-
_ => span_bug!(
2616-
pat.span,
2617-
"unexpected range pattern {:?} for constant value ctor",
2618-
pat
2619-
),
2620-
};
2621-
2622-
// FIXME: there's probably a more direct way of comparing for equality
2623-
if compare_const_vals(cx.tcx, ctor_value, pat_value, cx.param_env, pat.ty)?
2624-
!= Ordering::Equal
2625-
{
2626-
return None;
2627-
}
2628-
}
2629-
_ => {
2630-
// If we reach here, we must be trying to inspect an opaque constant. Thus we skip
2631-
// the row.
2632-
return None;
2633-
}
2634-
}
2635-
Some(Fields::empty())
2636-
}
2637-
2638-
PatKind::Array { ref prefix, ref slice, ref suffix }
2639-
| PatKind::Slice { ref prefix, ref slice, ref suffix } => match *constructor {
2640-
Slice(_) => {
2641-
// Number of subpatterns for this pattern
2642-
let pat_len = prefix.len() + suffix.len();
2643-
// Number of subpatterns for this constructor
2644-
let arity = ctor_wild_subpatterns.len();
2645-
2646-
if (slice.is_none() && arity != pat_len) || pat_len > arity {
2647-
return None;
2648-
}
2649-
2650-
// Replace the prefix and the suffix with the given patterns, leaving wildcards in
2651-
// the middle if there was a subslice pattern `..`.
2652-
let prefix = prefix.iter().enumerate();
2653-
let suffix = suffix.iter().enumerate().map(|(i, p)| (arity - suffix.len() + i, p));
2654-
Some(ctor_wild_subpatterns.replace_fields_indexed(prefix.chain(suffix)))
2655-
}
2656-
_ => span_bug!(pat.span, "unexpected ctor {:?} for slice pat", constructor),
2657-
},
2614+
(Opaque, Opaque, _) if is_its_own_ctor => Some(Fields::empty()),
2615+
// We are trying to inspect an opaque constant. Thus we skip the row.
2616+
(Opaque, _, _) | (_, Opaque, _) => None,
2617+
// Only a wildcard pattern can match the special extra constructor.
2618+
(NonExhaustive, _, _) => None,
26582619

2659-
PatKind::Or { .. } => bug!("Or-pattern should have been expanded earlier on."),
2620+
_ => bug!("trying to specialize pattern {:?} with constructor {:?}", pat, constructor),
26602621
};
2622+
26612623
debug!(
26622624
"specialize({:#?}, {:#?}, {:#?}) = {:#?}",
26632625
pat, constructor, ctor_wild_subpatterns, result
26642626
);
26652627

2628+
if let Some(fields) = &result {
2629+
debug_assert_eq!(fields.len(), ctor_wild_subpatterns.len());
2630+
}
2631+
26662632
result
26672633
}

0 commit comments

Comments
 (0)