From daac0114591777f29e2f6396e8c2bd5d2c506788 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Oct 2023 00:20:59 +0000 Subject: [PATCH 1/4] Suggest labeling block if `break` is in bare block Fix #103982. --- compiler/rustc_passes/messages.ftl | 2 + compiler/rustc_passes/src/errors.rs | 10 ++++ compiler/rustc_passes/src/loops.rs | 55 ++++++++++++++++--- .../ui/parser/break-in-unlabeled-block.fixed | 12 ++++ tests/ui/parser/break-in-unlabeled-block.rs | 11 ++++ .../ui/parser/break-in-unlabeled-block.stderr | 27 +++++++++ 6 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 tests/ui/parser/break-in-unlabeled-block.fixed create mode 100644 tests/ui/parser/break-in-unlabeled-block.rs create mode 100644 tests/ui/parser/break-in-unlabeled-block.stderr diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index 214c6d70960e5..25ef5245cf169 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -580,6 +580,8 @@ passes_outside_loop = *[false] {""} } +passes_outside_loop_suggestion = consider labeling this block to be able to break within it + passes_params_not_allowed = referencing function parameters is not allowed in naked functions .help = follow the calling convention in asm block to use parameters diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index bcf5abbfe7d9d..4b27b6d8c3698 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1099,6 +1099,16 @@ pub struct OutsideLoop<'a> { pub span: Span, pub name: &'a str, pub is_break: bool, + #[subdiagnostic] + pub suggestion: Option, +} +#[derive(Subdiagnostic)] +#[multipart_suggestion(passes_outside_loop_suggestion, applicability = "maybe-incorrect")] +pub struct OutsideLoopSuggestion { + #[suggestion_part(code = "'block: ")] + pub block_span: Span, + #[suggestion_part(code = " 'block")] + pub break_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 0aaf85086e455..10763556c7c67 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -1,7 +1,7 @@ use Context::*; use rustc_hir as hir; -use rustc_hir::def_id::LocalModDefId; +use rustc_hir::def_id::{LocalDefId, LocalModDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{Destination, Movability, Node}; use rustc_middle::hir::map::Map; @@ -10,19 +10,21 @@ use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_span::hygiene::DesugaringKind; -use rustc_span::Span; +use rustc_span::{BytePos, Span}; use crate::errors::{ BreakInsideAsyncBlock, BreakInsideClosure, BreakNonLoop, ContinueLabeledBlock, OutsideLoop, - UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, + OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock, }; #[derive(Clone, Copy, Debug, PartialEq)] enum Context { Normal, + Fn, Loop(hir::LoopSource), Closure(Span), AsyncClosure(Span), + UnlabeledBlock(Span), LabeledBlock, Constant, } @@ -60,6 +62,25 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { self.with_context(Constant, |v| intravisit::walk_inline_const(v, c)); } + fn visit_fn( + &mut self, + fk: hir::intravisit::FnKind<'hir>, + fd: &'hir hir::FnDecl<'hir>, + b: hir::BodyId, + _: Span, + id: LocalDefId, + ) { + self.with_context(Fn, |v| intravisit::walk_fn(v, fk, fd, b, id)); + } + + fn visit_trait_item(&mut self, trait_item: &'hir hir::TraitItem<'hir>) { + self.with_context(Fn, |v| intravisit::walk_trait_item(v, trait_item)); + } + + fn visit_impl_item(&mut self, impl_item: &'hir hir::ImplItem<'hir>) { + self.with_context(Fn, |v| intravisit::walk_impl_item(v, impl_item)); + } + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { match e.kind { hir::ExprKind::Loop(ref b, _, source, _) => { @@ -83,6 +104,14 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { hir::ExprKind::Block(ref b, Some(_label)) => { self.with_context(LabeledBlock, |v| v.visit_block(&b)); } + hir::ExprKind::Block(ref b, None) if matches!(self.cx, Fn) => { + self.with_context(Normal, |v| v.visit_block(&b)); + } + hir::ExprKind::Block(ref b, None) + if matches!(self.cx, Normal | Constant | UnlabeledBlock(_)) => + { + self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(&b)); + } hir::ExprKind::Break(break_label, ref opt_expr) => { if let Some(e) = opt_expr { self.visit_expr(e); @@ -147,7 +176,12 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } } - self.require_break_cx("break", e.span); + let sp_lo = e.span.with_lo(e.span.lo() + BytePos("break".len() as u32)); + let label_sp = match break_label.label { + Some(label) => sp_lo.with_hi(label.ident.span.hi()), + None => sp_lo.shrink_to_lo(), + }; + self.require_break_cx("break", e.span, label_sp); } hir::ExprKind::Continue(destination) => { self.require_label_in_labeled_block(e.span, &destination, "continue"); @@ -169,7 +203,7 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> { } Err(_) => {} } - self.require_break_cx("continue", e.span) + self.require_break_cx("continue", e.span, e.span) } _ => intravisit::walk_expr(self, e), } @@ -187,7 +221,8 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { self.cx = old_cx; } - fn require_break_cx(&self, name: &str, span: Span) { + fn require_break_cx(&self, name: &str, span: Span, break_span: Span) { + let is_break = name == "break"; match self.cx { LabeledBlock | Loop(_) => {} Closure(closure_span) => { @@ -196,8 +231,12 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { AsyncClosure(closure_span) => { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } - Normal | Constant => { - self.sess.emit_err(OutsideLoop { span, name, is_break: name == "break" }); + UnlabeledBlock(block_span) if is_break => { + let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); + self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion }); + } + Normal | Constant | Fn | UnlabeledBlock(_) => { + self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion: None }); } } } diff --git a/tests/ui/parser/break-in-unlabeled-block.fixed b/tests/ui/parser/break-in-unlabeled-block.fixed new file mode 100644 index 0000000000000..0e496430ae677 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.fixed @@ -0,0 +1,12 @@ +// run-rustfix +fn main() { + 'block: { + break 'block (); //~ ERROR `break` outside of a loop or labeled block + } + { + 'block: { + break 'block (); //~ ERROR `break` outside of a loop or labeled block + } + } +} + diff --git a/tests/ui/parser/break-in-unlabeled-block.rs b/tests/ui/parser/break-in-unlabeled-block.rs new file mode 100644 index 0000000000000..3e5587e9f9c97 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.rs @@ -0,0 +1,11 @@ +// run-rustfix +fn main() { + { + break (); //~ ERROR `break` outside of a loop or labeled block + } + { + { + break (); //~ ERROR `break` outside of a loop or labeled block + } + } +} diff --git a/tests/ui/parser/break-in-unlabeled-block.stderr b/tests/ui/parser/break-in-unlabeled-block.stderr new file mode 100644 index 0000000000000..632cca80d8c03 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block.stderr @@ -0,0 +1,27 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block.rs:4:9 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ break 'block (); + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block.rs:8:13 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ break 'block (); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0268`. From 5c17b8be61b69be6c38619f829ba81c64212110d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 3 Oct 2023 21:34:52 +0000 Subject: [PATCH 2/4] Move some tests around --- tests/ui/parser/{ => attribute}/attr-bad-meta-2.rs | 0 tests/ui/parser/{ => attribute}/attr-bad-meta-2.stderr | 0 tests/ui/parser/{ => attribute}/attr-bad-meta-3.rs | 0 tests/ui/parser/{ => attribute}/attr-bad-meta-3.stderr | 0 tests/ui/parser/{ => attribute}/attr-bad-meta.rs | 0 tests/ui/parser/{ => attribute}/attr-bad-meta.stderr | 0 tests/ui/parser/{ => attribute}/attr-before-eof.rs | 0 tests/ui/parser/{ => attribute}/attr-before-eof.stderr | 0 tests/ui/parser/{ => attribute}/attr-dangling-in-fn.rs | 0 tests/ui/parser/{ => attribute}/attr-dangling-in-fn.stderr | 0 tests/ui/parser/{ => attribute}/attr-dangling-in-mod.rs | 0 tests/ui/parser/{ => attribute}/attr-dangling-in-mod.stderr | 0 tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.rs | 0 tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.stderr | 0 tests/ui/parser/{ => attribute}/attr-with-a-semicolon.rs | 0 tests/ui/parser/{ => attribute}/attr-with-a-semicolon.stderr | 0 tests/ui/parser/{ => attribute}/attr.rs | 0 tests/ui/parser/{ => attribute}/attr.stderr | 0 .../attribute-with-no-generics-in-parameter-list.rs | 0 .../attribute-with-no-generics-in-parameter-list.stderr | 0 tests/ui/parser/{ => attribute}/attrs-after-extern-mod.rs | 0 tests/ui/parser/{ => attribute}/attrs-after-extern-mod.stderr | 0 22 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/parser/{ => attribute}/attr-bad-meta-2.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-2.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-3.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta-3.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta.rs (100%) rename tests/ui/parser/{ => attribute}/attr-bad-meta.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-before-eof.rs (100%) rename tests/ui/parser/{ => attribute}/attr-before-eof.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-fn.rs (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-fn.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-mod.rs (100%) rename tests/ui/parser/{ => attribute}/attr-dangling-in-mod.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.rs (100%) rename tests/ui/parser/{ => attribute}/attr-stmt-expr-attr-bad.stderr (100%) rename tests/ui/parser/{ => attribute}/attr-with-a-semicolon.rs (100%) rename tests/ui/parser/{ => attribute}/attr-with-a-semicolon.stderr (100%) rename tests/ui/parser/{ => attribute}/attr.rs (100%) rename tests/ui/parser/{ => attribute}/attr.stderr (100%) rename tests/ui/parser/{ => attribute}/attribute-with-no-generics-in-parameter-list.rs (100%) rename tests/ui/parser/{ => attribute}/attribute-with-no-generics-in-parameter-list.stderr (100%) rename tests/ui/parser/{ => attribute}/attrs-after-extern-mod.rs (100%) rename tests/ui/parser/{ => attribute}/attrs-after-extern-mod.stderr (100%) diff --git a/tests/ui/parser/attr-bad-meta-2.rs b/tests/ui/parser/attribute/attr-bad-meta-2.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta-2.rs rename to tests/ui/parser/attribute/attr-bad-meta-2.rs diff --git a/tests/ui/parser/attr-bad-meta-2.stderr b/tests/ui/parser/attribute/attr-bad-meta-2.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta-2.stderr rename to tests/ui/parser/attribute/attr-bad-meta-2.stderr diff --git a/tests/ui/parser/attr-bad-meta-3.rs b/tests/ui/parser/attribute/attr-bad-meta-3.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta-3.rs rename to tests/ui/parser/attribute/attr-bad-meta-3.rs diff --git a/tests/ui/parser/attr-bad-meta-3.stderr b/tests/ui/parser/attribute/attr-bad-meta-3.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta-3.stderr rename to tests/ui/parser/attribute/attr-bad-meta-3.stderr diff --git a/tests/ui/parser/attr-bad-meta.rs b/tests/ui/parser/attribute/attr-bad-meta.rs similarity index 100% rename from tests/ui/parser/attr-bad-meta.rs rename to tests/ui/parser/attribute/attr-bad-meta.rs diff --git a/tests/ui/parser/attr-bad-meta.stderr b/tests/ui/parser/attribute/attr-bad-meta.stderr similarity index 100% rename from tests/ui/parser/attr-bad-meta.stderr rename to tests/ui/parser/attribute/attr-bad-meta.stderr diff --git a/tests/ui/parser/attr-before-eof.rs b/tests/ui/parser/attribute/attr-before-eof.rs similarity index 100% rename from tests/ui/parser/attr-before-eof.rs rename to tests/ui/parser/attribute/attr-before-eof.rs diff --git a/tests/ui/parser/attr-before-eof.stderr b/tests/ui/parser/attribute/attr-before-eof.stderr similarity index 100% rename from tests/ui/parser/attr-before-eof.stderr rename to tests/ui/parser/attribute/attr-before-eof.stderr diff --git a/tests/ui/parser/attr-dangling-in-fn.rs b/tests/ui/parser/attribute/attr-dangling-in-fn.rs similarity index 100% rename from tests/ui/parser/attr-dangling-in-fn.rs rename to tests/ui/parser/attribute/attr-dangling-in-fn.rs diff --git a/tests/ui/parser/attr-dangling-in-fn.stderr b/tests/ui/parser/attribute/attr-dangling-in-fn.stderr similarity index 100% rename from tests/ui/parser/attr-dangling-in-fn.stderr rename to tests/ui/parser/attribute/attr-dangling-in-fn.stderr diff --git a/tests/ui/parser/attr-dangling-in-mod.rs b/tests/ui/parser/attribute/attr-dangling-in-mod.rs similarity index 100% rename from tests/ui/parser/attr-dangling-in-mod.rs rename to tests/ui/parser/attribute/attr-dangling-in-mod.rs diff --git a/tests/ui/parser/attr-dangling-in-mod.stderr b/tests/ui/parser/attribute/attr-dangling-in-mod.stderr similarity index 100% rename from tests/ui/parser/attr-dangling-in-mod.stderr rename to tests/ui/parser/attribute/attr-dangling-in-mod.stderr diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs similarity index 100% rename from tests/ui/parser/attr-stmt-expr-attr-bad.rs rename to tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs diff --git a/tests/ui/parser/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr similarity index 100% rename from tests/ui/parser/attr-stmt-expr-attr-bad.stderr rename to tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr diff --git a/tests/ui/parser/attr-with-a-semicolon.rs b/tests/ui/parser/attribute/attr-with-a-semicolon.rs similarity index 100% rename from tests/ui/parser/attr-with-a-semicolon.rs rename to tests/ui/parser/attribute/attr-with-a-semicolon.rs diff --git a/tests/ui/parser/attr-with-a-semicolon.stderr b/tests/ui/parser/attribute/attr-with-a-semicolon.stderr similarity index 100% rename from tests/ui/parser/attr-with-a-semicolon.stderr rename to tests/ui/parser/attribute/attr-with-a-semicolon.stderr diff --git a/tests/ui/parser/attr.rs b/tests/ui/parser/attribute/attr.rs similarity index 100% rename from tests/ui/parser/attr.rs rename to tests/ui/parser/attribute/attr.rs diff --git a/tests/ui/parser/attr.stderr b/tests/ui/parser/attribute/attr.stderr similarity index 100% rename from tests/ui/parser/attr.stderr rename to tests/ui/parser/attribute/attr.stderr diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.rs similarity index 100% rename from tests/ui/parser/attribute-with-no-generics-in-parameter-list.rs rename to tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.rs diff --git a/tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr b/tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr similarity index 100% rename from tests/ui/parser/attribute-with-no-generics-in-parameter-list.stderr rename to tests/ui/parser/attribute/attribute-with-no-generics-in-parameter-list.stderr diff --git a/tests/ui/parser/attrs-after-extern-mod.rs b/tests/ui/parser/attribute/attrs-after-extern-mod.rs similarity index 100% rename from tests/ui/parser/attrs-after-extern-mod.rs rename to tests/ui/parser/attribute/attrs-after-extern-mod.rs diff --git a/tests/ui/parser/attrs-after-extern-mod.stderr b/tests/ui/parser/attribute/attrs-after-extern-mod.stderr similarity index 100% rename from tests/ui/parser/attrs-after-extern-mod.stderr rename to tests/ui/parser/attribute/attrs-after-extern-mod.stderr From c30d57bb77535f3923cbfa666e84d1916b6bce37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 4 Oct 2023 01:29:45 +0000 Subject: [PATCH 3/4] fix --- tests/ui/parser/break-in-unlabeled-block.fixed | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/ui/parser/break-in-unlabeled-block.fixed b/tests/ui/parser/break-in-unlabeled-block.fixed index 0e496430ae677..0885623252160 100644 --- a/tests/ui/parser/break-in-unlabeled-block.fixed +++ b/tests/ui/parser/break-in-unlabeled-block.fixed @@ -9,4 +9,3 @@ fn main() { } } } - From d23dc2093c2037a3f401d917ddb9e9c8507ef116 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 9 Oct 2023 22:48:10 +0000 Subject: [PATCH 4/4] Account for macros --- compiler/rustc_passes/src/loops.rs | 2 +- .../break-in-unlabeled-block-in-macro.rs | 43 ++++++++++++ .../break-in-unlabeled-block-in-macro.stderr | 69 +++++++++++++++++++ 3 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 tests/ui/parser/break-in-unlabeled-block-in-macro.rs create mode 100644 tests/ui/parser/break-in-unlabeled-block-in-macro.stderr diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs index 10763556c7c67..4590ab9e4f579 100644 --- a/compiler/rustc_passes/src/loops.rs +++ b/compiler/rustc_passes/src/loops.rs @@ -231,7 +231,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> { AsyncClosure(closure_span) => { self.sess.emit_err(BreakInsideAsyncBlock { span, closure_span, name }); } - UnlabeledBlock(block_span) if is_break => { + UnlabeledBlock(block_span) if is_break && block_span.ctxt() == break_span.ctxt() => { let suggestion = Some(OutsideLoopSuggestion { block_span, break_span }); self.sess.emit_err(OutsideLoop { span, name, is_break, suggestion }); } diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.rs b/tests/ui/parser/break-in-unlabeled-block-in-macro.rs new file mode 100644 index 0000000000000..eecc0026b12d6 --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.rs @@ -0,0 +1,43 @@ +macro_rules! foo { + () => { + break (); //~ ERROR `break` outside of a loop or labeled block + }; + ($e: expr) => { + break $e; //~ ERROR `break` outside of a loop or labeled block + }; + (stmt $s: stmt) => { + $s + }; + (@ $e: expr) => { + { break $e; } //~ ERROR `break` outside of a loop or labeled block + }; + (=> $s: stmt) => { + { $s } + }; +} + +fn main() { + { + foo!(); + } + { + foo!(()); + } + { + foo!(stmt break ()); //~ ERROR `break` outside of a loop or labeled block + } + { + foo!(@ ()); + } + { + foo!(=> break ()); //~ ERROR `break` outside of a loop or labeled block + } + { + macro_rules! bar { + () => { + break () //~ ERROR `break` outside of a loop or labeled block + }; + } + bar!() + } +} diff --git a/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr new file mode 100644 index 0000000000000..9407e8ac0029d --- /dev/null +++ b/tests/ui/parser/break-in-unlabeled-block-in-macro.stderr @@ -0,0 +1,69 @@ +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:3:9 + | +LL | break (); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(); + | ------ in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:6:9 + | +LL | break $e; + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(()); + | -------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:27:19 + | +LL | foo!(stmt break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + | +help: consider labeling this block to be able to break within it + | +LL ~ 'block: { +LL ~ foo!(stmt break 'block ()); + | + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:12:11 + | +LL | { break $e; } + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | foo!(@ ()); + | ---------- in this macro invocation + | + = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider labeling this block to be able to break within it + | +LL | 'block: { break 'block $e; } + | +++++++ ++++++ + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17 + | +LL | foo!(=> break ()); + | ^^^^^^^^ cannot `break` outside of a loop or labeled block + +error[E0268]: `break` outside of a loop or labeled block + --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17 + | +LL | break () + | ^^^^^^^^ cannot `break` outside of a loop or labeled block +... +LL | bar!() + | ------ in this macro invocation + | + = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0268`.