diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs index fb06808619f..6847e45458a 100644 --- a/src/librustc_passes/liveness.rs +++ b/src/librustc_passes/liveness.rs @@ -987,8 +987,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { opt_expr.map_or(succ, |expr| self.propagate_through_expr(expr, succ)) } - fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) - -> LiveNode { + fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode) -> LiveNode { debug!("propagate_through_expr: {}", self.ir.tcx.hir().hir_to_pretty_string(expr.hir_id)); match expr.kind { @@ -1074,7 +1073,15 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> { match target { Some(b) => self.propagate_through_opt_expr(opt_expr.as_ref().map(|e| &**e), b), - None => span_bug!(expr.span, "break to unknown label") + None => { + // FIXME: This should have been checked earlier. Once this is fixed, + // replace with `delay_span_bug`. (#62480) + self.ir.tcx.sess.struct_span_err( + expr.span, + "`break` to unknown label", + ).emit(); + errors::FatalError.raise() + } } } diff --git a/src/test/ui/issues/issue-62480.rs b/src/test/ui/issues/issue-62480.rs new file mode 100644 index 00000000000..bc3e6c69a60 --- /dev/null +++ b/src/test/ui/issues/issue-62480.rs @@ -0,0 +1,10 @@ +#![feature(label_break_value)] + +fn main() { + // This used to ICE during liveness check because `target_id` passed to + // `propagate_through_expr` would be the closure and not the `loop`, which wouldn't be found in + // `self.break_ln`. (#62480) + 'a: { + || break 'a //~ ERROR `break` to unknown label + } +} diff --git a/src/test/ui/issues/issue-62480.stderr b/src/test/ui/issues/issue-62480.stderr new file mode 100644 index 00000000000..de8451ad7df --- /dev/null +++ b/src/test/ui/issues/issue-62480.stderr @@ -0,0 +1,8 @@ +error: `break` to unknown label + --> $DIR/issue-62480.rs:8:12 + | +LL | || break 'a + | ^^^^^^^^ + +error: aborting due to previous error +