summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2014-01-15 14:39:08 -0500
committerNiko Matsakis <niko@alum.mit.edu>2014-01-15 18:34:38 -0500
commit419ac4a1b899ba88fb360b4c71c08f3610564cd4 (patch)
treea67114bd33e84818930d054f29ac81b726a88198 /src/libsyntax
parent149fc76698318f8f7cdfaa37a818e347721764e7 (diff)
downloadrust-419ac4a1b899ba88fb360b4c71c08f3610564cd4.tar.gz
rust-419ac4a1b899ba88fb360b4c71c08f3610564cd4.zip
Issue #3511 - Rationalize temporary lifetimes.
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.
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/ast_util.rs6
-rw-r--r--src/libsyntax/ext/format.rs15
-rw-r--r--src/libsyntax/opt_vec.rs47
-rw-r--r--src/libsyntax/visit.rs11
4 files changed, 66 insertions, 13 deletions
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 3e0caab65c2..8fb18eecd6e 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/format.rs b/src/libsyntax/ext/format.rs
index a4b8dd78403..3ad5857395d 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)
 }