Skip to content

Commit acefba3

Browse files
committed
Check pattern error while lowering
1 parent c0c930d commit acefba3

File tree

1 file changed

+29
-42
lines changed

1 file changed

+29
-42
lines changed

compiler/rustc_mir_build/src/thir/pattern/check_match.rs

Lines changed: 29 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ struct MatchVisitor<'a, 'p, 'tcx> {
8181
lint_level: HirId,
8282
let_source: LetSource,
8383
pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
84+
/// Tracks if we encountered an error while checking this body. That the first function to
85+
/// report it stores it here. Some functions return `Result` to allow callers to short-circuit
86+
/// on error, but callers don't need to store it here again.
8487
error: Result<(), ErrorGuaranteed>,
8588
}
8689

@@ -211,11 +214,16 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
211214
}
212215

213216
fn lower_pattern(
214-
&self,
215-
cx: &mut MatchCheckCtxt<'p, 'tcx>,
217+
&mut self,
218+
cx: &MatchCheckCtxt<'p, 'tcx>,
216219
pattern: &Pat<'tcx>,
217-
) -> &'p DeconstructedPat<'p, 'tcx> {
218-
cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern))
220+
) -> Result<&'p DeconstructedPat<'p, 'tcx>, ErrorGuaranteed> {
221+
if let Err(err) = pattern.pat_error_reported() {
222+
self.error = Err(err);
223+
Err(err)
224+
} else {
225+
Ok(cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, pattern)))
226+
}
219227
}
220228

221229
fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> {
@@ -233,13 +241,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
233241
if let LetSource::None = source {
234242
return;
235243
}
236-
if let Err(err) = pat.pat_error_reported() {
237-
self.error = Err(err);
238-
return;
239-
}
240244
self.check_patterns(pat, Refutable);
241245
let mut cx = self.new_cx(self.lint_level, true);
242-
let tpat = self.lower_pattern(&mut cx, pat);
246+
let Ok(tpat) = self.lower_pattern(&cx, pat) else { return };
243247
self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span);
244248
}
245249

@@ -252,31 +256,22 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
252256
) {
253257
let mut cx = self.new_cx(self.lint_level, true);
254258

259+
let mut tarms = Vec::with_capacity(arms.len());
255260
for &arm in arms {
256261
// Check the arm for some things unrelated to exhaustiveness.
257262
let arm = &self.thir.arms[arm];
258263
self.with_lint_level(arm.lint_level, |this| {
259264
this.check_patterns(&arm.pattern, Refutable);
260265
});
261-
if let Err(err) = arm.pattern.pat_error_reported() {
262-
self.error = Err(err);
263-
return;
264-
}
266+
let hir_id = match arm.lint_level {
267+
LintLevel::Explicit(hir_id) => hir_id,
268+
LintLevel::Inherited => self.lint_level,
269+
};
270+
let Ok(pat) = self.lower_pattern(&mut cx, &arm.pattern) else { return };
271+
let arm = MatchArm { pat, hir_id, has_guard: arm.guard.is_some() };
272+
tarms.push(arm);
265273
}
266274

267-
let tarms: Vec<_> = arms
268-
.iter()
269-
.map(|&arm| {
270-
let arm = &self.thir.arms[arm];
271-
let hir_id = match arm.lint_level {
272-
LintLevel::Explicit(hir_id) => hir_id,
273-
LintLevel::Inherited => self.lint_level,
274-
};
275-
let pat = self.lower_pattern(&mut cx, &arm.pattern);
276-
MatchArm { pat, hir_id, has_guard: arm.guard.is_some() }
277-
})
278-
.collect();
279-
280275
let scrut = &self.thir[scrut];
281276
let scrut_ty = scrut.ty;
282277
let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty, scrut.span);
@@ -340,7 +335,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
340335
// and record chain members that aren't let exprs.
341336
let mut chain_refutabilities = Vec::new();
342337

343-
let mut error = Ok(());
338+
let mut got_lowering_error = false;
344339
let mut next_expr = Some(expr);
345340
while let Some(mut expr) = next_expr {
346341
while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
@@ -368,14 +363,13 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
368363
}
369364
let value = match expr.kind {
370365
ExprKind::Let { box ref pat, expr: _ } => {
371-
if let Err(err) = pat.pat_error_reported() {
372-
error = Err(err);
373-
None
374-
} else {
375-
let mut ncx = self.new_cx(expr_lint_level, true);
376-
let tpat = self.lower_pattern(&mut ncx, pat);
366+
let mut ncx = self.new_cx(expr_lint_level, true);
367+
if let Ok(tpat) = self.lower_pattern(&mut ncx, pat) {
377368
let refutable = !is_let_irrefutable(&mut ncx, expr_lint_level, tpat);
378369
Some((expr.span, refutable))
370+
} else {
371+
got_lowering_error = true;
372+
None
379373
}
380374
}
381375
_ => None,
@@ -385,8 +379,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
385379
debug!(?chain_refutabilities);
386380
chain_refutabilities.reverse();
387381

388-
if error.is_err() {
389-
self.error = error;
382+
if got_lowering_error {
390383
return;
391384
}
392385

@@ -452,15 +445,9 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
452445

453446
#[instrument(level = "trace", skip(self))]
454447
fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
455-
// If we got errors while lowering, don't emit anything more.
456-
if let Err(err) = pat.pat_error_reported() {
457-
self.error = Err(err);
458-
return;
459-
}
460-
461448
let mut cx = self.new_cx(self.lint_level, false);
462449

463-
let pattern = self.lower_pattern(&mut cx, pat);
450+
let Ok(pattern) = self.lower_pattern(&mut cx, pat) else { return };
464451
let pattern_ty = pattern.ty();
465452
let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false };
466453
let report =

0 commit comments

Comments
 (0)