rust/compiler
Joshua Nelson 31e39446ec Stabilize #![feature(label_break_value)]
# Stabilization proposal

The feature was implemented in https://github.com/rust-lang/rust/pull/50045 by est31 and has been in nightly since 2018-05-16 (over 4 years now).
There are [no open issues][issue-label] other than the tracking issue. There is a strong consensus that `break` is the right keyword and we should not use `return`.

There have been several concerns raised about this feature on the tracking issue (other than the one about tests, which has been fixed, and an interaction with try blocks, which has been fixed).
1. nrc's original comment about cost-benefit analysis: https://github.com/rust-lang/rust/issues/48594#issuecomment-422235234
2. joshtriplett's comments about seeing use cases: https://github.com/rust-lang/rust/issues/48594#issuecomment-422281176
3. withoutboats's comments that Rust does not need more control flow constructs: https://github.com/rust-lang/rust/issues/48594#issuecomment-450050630

Many different examples of code that's simpler using this feature have been provided:
- A lexer by rpjohnst which must repeat code without label-break-value: https://github.com/rust-lang/rust/issues/48594#issuecomment-422502014
- A snippet by SergioBenitez which avoids using a new function and adding several new return points to a function: https://github.com/rust-lang/rust/issues/48594#issuecomment-427628251. This particular case would also work if `try` blocks were stabilized (at the cost of making the code harder to optimize).
- Several examples by JohnBSmith: https://github.com/rust-lang/rust/issues/48594#issuecomment-434651395
- Several examples by Centril: https://github.com/rust-lang/rust/issues/48594#issuecomment-440154733
- An example by petrochenkov where this is used in the compiler itself to avoid duplicating error checking code: https://github.com/rust-lang/rust/issues/48594#issuecomment-443557569
- Amanieu recently provided another example related to complex conditions, where try blocks would not have helped: https://github.com/rust-lang/rust/issues/48594#issuecomment-1184213006

Additionally, petrochenkov notes that this is strictly more powerful than labelled loops due to macros which accidentally exit a loop instead of being consumed by the macro matchers: https://github.com/rust-lang/rust/issues/48594#issuecomment-450246249

nrc later resolved their concern, mostly because of the aforementioned macro problems.
joshtriplett suggested that macros could be able to generate IR directly
(https://github.com/rust-lang/rust/issues/48594#issuecomment-451685983) but there are no open RFCs,
and the design space seems rather speculative.

joshtriplett later resolved his concerns, due to a symmetry between this feature and existing labelled break: https://github.com/rust-lang/rust/issues/48594#issuecomment-632960804

withoutboats has regrettably left the language team.

joshtriplett later posted that the lang team would consider starting an FCP given a stabilization report: https://github.com/rust-lang/rust/issues/48594#issuecomment-1111269353

[issue-label]: https://github.com/rust-lang/rust/issues?q=is%3Aissue+is%3Aopen+label%3AF-label_break_value+

 ## Report

+ Feature gate:
    - d695a497bb/src/test/ui/feature-gates/feature-gate-label_break_value.rs
+ Diagnostics:
    - 6b2d3d5f3c/compiler/rustc_parse/src/parser/diagnostics.rs (L2629)
    - f65bf0b2bb/compiler/rustc_resolve/src/diagnostics.rs (L749)
    - f65bf0b2bb/compiler/rustc_resolve/src/diagnostics.rs (L1001)
    - 111df9e6ed/compiler/rustc_passes/src/loops.rs (L254)
    - d695a497bb/compiler/rustc_parse/src/parser/expr.rs (L2079)
    - d695a497bb/compiler/rustc_parse/src/parser/expr.rs (L1569)
+ Tests:
    - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_continue.rs
    - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_unlabeled_break.rs
    - https://github.com/rust-lang/rust/blob/master/src/test/ui/label/label_break_value_illegal_uses.rs
    - https://github.com/rust-lang/rust/blob/master/src/test/ui/lint/unused_labels.rs
    - https://github.com/rust-lang/rust/blob/master/src/test/ui/run-pass/for-loop-while/label_break_value.rs

 ## Interactions with other features

Labels follow the hygiene of local variables.

label-break-value is permitted within `try` blocks:
```rust
let _: Result<(), ()> = try {
    'foo: {
        Err(())?;
        break 'foo;
    }
};
```

label-break-value is disallowed within closures, generators, and async blocks:
```rust
'a: {
    || break 'a
    //~^ ERROR use of unreachable label `'a`
    //~| ERROR `break` inside of a closure
}
```

label-break-value is disallowed on [_BlockExpression_]; it can only occur as a [_LoopExpression_]:
```rust
fn labeled_match() {
    match false 'b: { //~ ERROR block label not supported here
        _ => {}
    }
}

macro_rules! m {
    ($b:block) => {
        'lab: $b; //~ ERROR cannot use a `block` macro fragment here
        unsafe $b; //~ ERROR cannot use a `block` macro fragment here
        |x: u8| -> () $b; //~ ERROR cannot use a `block` macro fragment here
    }
}

