Skip to content

Commit

Permalink
Rollup merge of rust-lang#84486 - Smittyvb:else-if-let-hir-pretty-pri…
Browse files Browse the repository at this point in the history
…nt, r=petrochenkov

Handle pretty printing of `else if let` clauses without ICEing

When pretty printing the HIR of `if ... {} else if let ... {}` clauses, this displays it the `else if let` part as `match` it gets desugared to, the same way normal `if let` statements are currently displayed, instead of ICEing.

```rust
pub fn main() {
    if true {
        // 1
    } else if let a = 1 {
        // 2
    } else {
        // 3
    }
}
```

now gets desugared (via `rustc -Zunpretty=hir,typed src/x.rs`) to:

```rust
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
pub fn main() ({
                   (if (true as bool)
                       ({
                            // 1
                        } as
                           ()) else {match (1 as i32) {
                                         a => {
                                             // 2
                                         }
                                         _ => {
                                             // 3
                                         }
                                     }} as ())
                    } as ())
```

For comparison, this code gets HIR prettyprinted the same way before and after this change:

```rust
pub fn main() {
    if let a = 1 {
        // 2
    } else {
        // 3
    }
}
```
turns into
```rust
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
pub fn main() ({
                   (match (1 as i32) {
                        a => {
                            // 2
                        }
                        _ => {
                            // 3
                        }
                    } as ())
               } as ())
```

This closes rust-lang#82329. It closes rust-lang#84434 as well, due to having the same root cause.
  • Loading branch information
Dylan-DPC committed Apr 25, 2021
2 parents cb196e6 + fc97ce6 commit ac0a77b
Show file tree
Hide file tree
Showing 4 changed files with 69 additions and 2 deletions.
24 changes: 22 additions & 2 deletions compiler/rustc_hir_pretty/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1095,8 +1095,8 @@ impl<'a> State<'a> {

fn print_else(&mut self, els: Option<&hir::Expr<'_>>) {
match els {
Some(_else) => {
match _else.kind {
Some(else_) => {
match else_.kind {
// "another else-if"
hir::ExprKind::If(ref i, ref then, ref e) => {
self.cbox(INDENT_UNIT - 1);
Expand All @@ -1114,6 +1114,26 @@ impl<'a> State<'a> {
self.s.word(" else ");
self.print_block(&b)
}
hir::ExprKind::Match(ref expr, arms, _) => {
// else if let desugared to match
assert!(arms.len() == 2, "if let desugars to match with two arms");

self.s.word(" else ");
self.s.word("{");

self.cbox(INDENT_UNIT);
self.ibox(INDENT_UNIT);
self.word_nbsp("match");
self.print_expr_as_cond(&expr);
self.s.space();
self.bopen();
for arm in arms {
self.print_arm(arm);
}
self.bclose(expr.span);

self.s.word("}");
}
// BLEAH, constraints would be great here
_ => {
panic!("print_if saw if with weird alternative");
Expand Down
9 changes: 9 additions & 0 deletions src/test/ui/match/issue-82392.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// https://github.com/rust-lang/rust/issues/82329
// compile-flags: -Zunpretty=hir,typed
// check-pass

pub fn main() {
if true {
} else if let Some(a) = Some(3) {
}
}
20 changes: 20 additions & 0 deletions src/test/ui/match/issue-82392.stdout
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#[prelude_import]
use ::std::prelude::rust_2015::*;
#[macro_use]
extern crate std;
// https://github.com/rust-lang/rust/issues/82329
// compile-flags: -Zunpretty=hir,typed
// check-pass

pub fn main() ({
(if (true as bool)
({ } as
()) else {match ((Some as
fn(i32) -> Option<i32> {Option::<i32>::Some})((3
as
i32))
as Option<i32>) {
Some(a) => { }
_ => { }
}} as ())
} as ())
18 changes: 18 additions & 0 deletions src/test/ui/match/issue-84434.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// https://github.com/rust-lang/rust/issues/84434
// check-pass

use std::path::Path;
struct A {
pub func: fn(check: bool, a: &Path, b: Option<&Path>),
}
const MY_A: A = A {
func: |check, a, b| {
if check {
let _ = ();
} else if let Some(parent) = b.and_then(|p| p.parent()) {
let _ = ();
}
},
};

fn main() {}

0 comments on commit ac0a77b

Please sign in to comment.