about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2014-01-17 07:56:45 -0800
committerbors <bors@rust-lang.org>2014-01-17 07:56:45 -0800
commit4098327b1fe1112ddf661b587be9eeec1d80adde (patch)
tree3d1a8d2613c1101d46657fd5de25d32403e9626b /src/libsyntax
parent1e1871f35eb83ae6a63952a145e5132deffded2c (diff)
parentb520c2f28002db0e4120797d823380914871bac4 (diff)
downloadrust-4098327b1fe1112ddf661b587be9eeec1d80adde.tar.gz
rust-4098327b1fe1112ddf661b587be9eeec1d80adde.zip
auto merge of #11585 : nikomatsakis/rust/issue-3511-rvalue-lifetimes, r=pcwalton
Major changes:

- Define temporary scopes in a syntax-based way that basically defaults
  to the innermost statement or conditional block, except for in
  a `let` initializer, where we default to the innermost block. Rules
  are documented in the code, but not in the manual (yet).
  See new test run-pass/cleanup-value-scopes.rs for examples.
- Refactors Datum to better define cleanup roles.
- Refactor cleanup scopes to not be tied to basic blocks, permitting
  us to have a very large number of scopes (one per AST node).
- Introduce nascent documentation in trans/doc.rs covering datums and
  cleanup in a more comprehensive way.

r? @pcwalton
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast_util.rs6
-rw-r--r--src/libsyntax/ext/expand.rs30
-rw-r--r--src/libsyntax/ext/format.rs15
-rw-r--r--src/libsyntax/opt_vec.rs47
-rw-r--r--src/libsyntax/visit.rs11
5 files changed, 78 insertions, 31 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 89aa03a46ba..598e30957e4 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -567,11 +567,7 @@ pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
         visited_outermost: false,
     };
 
-    match *item {
-        IIItem(i) => id_visitor.visit_item(i, ()),
-        IIForeign(i) => id_visitor.visit_foreign_item(i, ()),
-        IIMethod(_, _, m) => visit::walk_method_helper(&mut id_visitor, m, ()),
-    }
+    visit::walk_inlined_item(&mut id_visitor, item, ());
 }
 
 struct IdRangeComputingVisitor {
diff --git a/src/libsyntax/ext/expand.rs b/src/libsyntax/ext/expand.rs
index b1b38d6dc90..7d46f6e4594 100644
--- a/src/libsyntax/ext/expand.rs
+++ b/src/libsyntax/ext/expand.rs
@@ -138,15 +138,16 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
 
             // to:
             //
-            // {
-            //   let _i = &mut <src_expr>;
-            //   ['<ident>:] loop {
-            //       match i.next() {
+            //   match &mut <src_expr> {
+            //     i => {
+            //       ['<ident>:] loop {
+            //         match i.next() {
             //           None => break,
             //           Some(<src_pat>) => <src_loop_block>
+            //         }
             //       }
+            //     }
             //   }
-            // }
 
             let local_ident = token::gensym_ident("i");
             let next_ident = fld.cx.ident_of("next");
@@ -155,10 +156,6 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
             let local_path = fld.cx.path_ident(span, local_ident);
             let some_path = fld.cx.path_ident(span, fld.cx.ident_of("Some"));
 
-            // `let i = &mut <src_expr>`
-            let iter_decl_stmt = fld.cx.stmt_let(span, false, local_ident,
-                                                 fld.cx.expr_mut_addr_of(span, src_expr));
-
             // `None => break ['<ident>];`
             let none_arm = {
                 // FIXME #6993: this map goes away:
@@ -186,16 +183,13 @@ pub fn expand_expr(e: @ast::Expr, fld: &mut MacroExpander) -> @ast::Expr {
                                         ast::ExprLoop(fld.cx.block_expr(match_expr),
                                                       opt_ident));
 
-            // `{ let ... ;  loop { ... } }`
-            let block = fld.cx.block(span,
-                                     ~[iter_decl_stmt],
-                                     Some(loop_expr));
+            // `i => loop { ... }`
 
-            @ast::Expr {
-                id: ast::DUMMY_NODE_ID,
-                node: ast::ExprBlock(block),
-                span: span,
-            }
+            // `match &mut <src_expr> { i => loop { ... } }`
+            let discrim = fld.cx.expr_mut_addr_of(span, src_expr);
+            let i_pattern = fld.cx.pat_ident(span, local_ident);
+            let arm = fld.cx.arm(span, ~[i_pattern], loop_expr);
+            fld.cx.expr_match(span, discrim, ~[arm])
         }
 
         _ => noop_fold_expr(e, fld)
diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs
index 9ae13ddeb02..33832a8c62d 100644
--- a/src/libsyntax/ext/format.rs
+++ b/src/libsyntax/ext/format.rs
@@ -634,17 +634,24 @@ impl<'a> Context<'a> {
                                      self.ecx.expr_ident(e.span, lname)));
         }
 