fn foo() {
    m!({});
}
```

[_BlockExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/block-expr.html
[_LoopExpression_]: https://doc.rust-lang.org/nightly/reference/expressions/loop-expr.html
2022-08-23 21:14:12 -05:00
..
rustc Don't rerun the build script for the compiler each time on linux 2022-07-10 23:57:25 -05:00
rustc_apfloat Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_arena Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_ast Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_ast_lowering Rollup merge of #100018 - nnethercote:clean-up-LitKind, r=petrochenkov 2022-08-17 12:32:49 +02:00
rustc_ast_passes Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_ast_pretty Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_attr Adjust cfgs 2022-08-12 16:28:15 -04:00
rustc_borrowck Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_builtin_macros Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_codegen_cranelift Rollup merge of #100208 - RalfJung:dyn-upcast-nop, r=petrochenkov 2022-08-19 12:26:41 +05:30
rustc_codegen_gcc Introduce an ArchiveBuilderBuilder 2022-07-28 09:08:47 +00:00
rustc_codegen_llvm Rollup merge of #100460 - cuviper:drop-llvm-12, r=nagisa 2022-08-16 06:05:57 +02:00
rustc_codegen_ssa Rollup merge of #100208 - RalfJung:dyn-upcast-nop, r=petrochenkov 2022-08-19 12:26:41 +05:30
rustc_const_eval Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_data_structures Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_driver Error on broken pipe but do not ICE 2022-08-02 01:08:50 +01:00
rustc_error_codes Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_error_messages Rollup merge of #100723 - 5225225:the-easy-ones, r=compiler-errors 2022-08-20 07:09:03 +02:00
rustc_errors Add Handler::struct_diagnostic() 2022-08-21 09:17:43 +02:00
rustc_expand Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_feature Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_fs_util Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_graphviz Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_hir Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_hir_pretty Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_incremental Remove trait_of_item query. 2022-08-01 21:39:26 +02:00
rustc_index Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_infer Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_interface Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_lexer Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_lint Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_lint_defs Rollup merge of #99935 - CAD97:unstable-syntax-lints, r=petrochenkov 2022-08-20 19:45:10 +02:00
rustc_llvm Auto merge of #100627 - krasimirgg:lto-llvm-16, r=cuviper 2022-08-21 07:19:49 +00:00
rustc_log Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_macros Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_metadata Auto merge of #100209 - cjgillot:source-file-index, r=estebank 2022-08-19 15:31:25 +00:00
rustc_middle Rollup merge of #100691 - compiler-errors:issue-100690, r=estebank 2022-08-20 19:32:11 +02:00
rustc_mir_build Rollup merge of #100081 - RalfJung:unused-unsafe-in-unsafe-fn, r=jackh726 2022-08-19 12:26:40 +05:30
rustc_mir_dataflow Remove redundant TransferWrapper struct 2022-08-01 17:08:19 +02:00
rustc_mir_transform Rollup merge of #100522 - cjgillot:inline-polymorphic-recursion, r=tmiasko 2022-08-19 12:26:43 +05:30
rustc_monomorphize Refuse to codegen an upstream static. 2022-08-10 18:30:12 +02:00
rustc_parse Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_parse_format Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_passes Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_plugin_impl remove currently unused deps 2022-06-13 22:20:51 +03:00
rustc_privacy Replace #[lint/warning/error] with #[diag] 2022-08-21 09:17:43 +02:00
rustc_query_impl Rollup merge of #100723 - 5225225:the-easy-ones, r=compiler-errors 2022-08-20 07:09:03 +02:00
rustc_query_system Auto merge of #100441 - nnethercote:shrink-ast-Attribute, r=petrochenkov 2022-08-16 07:54:22 +00:00
rustc_resolve Rollup merge of #100592 - cjgillot:debug-import-kind, r=TaKO8Ki 2022-08-19 12:26:44 +05:30
rustc_save_analysis Remove DefId from AssocItemContainer. 2022-08-01 21:38:45 +02:00
rustc_serialize Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_session Add Handler::struct_diagnostic() 2022-08-21 09:17:43 +02:00
rustc_smir Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_span Rollup merge of #100723 - 5225225:the-easy-ones, r=compiler-errors 2022-08-20 07:09:03 +02:00
rustc_symbol_mangling Auto merge of #95548 - rcvalle:rust-cfi-2, r=nagisa 2022-07-24 01:22:36 +00:00
rustc_target Rollup merge of #100636 - cutsoy:revert-77716, r=davidtwco 2022-08-20 19:45:13 +02:00
rustc_trait_selection Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00
rustc_traits Add diagnostic translation lints to crates that don't emit them 2022-08-18 19:29:02 +01:00
rustc_transmute safe transmute: fix broken intradoc link 2022-08-02 14:44:23 +00:00
rustc_ty_utils Add bound_impl_subject and bound_return_ty 2022-08-03 01:02:46 -04:00
rustc_type_ir ADD - diagnostic lints to type_ir 2022-08-18 13:33:03 -04:00
rustc_typeck Stabilize #![feature(label_break_value)] 2022-08-23 21:14:12 -05:00