diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs index c86aaa7bf67..b7aafa0a9ab 100644 --- a/src/librustc/hir/lowering.rs +++ b/src/librustc/hir/lowering.rs @@ -2041,7 +2041,6 @@ impl<'a> LoweringContext<'a> { // // match { // => , - // [_ if => ,] // _ => [ | ()] // } @@ -2055,93 +2054,16 @@ impl<'a> LoweringContext<'a> { arms.push(self.arm(hir_vec![pat], body_expr)); } - // `[_ if => ,]` - // `_ => [ | ()]` + // _ => [|()] { - let mut current: Option<&Expr> = else_opt.as_ref().map(|p| &**p); - let mut else_exprs: Vec> = 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(); diff --git a/src/test/run-pass/issue-41272.rs b/src/test/run-pass/issue-41272.rs new file mode 100644 index 00000000000..d6a0034690a --- /dev/null +++ b/src/test/run-pass/issue-41272.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , 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() {}