Rollup merge of #128701 - veera-sivarajan:fix-128604, r=estebank

Don't Suggest Labeling `const` and `unsafe` Blocks

Fixes #128604

Previously, both anonymous constant blocks (E.g. The labeled block
inside `['_'; 'block: { break 'block 1 + 2; }]`) and inline const
blocks (E.g. `const { ... }`) were considered to be the same
kind of blocks. This caused the compiler to incorrectly suggest
labeling both the blocks when only anonymous constant blocks can be
labeled.

This PR adds an other enum variant to `Context` so that both the
blocks can be handled appropriately.

Also, adds some doc comments and removes unnecessary `&mut` in a
couple of places.
This commit is contained in:
Matthias Krüger 2024-09-03 19:13:23 +02:00 committed by GitHub
commit 51c686f32b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 166 additions and 14 deletions

View File

@ -19,17 +19,25 @@
OutsideLoopSuggestion, UnlabeledCfInWhileCondition, UnlabeledInLabeledBlock,
};
/// The context in which a block is encountered.
#[derive(Clone, Copy, Debug, PartialEq)]
enum Context {
Normal,
Fn,
Loop(hir::LoopSource),
Closure(Span),
Coroutine { coroutine_span: Span, kind: hir::CoroutineDesugaring, source: hir::CoroutineSource },
Coroutine {
coroutine_span: Span,
kind: hir::CoroutineDesugaring,
source: hir::CoroutineSource,
},
UnlabeledBlock(Span),
UnlabeledIfBlock(Span),
LabeledBlock,
Constant,
/// E.g. The labeled block inside `['_'; 'block: { break 'block 1 + 2; }]`.
AnonConst,
/// E.g. `const { ... }`.
ConstBlock,
}
#[derive(Clone)]
@ -90,11 +98,11 @@ fn nested_visit_map(&mut self) -> Self::Map {
}
fn visit_anon_const(&mut self, c: &'hir hir::AnonConst) {
self.with_context(Constant, |v| intravisit::walk_anon_const(v, c));
self.with_context(AnonConst, |v| intravisit::walk_anon_const(v, c));
}
fn visit_inline_const(&mut self, c: &'hir hir::ConstBlock) {
self.with_context(Constant, |v| intravisit::walk_inline_const(v, c));
self.with_context(ConstBlock, |v| intravisit::walk_inline_const(v, c));
}
fn visit_fn(
@ -128,7 +136,7 @@ fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) {
&& matches!(
ck_loop.cx_stack.last(),
Some(&Normal)
| Some(&Constant)
| Some(&AnonConst)
| Some(&UnlabeledBlock(_))
| Some(&UnlabeledIfBlock(_))
)
@ -175,14 +183,18 @@ fn visit_expr(&mut self, e: &'hir hir::Expr<'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_stack.last(), Some(&Fn)) => {
hir::ExprKind::Block(ref b, None)
if matches!(self.cx_stack.last(), Some(&Fn) | Some(&ConstBlock)) =>
{
self.with_context(Normal, |v| v.visit_block(b));
}
hir::ExprKind::Block(ref b, None)
if matches!(
self.cx_stack.last(),
Some(&Normal) | Some(&Constant) | Some(&UnlabeledBlock(_))
) =>
hir::ExprKind::Block(
ref b @ hir::Block { rules: hir::BlockCheckMode::DefaultBlock, .. },
None,
) if matches!(
self.cx_stack.last(),
Some(&Normal) | Some(&AnonConst) | Some(&UnlabeledBlock(_))
) =>
{
self.with_context(UnlabeledBlock(b.span.shrink_to_lo()), |v| v.visit_block(b));
}
@ -353,7 +365,7 @@ fn require_break_cx(
UnlabeledIfBlock(_) if br_cx_kind == BreakContextKind::Break => {
self.require_break_cx(br_cx_kind, span, break_span, cx_pos - 1);
}
Normal | Constant | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) => {
Normal | AnonConst | Fn | UnlabeledBlock(_) | UnlabeledIfBlock(_) | ConstBlock => {
self.sess.dcx().emit_err(OutsideLoop {
spans: vec![span],
name: &br_cx_kind.to_string(),
@ -365,7 +377,7 @@ fn require_break_cx(
}
fn require_label_in_labeled_block(
&mut self,
&self,
span: Span,
label: &Destination,
cf_type: &str,
@ -380,7 +392,7 @@ fn require_label_in_labeled_block(
false
}
fn report_outside_loop_error(&mut self) {
fn report_outside_loop_error(&self) {
for (s, block) in &self.block_breaks {
self.sess.dcx().emit_err(OutsideLoop {
spans: block.spans.clone(),

View File

@ -0,0 +1,25 @@
fn main() {
let _ = ['a'; { break 2; 1 }];
//~^ ERROR `break` outside of a loop or labeled block
//~| HELP consider labeling this block to be able to break within it
const {
{
//~^ HELP consider labeling this block to be able to break within it
break;
//~^ ERROR `break` outside of a loop or labeled block
}
};
const {
break;
//~^ ERROR `break` outside of a loop or labeled block
};
{
const {
break;
//~^ ERROR `break` outside of a loop or labeled block
}
}
}

View File

@ -0,0 +1,39 @@
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-inline-const-issue-128604.rs:15:9
|
LL | break;
| ^^^^^ cannot `break` outside of a loop or labeled block
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-inline-const-issue-128604.rs:21:13
|
LL | break;
| ^^^^^ cannot `break` outside of a loop or labeled block
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-inline-const-issue-128604.rs:2:21
|
LL | let _ = ['a'; { break 2; 1 }];
| ^^^^^^^ cannot `break` outside of a loop or labeled block
|
help: consider labeling this block to be able to break within it
|
LL | let _ = ['a'; 'block: { break 'block 2; 1 }];
| +++++++ ++++++
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-inline-const-issue-128604.rs:9: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 |
LL ~ break 'block;
|
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0268`.

View File

@ -0,0 +1,34 @@
fn main() {
let a = ["_"; unsafe { break; 1 + 2 }];
//~^ ERROR `break` outside of a loop or labeled block
unsafe {
{
//~^ HELP consider labeling this block to be able to break within it
break;
//~^ ERROR `break` outside of a loop or labeled block
}
}
unsafe {
break;
//~^ ERROR `break` outside of a loop or labeled block
}
{
//~^ HELP consider labeling this block to be able to break within it
unsafe {
break;
//~^ ERROR `break` outside of a loop or labeled block
}
}
while 2 > 1 {
unsafe {
if true || false {
break;
}
}
}
}

View File

@ -0,0 +1,42 @@
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-unsafe-block-issue-128604.rs:2:28
|
LL | let a = ["_"; unsafe { break; 1 + 2 }];
| ^^^^^ cannot `break` outside of a loop or labeled block
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-unsafe-block-issue-128604.rs:14:9
|
LL | break;
| ^^^^^ cannot `break` outside of a loop or labeled block
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-unsafe-block-issue-128604.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 |
LL ~ break 'block;
|
error[E0268]: `break` outside of a loop or labeled block
--> $DIR/break-inside-unsafe-block-issue-128604.rs:21: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 |
LL | unsafe {
LL ~ break 'block;
|
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0268`.