Skip to content

Commit c67cf5f

Browse files
committed
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
2 parents 5f13a3b + 5649b37 commit c67cf5f

File tree

2 files changed

+38
-87
lines changed

2 files changed

+38
-87
lines changed

src/librustc/hir/lowering.rs

+9-87
Original file line numberDiff line numberDiff line change
@@ -2041,7 +2041,6 @@ impl<'a> LoweringContext<'a> {
20412041
//
20422042
// match <sub_expr> {
20432043
// <pat> => <body>,
2044-
// [_ if <else_opt_if_cond> => <else_opt_if_body>,]
20452044
// _ => [<else_opt> | ()]
20462045
// }
20472046

@@ -2055,93 +2054,16 @@ impl<'a> LoweringContext<'a> {
20552054
arms.push(self.arm(hir_vec![pat], body_expr));
20562055
}
20572056

2058-
// `[_ if <else_opt_if_cond> => <else_opt_if_body>,]`
2059-
// `_ => [<else_opt> | ()]`
2057+
// _ => [<else_opt>|()]
20602058
{
2061-
let mut current: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
2062-
let mut else_exprs: Vec<Option<&Expr>> = vec![current];
2063-
2064-
// First, we traverse the AST and recursively collect all
2065-
// `else` branches into else_exprs, e.g.:
2066-
//
2067-
// if let Some(_) = x {
2068-
// ...
2069-
// } else if ... { // Expr1
2070-
// ...
2071-
// } else if ... { // Expr2
2072-
// ...
2073-
// } else { // Expr3
2074-
// ...
2075-
// }
2076-
//
2077-
// ... results in else_exprs = [Some(&Expr1),
2078-
// Some(&Expr2),
2079-
// Some(&Expr3)]
2080-
//
2081-
// Because there also the case there is no `else`, these
2082-
// entries can also be `None`, as in:
2083-
//
2084-
// if let Some(_) = x {
2085-
// ...
2086-
// } else if ... { // Expr1
2087-
// ...
2088-
// } else if ... { // Expr2
2089-
// ...
2090-
// }
2091-
//
2092-
// ... results in else_exprs = [Some(&Expr1),
2093-
// Some(&Expr2),
2094-
// None]
2095-
//
2096-
// The last entry in this list is always translated into
2097-
// the final "unguard" wildcard arm of the `match`. In the
2098-
// case of a `None`, it becomes `_ => ()`.
2099-
loop {
2100-
if let Some(e) = current {
2101-
// There is an else branch at this level
2102-
if let ExprKind::If(_, _, ref else_opt) = e.node {
2103-
// The else branch is again an if-expr
2104-
current = else_opt.as_ref().map(|p| &**p);
2105-
else_exprs.push(current);
2106-
} else {
2107-
// The last item in the list is not an if-expr,
2108-
// stop here
2109-
break
2110-
}
2111-
} else {
2112-
// We have no more else branch
2113-
break
2114-
}
2115-
}
2116-
2117-
// Now translate the list of nested else-branches into the
2118-
// arms of the match statement.
2119-
for else_expr in else_exprs {
2120-
if let Some(else_expr) = else_expr {
2121-
let (guard, body) = if let ExprKind::If(ref cond,
2122-
ref then,
2123-
_) = else_expr.node {
2124-
let then = self.lower_block(then, false);
2125-
(Some(cond),
2126-
self.expr_block(then, ThinVec::new()))
2127-
} else {
2128-
(None,
2129-
self.lower_expr(else_expr))
2130-
};
2131-
2132-
arms.push(hir::Arm {
2133-
attrs: hir_vec![],
2134-
pats: hir_vec![self.pat_wild(e.span)],
2135-
guard: guard.map(|e| P(self.lower_expr(e))),
2136-
body: P(body),
2137-
});
2138-
} else {
2139-
// There was no else-branch, push a noop
2140-
let pat_under = self.pat_wild(e.span);
2141-
let unit = self.expr_tuple(e.span, hir_vec![]);
2142-
arms.push(self.arm(hir_vec![pat_under], unit));
2143-
}
2144-
}
2059+
let wildcard_arm: Option<&Expr> = else_opt.as_ref().map(|p| &**p);
2060+
let wildcard_pattern = self.pat_wild(e.span);
2061+
let body = if let Some(else_expr) = wildcard_arm {
2062+
P(self.lower_expr(else_expr))
2063+
} else {
2064+
self.expr_tuple(e.span, hir_vec![])
2065+
};
2066+
arms.push(self.arm(hir_vec![wildcard_pattern], body));
21452067
}
21462068

21472069
let contains_else_clause = else_opt.is_some();

src/test/run-pass/issue-41272.rs

+29
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo;
12+
13+
impl Foo {
14+
fn bar(&mut self) -> bool { true }
15+
}
16+
17+
fn error(foo: &mut Foo) {
18+
if let Some(_) = Some(true) {
19+
} else if foo.bar() {}
20+
}
21+
22+
fn ok(foo: &mut Foo) {
23+
if let Some(_) = Some(true) {
24+
} else {
25+
if foo.bar() {}
26+
}
27+
}
28+
29+
fn main() {}

0 commit comments

Comments
 (0)