about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-09-03 19:13:23 +0200
committerGitHub <noreply@github.com>2024-09-03 19:13:23 +0200
commit51c686f32b937065b22ac416065733980d936f4c (patch)
tree2431fad806c7efc8cbffd9b58a6aa59124245e93
parentf75a1954eb1c358c5a2ef99736dabac636d40ef7 (diff)
parentf003e92a5ba73c673f0faeaac01b6eac6ba3f76a (diff)
downloadrust-51c686f32b937065b22ac416065733980d936f4c.tar.gz
rust-51c686f32b937065b22ac416065733980d936f4c.zip
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.
-rw-r--r--compiler/rustc_passes/src/loops.rs40
-rw-r--r--tests/ui/inline-const/break-inside-inline-const-issue-128604.rs25
-rw-r--r--tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr39
-rw-r--r--tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs34
-rw-r--r--tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr42
5 files changed, 166 insertions, 14 deletions
diff --git a/compiler/rustc_passes/src/loops.rs b/compiler/rustc_passes/src/loops.rs
index 25115c5cafd..c11562ae39e 100644
--- a/compiler/rustc_passes/src/loops.rs
+++ b/compiler/rustc_passes/src/loops.rs
@@ -19,17 +19,25 @@ use crate::errors::{
     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 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
     }
 
     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 @@ impl<'a, 'hir> Visitor<'hir> for CheckLoopVisitor<'a, 'hir> {
                         && matches!(
                             ck_loop.cx_stack.last(),
                             Some(&Normal)
-                                | Some(&Constant)
+                                | Some(&AnonConst)
                                 | Some(&UnlabeledBlock(_))
                                 | Some(&UnlabeledIfBlock(_))
                         )
@@ -175,14 +183,18 @@ 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_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 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
             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 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
     }
 
     fn require_label_in_labeled_block(
-        &mut self,
+        &self,
         span: Span,
         label: &Destination,
         cf_type: &str,
@@ -380,7 +392,7 @@ impl<'a, 'hir> CheckLoopVisitor<'a, 'hir> {
         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(),
diff --git a/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs b/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs
new file mode 100644
index 00000000000..a9795d1569c
--- /dev/null
+++ b/tests/ui/inline-const/break-inside-inline-const-issue-128604.rs
@@ -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
+        }
+    }
+}
diff --git a/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr b/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr
new file mode 100644
index 00000000000..300cd45ad69
--- /dev/null
+++ b/tests/ui/inline-const/break-inside-inline-const-issue-128604.stderr
@@ -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`.
diff --git a/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs
new file mode 100644
index 00000000000..a83141f0e4e
--- /dev/null
+++ b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.rs
@@ -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;
+            }
+        }
+    }
+
+}
diff --git a/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr
new file mode 100644
index 00000000000..b7cbe1a5cf4
--- /dev/null
+++ b/tests/ui/unsafe/break-inside-unsafe-block-issue-128604.stderr
@@ -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`.