always check for mixed deref pattern and normal constructors
This makes it work for box patterns and in rust-analyzer.
This commit is contained in:
@@ -1027,6 +1027,21 @@ impl<'p, 'tcx: 'p> PatCx for RustcPatCtxt<'p, 'tcx> {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn report_mixed_deref_pat_ctors(
|
||||
&self,
|
||||
deref_pat: &crate::pat::DeconstructedPat<Self>,
|
||||
normal_pat: &crate::pat::DeconstructedPat<Self>,
|
||||
) -> Self::Error {
|
||||
let deref_pattern_label = deref_pat.data().span;
|
||||
let normal_constructor_label = normal_pat.data().span;
|
||||
self.tcx.dcx().emit_err(errors::MixedDerefPatternConstructors {
|
||||
spans: vec![deref_pattern_label, normal_constructor_label],
|
||||
smart_pointer_ty: deref_pat.ty().inner(),
|
||||
deref_pattern_label,
|
||||
normal_constructor_label,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Recursively expand this pattern into its subpatterns. Only useful for or-patterns.
|
||||
@@ -1055,13 +1070,6 @@ pub fn analyze_match<'p, 'tcx>(
|
||||
) -> Result<UsefulnessReport<'p, 'tcx>, ErrorGuaranteed> {
|
||||
let scrut_ty = tycx.reveal_opaque_ty(scrut_ty);
|
||||
|
||||
// The analysis doesn't support deref patterns mixed with normal constructors; error if present.
|
||||
// FIXME(deref_patterns): This only needs to run when a deref pattern was found during lowering.
|
||||
if tycx.tcx.features().deref_patterns() {
|
||||
let pat_column = PatternColumn::new(arms);
|
||||
detect_mixed_deref_pat_ctors(tycx, &pat_column)?;
|
||||
}
|
||||
|
||||
let scrut_validity = PlaceValidity::from_bool(tycx.known_valid_scrutinee);
|
||||
let report = compute_match_usefulness(
|
||||
tycx,
|
||||
@@ -1080,48 +1088,3 @@ pub fn analyze_match<'p, 'tcx>(
|
||||
|
||||
Ok(report)
|
||||
}
|
||||
|
||||
// FIXME(deref_patterns): Currently it's the responsibility of the frontend (rustc or rust-analyzer)
|
||||
// to ensure that deref patterns don't appear in the same column as normal constructors. Deref
|
||||
// patterns aren't currently implemented in rust-analyzer, but should they be, the columnwise check
|
||||
// here could be made generic and shared between frontends.
|
||||
fn detect_mixed_deref_pat_ctors<'p, 'tcx>(
|
||||
cx: &RustcPatCtxt<'p, 'tcx>,
|
||||
column: &PatternColumn<'p, RustcPatCtxt<'p, 'tcx>>,
|
||||
) -> Result<(), ErrorGuaranteed> {
|
||||
let Some(&ty) = column.head_ty() else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// Check for a mix of deref patterns and normal constructors.
|
||||
let mut normal_ctor_span = None;
|
||||
let mut deref_pat_span = 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_span = Some(pat.data().span),
|
||||
// Nothing else can be compared to deref patterns in `Constructor::is_covered_by`.
|
||||
_ => normal_ctor_span = Some(pat.data().span),
|
||||
}
|
||||
}
|
||||
if let Some(normal_constructor_label) = normal_ctor_span
|
||||
&& let Some(deref_pattern_label) = deref_pat_span
|
||||
{
|
||||
return Err(cx.tcx.dcx().emit_err(errors::MixedDerefPatternConstructors {
|
||||
spans: vec![deref_pattern_label, normal_constructor_label],
|
||||
smart_pointer_ty: ty.inner(),
|
||||
deref_pattern_label,
|
||||
normal_constructor_label,
|
||||
}));
|
||||
}
|
||||
|
||||
// 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(cx, specialized_column)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user