]> git.lizzy.rs Git - rust.git/commitdiff
Change the for-loop desugar so the `break` does not affect type inference. Fixes...
authorJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Tue, 13 Jun 2017 16:36:01 +0000 (18:36 +0200)
committerJohn Kåre Alsaker <john.kare.alsaker@gmail.com>
Tue, 13 Jun 2017 16:36:01 +0000 (18:36 +0200)
src/libcore/iter/mod.rs
src/librustc/hir/lowering.rs

index ee81151348772e2456e597b7bacb918904d28648..c91fd16391aafc0b11e6fa783fe6fd595dcbc203 100644 (file)
 //! {
 //!     let result = match IntoIterator::into_iter(values) {
 //!         mut iter => loop {
-//!             let x = match iter.next() {
-//!                 Some(val) => val,
+//!             let next;
+//!             match iter.next() {
+//!                 Some(val) => next = val,
 //!                 None => break,
 //!             };
+//!             let x = next;
 //!             let () = { println!("{}", x); };
 //!         },
 //!     };
index a6ab67e04693d4f9805546a5c9abda0084a795ef..1283d136d32877a4c3af437568c0f9aefda8ca5d 100644 (file)
@@ -2170,11 +2170,13 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 //     let result = match ::std::iter::IntoIterator::into_iter(<head>) {
                 //       mut iter => {
                 //         [opt_ident]: loop {
-                //           let <pat> = match ::std::iter::Iterator::next(&mut iter) {
-                //             ::std::option::Option::Some(val) => val,
+                //           let next;
+                //           match ::std::iter::Iterator::next(&mut iter) {
+                //             ::std::option::Option::Some(val) => next = val,
                 //             ::std::option::Option::None => break
                 //           };
-                //           SemiExpr(<body>);
+                //           let <pat> = next;
+                //           StmtExpr(<body>);
                 //         }
                 //       }
                 //     };
@@ -2186,13 +2188,18 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
 
                 let iter = self.str_to_ident("iter");
 
-                // `::std::option::Option::Some(val) => val`
+                let next_ident = self.str_to_ident("next");
+                let next_pat = self.pat_ident(e.span, next_ident);
+                
+                // `::std::option::Option::Some(val) => next = val`
                 let pat_arm = {
                     let val_ident = self.str_to_ident("val");
                     let val_pat = self.pat_ident(e.span, val_ident);
                     let val_expr = P(self.expr_ident(e.span, val_ident, val_pat.id));
+                    let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
+                    let assign = P(self.expr(e.span, hir::ExprAssign(next_expr, val_expr), ThinVec::new()));
                     let some_pat = self.pat_some(e.span, val_pat);
-                    self.arm(hir_vec![some_pat], val_expr)
+                    self.arm(hir_vec![some_pat], assign)
                 };
 
                 // `::std::option::Option::None => break`
@@ -2222,10 +2229,20 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                                                hir::MatchSource::ForLoopDesugar),
                                 ThinVec::new()))
                 };
+                let match_stmt = respan(e.span, hir::StmtExpr(match_expr, self.next_id()));
+
+                let next_expr = P(self.expr_ident(e.span, next_ident, next_pat.id));
+                
+                // `let next`
+                let next_let = self.stmt_let_pat(e.span,
+                    None,
+                    next_pat,
+                    hir::LocalSource::ForLoopDesugar);
 
+                // `let <pat> = next`
                 let pat = self.lower_pat(pat);
                 let pat_let = self.stmt_let_pat(e.span,
-                    match_expr,
+                    Some(next_expr),
                     pat,
                     hir::LocalSource::ForLoopDesugar);
 
@@ -2234,7 +2251,7 @@ fn lower_expr(&mut self, e: &Expr) -> hir::Expr {
                 let body_expr = P(self.expr_block(body_block, ThinVec::new()));
                 let body_stmt = respan(e.span, hir::StmtExpr(body_expr, self.next_id()));
 
-                let loop_block = P(self.block_all(e.span, hir_vec![pat_let, body_stmt], None));
+                let loop_block = P(self.block_all(e.span, hir_vec![next_let, match_stmt, pat_let, body_stmt], None));
 
                 // `[opt_ident]: loop { ... }`
                 let loop_expr = hir::ExprLoop(loop_block, self.lower_opt_sp_ident(opt_ident),
@@ -2601,14 +2618,14 @@ fn expr(&mut self, span: Span, node: hir::Expr_, attrs: ThinVec<Attribute>) -> h
 
     fn stmt_let_pat(&mut self,
                     sp: Span,
-                    ex: P<hir::Expr>,
+                    ex: Option<P<hir::Expr>>,
                     pat: P<hir::Pat>,
                     source: hir::LocalSource)
                     -> hir::Stmt {
         let local = P(hir::Local {
             pat: pat,
             ty: None,
-            init: Some(ex),
+            init: ex,
             id: self.next_id(),
             span: sp,
             attrs: ThinVec::new(),
@@ -2626,7 +2643,7 @@ fn stmt_let(&mut self, sp: Span, mutbl: bool, ident: Name, ex: P<hir::Expr>)
             self.pat_ident(sp, ident)
         };
         let pat_id = pat.id;
-        (self.stmt_let_pat(sp, ex, pat, hir::LocalSource::Normal), pat_id)
+        (self.stmt_let_pat(sp, Some(ex), pat, hir::LocalSource::Normal), pat_id)
     }
 
     fn block_expr(&mut self, expr: P<hir::Expr>) -> hir::Block {