Auto merge of #125051 - dtolnay:printletelse, r=compiler-errors

Pretty-print let-else with added parenthesization when needed

Rustc used to produce invalid syntax for the following code, which is problematic because it means we cannot apply rustfmt to the output of `-Zunpretty=expanded`.

```rust
macro_rules! expr {
    ($e:expr) => { $e };
}

fn main() {
    let _ = expr!(loop {}) else { return; };
}
```

```console
$ rustc repro.rs -Zunpretty=expanded | rustfmt
error: `loop...else` loops are not supported
 --> <stdin>:9:29
  |
9 | fn main() { let _ = loop {} else { return; }; }
  |                     ----    ^^^^^^^^^^^^^^^^
  |                     |
  |                     `else` is attached to this loop
  |
  = note: consider moving this `else` clause to a separate `if` statement and use a `bool` variable to control if it should run
```
This commit is contained in:
bors 2024-05-12 22:06:34 +00:00
commit ecbe3fd550
6 changed files with 46 additions and 1 deletions

View File

@ -1238,7 +1238,11 @@ impl<'a> State<'a> {
if let Some((init, els)) = loc.kind.init_else_opt() {
self.nbsp();
self.word_space("=");
self.print_expr(init, FixupContext::default());
self.print_expr_cond_paren(
init,
els.is_some() && classify::expr_trailing_brace(init).is_some(),
FixupContext::default(),
);
if let Some(els) = els {
self.cbox(INDENT_UNIT);
self.ibox(INDENT_UNIT);

View File

@ -675,6 +675,11 @@ fn test_stmt() {
"let (a, b): (u32, u32) = (1, 2);",
"let (a, b): (u32, u32) = (1, 2)"
);
c2!(stmt,
[ let _ = f() else { return; } ],
"let _ = f() else { return; };",
"let _ = f() else { return; }",
);
macro_rules! c2_let_expr_minus_one {
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
c2!(stmt, [ let _ = $expr - 1 ], $stmt_expected, $tokens_expected);
@ -685,6 +690,16 @@ fn test_stmt() {
"let _ = match void {} - 1;",
"let _ = match void {} - 1",
);
macro_rules! c2_let_expr_else_return {
([ $expr:expr ], $stmt_expected:expr, $tokens_expected:expr $(,)?) => {
c2!(stmt, [ let _ = $expr else { return; } ], $stmt_expected, $tokens_expected);
};
}
c2_let_expr_else_return!(
[ f() ],
"let _ = f() else { return; };",
"let _ = f() else { return; }",
);
// StmtKind::Item
c1!(stmt, [ struct S; ], "struct S;");

View File

@ -0,0 +1,11 @@
//@ compile-flags: -Zunpretty=expanded
//@ check-pass
macro_rules! expr {
($e:expr) => { $e };
}
fn main() {
let _ = expr!(1 + 1) else { return; };
let _ = expr!(loop {}) else { return; };
}

View File

@ -0,0 +1,15 @@
#![feature(prelude_import)]
#![no_std]
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
//@ compile-flags: -Zunpretty=expanded
//@ check-pass
macro_rules! expr { ($e:expr) => { $e }; }
fn main() {
let _ = 1 + 1 else { return; };
let _ = (loop {}) else { return; };
}