only check for mixed deref/normal constructors when needed

This commit is contained in:
dianne
2025-07-04 21:53:03 -07:00
parent 50061f3b11
commit bb64315978
5 changed files with 26 additions and 1 deletions

View File

@@ -109,6 +109,11 @@ pub trait PatCx: Sized + fmt::Debug {
) {
}
/// Check if we may need to perform additional deref-pattern-specific validation.
fn match_may_contain_deref_pats(&self) -> bool {
true
}
/// The current implementation of deref patterns requires that they can't match on the same
/// place as a normal constructor. Since this isn't caught by type-checking, we check it in the
/// `PatCx` before running the analysis. This reports an error if the check fails.

View File

@@ -1,3 +1,4 @@
use std::cell::Cell;
use std::fmt;
use std::iter::once;
@@ -99,6 +100,16 @@ pub struct RustcPatCtxt<'p, 'tcx: 'p> {
/// Whether the data at the scrutinee is known to be valid. This is false if the scrutinee comes
/// from a union field, a pointer deref, or a reference deref (pending opsem decisions).
pub known_valid_scrutinee: bool,
pub internal_state: RustcPatCtxtState,
}
/// Private fields of [`RustcPatCtxt`], separated out to permit record initialization syntax.
#[derive(Clone, Default)]
pub struct RustcPatCtxtState {
/// Has a deref pattern been lowered? This is initialized to `false` and is updated by
/// [`RustcPatCtxt::lower_pat`] in order to avoid performing deref-pattern-specific validation
/// for everything containing patterns.
has_lowered_deref_pat: Cell<bool>,
}
impl<'p, 'tcx: 'p> fmt::Debug for RustcPatCtxt<'p, 'tcx> {
@@ -474,6 +485,7 @@ impl<'p, 'tcx: 'p> RustcPatCtxt<'p, 'tcx> {
fields = vec![self.lower_pat(subpattern).at_index(0)];
arity = 1;
ctor = DerefPattern(cx.reveal_opaque_ty(subpattern.ty));
self.internal_state.has_lowered_deref_pat.set(true);
}
PatKind::Leaf { subpatterns } | PatKind::Variant { subpatterns, .. } => {
match ty.kind() {
@@ -1028,6 +1040,10 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
}
}
fn match_may_contain_deref_pats(&self) -> bool {
self.internal_state.has_lowered_deref_pat.get()
}
fn report_mixed_deref_pat_ctors(
&self,
deref_pat: &crate::pat::DeconstructedPat<Self>,

View File

@@ -1837,7 +1837,9 @@ pub fn compute_match_usefulness<'p, Cx: PatCx>(
complexity_limit: usize,
) -> Result<UsefulnessReport<'p, Cx>, Cx::Error> {
// The analysis doesn't support deref patterns mixed with normal constructors; error if present.
checks::detect_mixed_deref_pat_ctors(tycx, arms)?;
if tycx.match_may_contain_deref_pats() {
checks::detect_mixed_deref_pat_ctors(tycx, arms)?;
}
let mut cx = UsefulnessCtxt {
tycx,