diff --git a/src/librustc_typeck/check/expr.rs b/src/librustc_typeck/check/expr.rs index 4766360c048..5bfc60c7540 100644 --- a/src/librustc_typeck/check/expr.rs +++ b/src/librustc_typeck/check/expr.rs @@ -582,11 +582,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If this is a break with a value, we need to type-check // the expression. Get an expected type from the loop context. let opt_coerce_to = { + // We should release `enclosing_breakables` before the `check_expr_with_hint` + // below, so can't move this block of code to the enclosing scope and share + // `ctxt` with the second `encloding_breakables` borrow below. let mut enclosing_breakables = self.enclosing_breakables.borrow_mut(); - enclosing_breakables.find_breakable(target_id) - .coerce - .as_ref() - .map(|coerce| coerce.expected_ty()) + match enclosing_breakables.opt_find_breakable(target_id) { + Some(ctxt) => + ctxt.coerce.as_ref().map(|coerce| coerce.expected_ty()), + None => { // Avoid ICE when `break` is inside a closure (#65383). + self.tcx.sess.delay_span_bug( + expr.span, + "break was outside loop, but no error was emitted", + ); + return tcx.types.err; + } + } }; // If the loop context is not a `loop { }`, then break with diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.rs b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs new file mode 100644 index 00000000000..bd3c00d2621 --- /dev/null +++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.rs @@ -0,0 +1,7 @@ +// Breaks with values inside closures used to ICE (#66863) + +fn main() { + 'some_label: loop { + || break 'some_label (); //~ ERROR: `break` inside of a closure + } +} diff --git a/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr new file mode 100644 index 00000000000..83bde9775b2 --- /dev/null +++ b/src/test/ui/issues/issue-66702-break-outside-loop-val.stderr @@ -0,0 +1,11 @@ +error[E0267]: `break` inside of a closure + --> $DIR/issue-66702-break-outside-loop-val.rs:5:12 + | +LL | || break 'some_label (); + | -- ^^^^^^^^^^^^^^^^^^^^ cannot `break` inside of a closure + | | + | enclosing closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0267`.