]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #41316 - suchithjn225:issue-41272, r=eddyb
authorbors <bors@rust-lang.org>
Sat, 15 Apr 2017 12:13:27 +0000 (12:13 +0000)
committerbors <bors@rust-lang.org>
Sat, 15 Apr 2017 12:13:27 +0000 (12:13 +0000)
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

1  2 
src/librustc/hir/lowering.rs

index c86aaa7bf672745a9fd74bababce0979e59bcd20,0fd906ae5e4a349b8d378fd6e888f7e7afa6c451..b7aafa0a9ab0b06b1c082ee795ab51c5a0791bf5
@@@ -646,13 -646,6 +646,13 @@@ impl<'a> LoweringContext<'a> 
          }
      }
  
 +    fn lower_global_asm(&mut self, ga: &GlobalAsm) -> P<hir::GlobalAsm> {
 +        P(hir::GlobalAsm {
 +            asm: ga.asm,
 +            ctxt: ga.ctxt,
 +        })
 +    }
 +
      fn lower_variant(&mut self, v: &Variant) -> hir::Variant {
          Spanned {
              node: hir::Variant_ {
              }
              ItemKind::Mod(ref m) => hir::ItemMod(self.lower_mod(m)),
              ItemKind::ForeignMod(ref nm) => hir::ItemForeignMod(self.lower_foreign_mod(nm)),
 +            ItemKind::GlobalAsm(ref ga) => hir::ItemGlobalAsm(self.lower_global_asm(ga)),
              ItemKind::Ty(ref t, ref generics) => {
                  hir::ItemTy(self.lower_ty(t), self.lower_generics(generics))
              }
                  //
                  //   match <sub_expr> {
                  //     <pat> => <body>,
-                 //     [_ if <else_opt_if_cond> => <else_opt_if_body>,]
                  //     _ => [<else_opt> | ()]
                  //   }
  
                      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();