diff options
Diffstat (limited to 'compiler/rustc_pattern_analysis')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/lib.rs | 5 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/rustc.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 4 |
3 files changed, 24 insertions, 1 deletions
diff --git a/compiler/rustc_pattern_analysis/src/lib.rs b/compiler/rustc_pattern_analysis/src/lib.rs index 129fd38725c..66df35f9ee4 100644 --- a/compiler/rustc_pattern_analysis/src/lib.rs +++ b/compiler/rustc_pattern_analysis/src/lib.rs @@ -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. diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index e9795126db6..ee72b676b38 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -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>, diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index fb94b4afebb..b1c646e9884 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -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, |