+        // Now create a vector containing all the arguments
+        let slicename = self.ecx.ident_of("__args_vec");
+        {
+            let args = names.move_iter().map(|a| a.unwrap());
+            let mut args = locals.move_iter().chain(args);
+            let args = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
+            lets.push(self.ecx.stmt_let(self.fmtsp, false, slicename, args));
+        }
+
         // Now create the fmt::Arguments struct with all our locals we created.
-        let args = names.move_iter().map(|a| a.unwrap());
-        let mut args = locals.move_iter().chain(args);
         let fmt = self.ecx.expr_ident(self.fmtsp, static_name);
-        let args = self.ecx.expr_vec_slice(self.fmtsp, args.collect());
+        let args_slice = self.ecx.expr_ident(self.fmtsp, slicename);
         let result = self.ecx.expr_call_global(self.fmtsp, ~[
                 self.ecx.ident_of("std"),
                 self.ecx.ident_of("fmt"),
                 self.ecx.ident_of("Arguments"),
                 self.ecx.ident_of("new"),
-            ], ~[fmt, args]);
+            ], ~[fmt, args_slice]);
 
         // We did all the work of making sure that the arguments
         // structure is safe, so we can safely have an unsafe block.
diff --git a/src/libsyntax/opt_vec.rs b/src/libsyntax/opt_vec.rs
index 247962e0b94..326f712d5b2 100644
--- a/src/libsyntax/opt_vec.rs
+++ b/src/libsyntax/opt_vec.rs
@@ -42,12 +42,31 @@ impl<T> OptVec<T> {
                 v.push(t);
                 return;
             }
-            Empty => {}
+            Empty => {
+                *self = Vec(~[t]);
+            }
         }
+    }
+
+    pub fn pop(&mut self) -> T {
+        match *self {
+            Vec(ref mut v) => v.pop(),
+            Empty => fail!("pop from empty opt_vec")
+        }
+    }
 
-        // FIXME(#5074): flow insensitive means we can't move
-        // assignment inside `match`
-        *self = Vec(~[t]);
+    pub fn last<'a>(&'a self) -> &'a T {
+        match *self {
+            Vec(ref v) => v.last(),
+            Empty => fail!("last on empty opt_vec")
+        }
+    }
+
+    pub fn mut_last<'a>(&'a mut self) -> &'a mut T {
+        match *self {
+            Vec(ref mut v) => v.mut_last(),
+            Empty => fail!("mut_last on empty opt_vec")
+        }
     }
 
     pub fn map<U>(&self, op: |&T| -> U) -> OptVec<U> {
@@ -82,6 +101,16 @@ impl<T> OptVec<T> {
         }
     }
 
+    pub fn swap_remove(&mut self, index: uint) {
+        match *self {
+            Empty => { fail!("Index out of bounds"); }
+            Vec(ref mut v) => {
+                assert!(index < v.len());
+                v.swap_remove(index);
+            }
+        }
+    }
+
     #[inline]
     pub fn iter<'r>(&'r self) -> OptVecIterator<'r, T> {
         match *self {
@@ -166,6 +195,16 @@ impl<'a, T> Iterator<&'a T> for OptVecIterator<'a, T> {
     }
 }
 
+impl<'a, T> DoubleEndedIterator<&'a T> for OptVecIterator<'a, T> {
+    #[inline]
+    fn next_back(&mut self) -> Option<&'a T> {
+        match self.iter {
+            Some(ref mut x) => x.next_back(),
+            None => None
+        }
+    }
+}
+
 impl<A> FromIterator<A> for OptVec<A> {
     fn from_iterator<T: Iterator<A>>(iterator: &mut T) -> OptVec<A> {
         let mut r = Empty;
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index d79522b7103..484f8dce1f7 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -121,6 +121,17 @@ pub trait Visitor<E: Clone> {
     }
 }
 
+pub fn walk_inlined_item<E: Clone, V: Visitor<E>>(visitor: &mut V,
+                                                  item: &ast::InlinedItem,
+                                                  env: E) {
+    match *item {
+        IIItem(i) => visitor.visit_item(i, env),
+        IIForeign(i) => visitor.visit_foreign_item(i, env),
+        IIMethod(_, _, m) => walk_method_helper(visitor, m, env),
+    }
+}
+
+
 pub fn walk_crate<E: Clone, V: Visitor<E>>(visitor: &mut V, crate: &Crate, env: E) {
     visitor.visit_mod(&crate.module, crate.span, CRATE_NODE_ID, env)
 }