提交 c67cf5fd 编写于 作者: B bors

Auto merge of #41316 - suchithjn225:issue-41272, r=eddyb

Do not desugar if-let-else to match arm guards

Fixes #41272
Changed the desugaring code

**Before**
```rust
match <sub_expr> {
     <pat> => <body>,
     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
     _ => [<else_opt> | ()]
}
```

**After**
```rust
match <sub_expr> {
    <pat> => <body>,
     _       => [<else_opt> | ()]
}
```
With this fix, it doesn't cause E0301
......@@ -2041,7 +2041,6 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
//
// match <sub_expr> {
// <pat> => <body>,
// [_ if <else_opt_if_cond> => <else_opt_if_body>,]
// _ => [<else_opt> | ()]
// }
......@@ -2055,93 +2054,16 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
arms.push(self.arm(hir_vec![pat], body_expr));
}
// `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
// `_ => [<else_opt> | ()]`
// _ => [<else_opt>|()]
{
let mut current: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
let mut else_exprs: Vec<Option<&Expr>> = vec![current];
// First, we traverse the AST and recursively collect all
// `else` branches into else_exprs, e.g.:
//
// if let Some(_) = x {
// ...
// } else if ... { // Expr1
// ...
// } else if ... { // Expr2
// ...
// } else { // Expr3
// ...
// }
//
// ... results in else_exprs = [Some(&Expr1),
// Some(&Expr2),
// Some(&Expr3)]
//
// Because there also the case there is no `else`, these
// entries can also be `None`, as in:
//
// if let Some(_) = x {
// ...
// } else if ... { // Expr1
// ...
// } else if ... { // Expr2
// ...
// }
//
// ... results in else_exprs = [Some(&Expr1),
// Some(&Expr2),
// None]
//
// The last entry in this list is always translated into
// the final "unguard" wildcard arm of the `match`. In the
// case of a `None`, it becomes `_ => ()`.
loop {
if let Some(e) = current {
// There is an else branch at this level
if let ExprKind::If(_, _, ref else_opt) = e.node {
// The else branch is again an if-expr
current = else_opt.as_ref().map(|p| &**p);
else_exprs.push(current);
} else {
// The last item in the list is not an if-expr,
// stop here
break
}
} else {
// We have no more else branch
break
}
}
// Now translate the list of nested else-branches into the
// arms of the match statement.
for else_expr in else_exprs {
if let Some(else_expr) = else_expr {
let (guard, body) = if let ExprKind::If(ref cond,
ref then,
_) = else_expr.node {
let then = self.lower_block(then, false);
(Some(cond),
self.expr_block(then, ThinVec::new()))
} else {
(None,
self.lower_expr(else_expr))
};
arms.push(hir::Arm {
attrs: hir_vec![],
pats: hir_vec![self.pat_wild(e.span)],
guard: guard.map(|e| P(self.lower_expr(e))),
body: P(body),
});
} else {
// There was no else-branch, push a noop
let pat_under = self.pat_wild(e.span);
let unit = self.expr_tuple(e.span, hir_vec![]);
arms.push(self.arm(hir_vec![pat_under], unit));
}
}
let wildcard_arm: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
let wildcard_pattern = self.pat_wild(e.span);
let body = if let Some(else_expr) = wildcard_arm {
P(self.lower_expr(else_expr))
} else {
self.expr_tuple(e.span, hir_vec![])
};
arms.push(self.arm(hir_vec![wildcard_pattern], body));
}
let contains_else_clause = else_opt.is_some();
......
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo;
impl Foo {
fn bar(&mut self) -> bool { true }
}
fn error(foo: &mut Foo) {
if let Some(_) = Some(true) {
} else if foo.bar() {}
}
fn ok(foo: &mut Foo) {
if let Some(_) = Some(true) {
} else {
if foo.bar() {}
}
}
fn main() {}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册