From 4657917f6e6c49893e4fbcbe71469d4489b743d0 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Mon, 20 Nov 2023 15:14:08 +0530 Subject: [PATCH] Typeck break expr even if break is illegal We were earlier returning immediately when encountering an illegal break. However, this caused problems later when the expr that the break was returning was evaluated during writeback. So now we don't return and instead simply set tainted by error. This lets typeck of break expr to occur even though we've encountered an illegal break. --- compiler/rustc_hir_typeck/src/expr.rs | 21 +++++++++++-------- .../issue-114529-illegal-break-with-value.rs | 6 ++++++ ...sue-114529-illegal-break-with-value.stderr | 17 ++++++++++++++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a6f78dc8ab53f..59f8f49f77915 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -626,15 +626,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } }; - let coerce_to = match opt_coerce_to { - Some(c) => c, - None => { - // If the loop context is not a `loop { }`, then break with - // a value is illegal, and `opt_coerce_to` will be `None`. - // Return error in that case (#114529). - return Ty::new_misc_error(tcx); - } - }; + // If the loop context is not a `loop { }`, then break with + // a value is illegal, and `opt_coerce_to` will be `None`. + // Set expectation to error in that case and set tainted + // by error (#114529) + let coerce_to = opt_coerce_to.unwrap_or_else(|| { + let guar = tcx.sess.delay_span_bug( + expr.span, + "illegal break with value found but no error reported", + ); + self.set_tainted_by_errors(guar); + Ty::new_error(tcx, guar) + }); // Recurse without `enclosing_breakables` borrowed. e_ty = self.check_expr_with_hint(e, coerce_to); diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.rs b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs index 613d1b6343a34..353a935e37313 100644 --- a/tests/ui/typeck/issue-114529-illegal-break-with-value.rs +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.rs @@ -17,4 +17,10 @@ fn main() { }; 51 }]; + + while true { + break (|| { //~ ERROR `break` with value from a `while` loop + let local = 9; + }); + } } diff --git a/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr index 4d6c27bbbd03b..731f234c162ad 100644 --- a/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr +++ b/tests/ui/typeck/issue-114529-illegal-break-with-value.stderr @@ -24,6 +24,21 @@ help: use `break` on its own without a value inside this `while` loop LL | break; | ~~~~~ -error: aborting due to 2 previous errors +error[E0571]: `break` with value from a `while` loop + --> $DIR/issue-114529-illegal-break-with-value.rs:22:9 + | +LL | while true { + | ---------- you can't `break` with a value in a `while` loop +LL | / break (|| { +LL | | let local = 9; +LL | | }); + | |__________^ can only break with a value inside `loop` or breakable block + | +help: use `break` on its own without a value inside this `while` loop + | +LL | break; + | ~~~~~ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0571`.