| //! Contains checks that must be run to validate matches before performing usefulness analysis. |
| |
| use crate::constructor::Constructor::*; |
| use crate::pat_column::PatternColumn; |
| use crate::{MatchArm, PatCx}; |
| |
| /// Validate that deref patterns and normal constructors aren't used to match on the same place. |
| pub(crate) fn detect_mixed_deref_pat_ctors<'p, Cx: PatCx>( |
| cx: &Cx, |
| arms: &[MatchArm<'p, Cx>], |
| ) -> Result<(), Cx::Error> { |
| let pat_column = PatternColumn::new(arms); |
| detect_mixed_deref_pat_ctors_inner(cx, &pat_column) |
| } |
| |
| fn detect_mixed_deref_pat_ctors_inner<'p, Cx: PatCx>( |
| cx: &Cx, |
| column: &PatternColumn<'p, Cx>, |
| ) -> Result<(), Cx::Error> { |
| let Some(ty) = column.head_ty() else { |
| return Ok(()); |
| }; |
| |
| // Check for a mix of deref patterns and normal constructors. |
| let mut deref_pat = None; |
| let mut normal_pat = None; |
| for pat in column.iter() { |
| match pat.ctor() { |
| // The analysis can handle mixing deref patterns with wildcards and opaque patterns. |
| Wildcard | Opaque(_) => {} |
| DerefPattern(_) => deref_pat = Some(pat), |
| // Nothing else can be compared to deref patterns in `Constructor::is_covered_by`. |
| _ => normal_pat = Some(pat), |
| } |
| } |
| if let Some(deref_pat) = deref_pat |
| && let Some(normal_pat) = normal_pat |
| { |
| return Err(cx.report_mixed_deref_pat_ctors(deref_pat, normal_pat)); |
| } |
| |
| // Specialize and recurse into the patterns' fields. |
| let set = column.analyze_ctors(cx, &ty)?; |
| for ctor in set.present { |
| for specialized_column in column.specialize(cx, &ty, &ctor).iter() { |
| detect_mixed_deref_pat_ctors_inner(cx, specialized_column)?; |
| } |
| } |
| Ok(()) |
| } |