1
Fork 0

Bail out of MIR construction if check_match fails

This commit is contained in:
clubby789 2023-04-30 16:31:36 +01:00
parent c1bb0e0911
commit 2d5ca0ea4f
5 changed files with 154 additions and 13 deletions

View file

@ -42,7 +42,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
// Ensure unsafeck and abstract const building is ran before we steal the THIR.
tcx.ensure_with_value().thir_check_unsafety(def);
tcx.ensure_with_value().thir_abstract_const(def);
tcx.ensure_with_value().check_match(def);
if let Err(e) = tcx.check_match(def) {
return construct_error(tcx, def, e);
}
let body = match tcx.thir_body(def) {
Err(error_reported) => construct_error(tcx, def, error_reported),

View file

@ -26,8 +26,8 @@ use rustc_session::Session;
use rustc_span::hygiene::DesugaringKind;
use rustc_span::Span;
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) {
let Ok((thir, expr)) = tcx.thir_body(def_id) else { return };
pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), ErrorGuaranteed> {
let (thir, expr) = tcx.thir_body(def_id)?;
let thir = thir.borrow();
let pattern_arena = TypedArena::default();
let mut visitor = MatchVisitor {
@ -37,13 +37,16 @@ pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) {
lint_level: tcx.hir().local_def_id_to_hir_id(def_id),
let_source: LetSource::None,
pattern_arena: &pattern_arena,
error: Ok(()),
};
visitor.visit_expr(&thir[expr]);
for param in thir.params.iter() {
if let Some(box ref pattern) = param.pat {
visitor.check_irrefutable(pattern, "function argument", None);
}
}
visitor.error
}
fn create_e0004(
@ -77,6 +80,7 @@ struct MatchVisitor<'a, 'p, 'tcx> {
lint_level: HirId,
let_source: LetSource,
pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
error: Result<(), ErrorGuaranteed>,
}
impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
@ -276,9 +280,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
let [pat_field] = &subpatterns[..] else { bug!() };
self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None);
} else {
non_exhaustive_match(
self.error = Err(non_exhaustive_match(
&cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
);
));
}
}
}
@ -409,7 +413,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
}
#[instrument(level = "trace", skip(self))]
fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
let mut cx = self.new_cx(self.lint_level, false);
let pattern = self.lower_pattern(&mut cx, pat);
@ -478,7 +482,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
AdtDefinedHere { adt_def_span, ty, variants }
};
self.tcx.sess.emit_err(PatternNotCovered {
self.error = Err(self.tcx.sess.emit_err(PatternNotCovered {
span: pat.span,
origin,
uncovered: Uncovered::new(pat.span, &cx, witnesses),
@ -489,7 +493,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
let_suggestion,
misc_suggestion,
adt_defined_here,
});
}));
}
}
@ -631,7 +635,7 @@ fn non_exhaustive_match<'p, 'tcx>(
witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
arms: &[ArmId],
expr_span: Span,
) {
) -> ErrorGuaranteed {
let is_empty_match = arms.is_empty();
let non_empty_enum = match scrut_ty.kind() {
ty::Adt(def, _) => def.is_enum() && !def.variants().is_empty(),
@ -643,13 +647,12 @@ fn non_exhaustive_match<'p, 'tcx>(
let pattern;
let patterns_len;
if is_empty_match && !non_empty_enum {
cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty {
return cx.tcx.sess.emit_err(NonExhaustivePatternsTypeNotEmpty {
cx,
expr_span,
span: sp,
ty: scrut_ty,
});
return;
} else {
// FIXME: migration of this diagnostic will require list support
let joined_patterns = joined_uncovered_patterns(cx, &witnesses);
@ -800,7 +803,7 @@ fn non_exhaustive_match<'p, 'tcx>(
} else {
err.help(&msg);
}
err.emit();
err.emit()
}
pub(crate) fn joined_uncovered_patterns<'p, 'tcx>(