diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-07-02 17:47:45 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-07-02 17:47:45 +0200 |
| commit | f8f67b296915e70a67fbf4595b1f54d9d773be57 (patch) | |
| tree | 0188cd7a6c3431559cc52d81c8a3bf37e743f2a8 /compiler/rustc_ast_pretty | |
| parent | 7d97c59438e933e86f557ed999da3b8dfc6855a7 (diff) | |
| parent | 06982239a6210cfc7b0b370634c9a9160c9b9dc4 (diff) | |
| download | rust-f8f67b296915e70a67fbf4595b1f54d9d773be57.tar.gz rust-f8f67b296915e70a67fbf4595b1f54d9d773be57.zip | |
Rollup merge of #126883 - dtolnay:breakvalue, r=fmease
Parenthesize break values containing leading label
The AST pretty printer previously produced invalid syntax in the case of `break` expressions with a value that begins with a loop or block label.
```rust
macro_rules! expr {
($e:expr) => {
$e
};
}
fn main() {
loop {
break expr!('a: loop { break 'a 1; } + 1);
};
}
```
`rustc -Zunpretty=expanded main.rs `:
```console
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
macro_rules! expr { ($e:expr) => { $e }; }
fn main() { loop { break 'a: loop { break 'a 1; } + 1; }; }
```
The expanded code is not valid Rust syntax. Printing invalid syntax is bad because it blocks `cargo expand` from being able to format the output as Rust syntax using rustfmt.
```console
error: parentheses are required around this expression to avoid confusion with a labeled break expression
--> <anon>:9:26
|
9 | fn main() { loop { break 'a: loop { break 'a 1; } + 1; }; }
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
help: wrap the expression in parentheses
|
9 | fn main() { loop { break ('a: loop { break 'a 1; }) + 1; }; }
| + +
```
This PR updates the AST pretty-printer to insert parentheses around the value of a `break` expression as required to avoid this edge case.
Diffstat (limited to 'compiler/rustc_ast_pretty')
| -rw-r--r-- | compiler/rustc_ast_pretty/src/pprust/state/expr.rs | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index 3d1f43a3766..5b13858f839 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -5,6 +5,7 @@ use ast::{ForLoopKind, MatchKind}; use itertools::{Itertools, Position}; use rustc_ast::ptr::P; use rustc_ast::token; +use rustc_ast::util::classify; use rustc_ast::util::literal::escape_byte_str_symbol; use rustc_ast::util::parser::{self, AssocOp, Fixity}; use rustc_ast::{self as ast, BlockCheckMode}; @@ -610,9 +611,12 @@ impl<'a> State<'a> { } if let Some(expr) = opt_expr { self.space(); - self.print_expr_maybe_paren( + self.print_expr_cond_paren( expr, - parser::PREC_JUMP, + // Parenthesize if required by precedence, or in the + // case of `break 'inner: loop { break 'inner 1 } + 1` + expr.precedence().order() < parser::PREC_JUMP + || (opt_label.is_none() && classify::leading_labeled_expr(expr)), fixup.subsequent_subexpression(), ); } |
