rustc_pattern_analysis/
checks.rs

1//! Contains checks that must be run to validate matches before performing usefulness analysis.
2
3use crate::constructor::Constructor::*;
4use crate::pat_column::PatternColumn;
5use crate::{MatchArm, PatCx};
6
7/// Validate that deref patterns and normal constructors aren't used to match on the same place.
8pub(crate) fn detect_mixed_deref_pat_ctors<'p, Cx: PatCx>(
9    cx: &Cx,
10    arms: &[MatchArm<'p, Cx>],
11) -> Result<(), Cx::Error> {
12    let pat_column = PatternColumn::new(arms);
13    detect_mixed_deref_pat_ctors_inner(cx, &pat_column)
14}
15
16fn detect_mixed_deref_pat_ctors_inner<'p, Cx: PatCx>(
17    cx: &Cx,
18    column: &PatternColumn<'p, Cx>,
19) -> Result<(), Cx::Error> {
20    let Some(ty) = column.head_ty() else {
21        return Ok(());
22    };
23
24    // Check for a mix of deref patterns and normal constructors.
25    let mut deref_pat = None;
26    let mut normal_pat = None;
27    for pat in column.iter() {
28        match pat.ctor() {
29            // The analysis can handle mixing deref patterns with wildcards and opaque patterns.
30            Wildcard | Opaque(_) => {}
31            DerefPattern(_) => deref_pat = Some(pat),
32            // Nothing else can be compared to deref patterns in `Constructor::is_covered_by`.
33            _ => normal_pat = Some(pat),
34        }
35    }
36    if let Some(deref_pat) = deref_pat
37        && let Some(normal_pat) = normal_pat
38    {
39        return Err(cx.report_mixed_deref_pat_ctors(deref_pat, normal_pat));
40    }
41
42    // Specialize and recurse into the patterns' fields.
43    let set = column.analyze_ctors(cx, &ty)?;
44    for ctor in set.present {
45        for specialized_column in column.specialize(cx, &ty, &ctor).iter() {
46            detect_mixed_deref_pat_ctors_inner(cx, specialized_column)?;
47        }
48    }
49    Ok(())
50}