diff options
| author | Nadrieril <nadrieril+git@gmail.com> | 2024-01-24 23:08:36 +0100 |
|---|---|---|
| committer | Nadrieril <nadrieril+git@gmail.com> | 2024-02-07 23:10:51 +0100 |
| commit | cb3ce6645f09929d2e9419aa0a45134db87ab991 (patch) | |
| tree | 1348a37a412f1cfe0b920891ea03d202db445835 /compiler/rustc_pattern_analysis/src/usefulness.rs | |
| parent | 8ace7ea1f7cbba7b4f031e66c54ca237a0d65de6 (diff) | |
| download | rust-cb3ce6645f09929d2e9419aa0a45134db87ab991.tar.gz rust-cb3ce6645f09929d2e9419aa0a45134db87ab991.zip | |
Move usefulness-specific pattern computations to `usefulness`
Diffstat (limited to 'compiler/rustc_pattern_analysis/src/usefulness.rs')
| -rw-r--r-- | compiler/rustc_pattern_analysis/src/usefulness.rs | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/compiler/rustc_pattern_analysis/src/usefulness.rs b/compiler/rustc_pattern_analysis/src/usefulness.rs index 576005b2c7f..219d774513d 100644 --- a/compiler/rustc_pattern_analysis/src/usefulness.rs +++ b/compiler/rustc_pattern_analysis/src/usefulness.rs @@ -1599,6 +1599,36 @@ pub enum Usefulness<'p, Cx: TypeCx> { Redundant, } +/// Report whether this pattern was found useful, and its subpatterns that were not useful if any. +fn collect_pattern_usefulness<'p, Cx: TypeCx>(pat: &'p DeconstructedPat<Cx>) -> Usefulness<'p, Cx> { + fn pat_is_useful<'p, Cx: TypeCx>(pat: &'p DeconstructedPat<Cx>) -> bool { + if pat.useful.get() { + true + } else if pat.is_or_pat() && pat.iter_fields().any(|f| pat_is_useful(f)) { + // We always expand or patterns in the matrix, so we will never see the actual + // or-pattern (the one with constructor `Or`) in the column. As such, it will not be + // marked as useful itself, only its children will. We recover this information here. + true + } else { + false + } + } + + let mut redundant_subpats = Vec::new(); + pat.walk(&mut |p| { + if pat_is_useful(p) { + // The pattern is useful, so we recurse to find redundant subpatterns. + true + } else { + // The pattern is redundant. + redundant_subpats.push(p); + false // stop recursing + } + }); + + if pat_is_useful(pat) { Usefulness::Useful(redundant_subpats) } else { Usefulness::Redundant } +} + /// The output of checking a match for exhaustiveness and arm usefulness. pub struct UsefulnessReport<'p, Cx: TypeCx> { /// For each arm of the input, whether that arm is useful after the arms above it. @@ -1626,12 +1656,7 @@ pub fn compute_match_usefulness<'p, Cx: TypeCx>( .copied() .map(|arm| { debug!(?arm); - // We warn when a pattern is not useful. - let usefulness = if arm.pat.is_useful() { - Usefulness::Useful(arm.pat.redundant_subpatterns()) - } else { - Usefulness::Redundant - }; + let usefulness = collect_pattern_usefulness(arm.pat); (arm, usefulness) }) .collect(); |
