]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #11944 : nathanielherman/rust/vec_opt, r=alexcrichton
authorbors <bors@rust-lang.org>
Sat, 1 Feb 2014 15:21:23 +0000 (07:21 -0800)
committerbors <bors@rust-lang.org>
Sat, 1 Feb 2014 15:21:23 +0000 (07:21 -0800)
Closes #11733

1  2 
src/librustc/middle/trans/cleanup.rs
src/libstd/vec.rs

index c6d56db6877bb8042e83df7ec9c33192e351e01b,299cf8f6aeeb4400fd37949703373f204a7c7e21..acbbdf27d1c266cf37ba28ba1b3192021246e6ca
@@@ -214,7 -214,7 +214,7 @@@ impl<'a> CleanupMethods<'a> for Functio
          self.ccx.tcx.sess.bug("No loop scope found");
      }
  
 -    fn normal_exit_block(&self,
 +    fn normal_exit_block(&'a self,
                           cleanup_scope: ast::NodeId,
                           exit: uint) -> BasicBlockRef {
          /*!
          self.trans_cleanups_to_exit_scope(LoopExit(cleanup_scope, exit))
      }
  
 -    fn return_exit_block(&self) -> BasicBlockRef {
 +    fn return_exit_block(&'a self) -> BasicBlockRef {
          /*!
           * Returns a block to branch to which will perform all pending
           * cleanups and then return from this function
          scopes.get().iter().rev().any(|s| s.needs_invoke())
      }
  
 -    fn get_landing_pad(&self) -> BasicBlockRef {
 +    fn get_landing_pad(&'a self) -> BasicBlockRef {
          /*!
           * Returns a basic block to branch to in the event of a failure.
           * This block will run the failure cleanups and eventually
@@@ -481,7 -481,7 +481,7 @@@ impl<'a> CleanupHelperMethods<'a> for F
          f(scopes.get().last().unwrap())
      }
  
 -    fn trans_cleanups_to_exit_scope(&self,
 +    fn trans_cleanups_to_exit_scope(&'a self,
                                      label: EarlyExitLabel)
                                      -> BasicBlockRef {
          /*!
          prev_llbb
      }
  
 -    fn get_or_create_landing_pad(&self) -> BasicBlockRef {
 +    fn get_or_create_landing_pad(&'a self) -> BasicBlockRef {
          /*!
           * Creates a landing pad for the top scope, if one does not
           * exist.  The landing pad will perform all cleanups necessary
          // Check if a landing pad block exists; if not, create one.
          {
              let mut scopes = self.scopes.borrow_mut();
-             let last_scope = scopes.get().mut_last();
+             let last_scope = scopes.get().mut_last().unwrap();
              match last_scope.cached_landing_pad {
                  Some(llbb) => { return llbb; }
                  None => {
@@@ -903,10 -903,10 +903,10 @@@ pub trait CleanupMethods<'a> 
                                            custom_scope: CustomScopeIndex)
                                            -> &'a Block<'a>;
      fn top_loop_scope(&self) -> ast::NodeId;
 -    fn normal_exit_block(&self,
 +    fn normal_exit_block(&'a self,
                           cleanup_scope: ast::NodeId,
                           exit: uint) -> BasicBlockRef;
 -    fn return_exit_block(&self) -> BasicBlockRef;
 +    fn return_exit_block(&'a self) -> BasicBlockRef;
      fn schedule_drop_mem(&self,
                           cleanup_scope: ScopeId,
                           val: ValueRef,
                                      custom_scope: CustomScopeIndex,
                                      cleanup: ~Cleanup);
      fn needs_invoke(&self) -> bool;
 -    fn get_landing_pad(&self) -> BasicBlockRef;
 +    fn get_landing_pad(&'a self) -> BasicBlockRef;
  }
  
  trait CleanupHelperMethods<'a> {
      fn trans_scope_cleanups(&self,
                              bcx: &'a Block<'a>,
                              scope: &CleanupScope<'a>) -> &'a Block<'a>;
 -    fn trans_cleanups_to_exit_scope(&self,
 +    fn trans_cleanups_to_exit_scope(&'a self,
                                      label: EarlyExitLabel)
                                      -> BasicBlockRef;
 -    fn get_or_create_landing_pad(&self) -> BasicBlockRef;
 +    fn get_or_create_landing_pad(&'a self) -> BasicBlockRef;
      fn scopes_len(&self) -> uint;
      fn push_scope(&self, scope: CleanupScope<'a>);
      fn pop_scope(&self) -> CleanupScope<'a>;
diff --combined src/libstd/vec.rs
index 15cd5ce334323e1f15bd07a25cec1339d8f86252,0b9820e12ebc5400d4b42d4de237d6dfc65bf55d..7e4405fd545bde704d8563038aaecdf1c9e5bda7
@@@ -109,7 -109,7 +109,7 @@@ use cmp::{Eq, TotalOrd, Ordering, Less
  use cmp;
  use default::Default;
  use iter::*;
 -use num::{Integer, CheckedAdd, Saturating};
 +use num::{Integer, CheckedAdd, Saturating, checked_next_power_of_two};
  use option::{None, Option, Some};
  use ptr::to_unsafe_ptr;
  use ptr;
@@@ -117,7 -117,6 +117,7 @@@ use ptr::RawPtr
  use rt::global_heap::{malloc_raw, realloc_raw, exchange_free};
  use mem;
  use mem::size_of;
 +use kinds::marker;
  use uint;
  use unstable::finally::Finally;
  use unstable::intrinsics;
@@@ -804,7 -803,7 +804,7 @@@ pub trait CloneableVector<T> 
      /// Copy `self` into a new owned vector
      fn to_owned(&self) -> ~[T];
  
 -    /// Convert `self` into a owned vector, not making a copy if possible.
 +    /// Convert `self` into an owned vector, not making a copy if possible.
      fn into_owned(self) -> ~[T];
  }
  
@@@ -1000,14 -999,15 +1000,15 @@@ pub trait ImmutableVector<'a, T> 
       * Equivalent to:
       *
       * ```
+      *     if self.len() == 0 { return None }
       *     let head = &self[0];
       *     *self = self.slice_from(1);
-      *     head
+      *     Some(head)
       * ```
       *
-      * Fails if slice is empty.
+      * Returns `None` if vector is empty
       */
-     fn shift_ref(&mut self) -> &'a T;
+     fn shift_ref(&mut self) -> Option<&'a T>;
  
      /**
       * Returns a mutable reference to the last element in this slice
       * Equivalent to:
       *
       * ```
+      *     if self.len() == 0 { return None; }
       *     let tail = &self[self.len() - 1];
       *     *self = self.slice_to(self.len() - 1);
-      *     tail
+      *     Some(tail)
       * ```
       *
-      * Fails if slice is empty.
+      * Returns `None` if slice is empty.
       */
-     fn pop_ref(&mut self) -> &'a T;
+     fn pop_ref(&mut self) -> Option<&'a T>;
  }
  
  impl<'a,T> ImmutableVector<'a, T> for &'a [T] {
              let p = self.as_ptr();
              if mem::size_of::<T>() == 0 {
                  Items{ptr: p,
 -                            end: (p as uint + self.len()) as *T,
 -                            lifetime: None}
 +                      end: (p as uint + self.len()) as *T,
 +                      marker: marker::ContravariantLifetime::<'a>}
              } else {
                  Items{ptr: p,
 -                            end: p.offset(self.len() as int),
 -                            lifetime: None}
 +                      end: p.offset(self.len() as int),
 +                      marker: marker::ContravariantLifetime::<'a>}
              }
          }
      }
          self.iter().map(f).collect()
      }
  
-     fn shift_ref(&mut self) -> &'a T {
+     fn shift_ref(&mut self) -> Option<&'a T> {
+         if self.len() == 0 { return None; }
          unsafe {
              let s: &mut Slice<T> = cast::transmute(self);
-             &*raw::shift_ptr(s)
+             Some(&*raw::shift_ptr(s))
          }
      }
  
-     fn pop_ref(&mut self) -> &'a T {
+     fn pop_ref(&mut self) -> Option<&'a T> {
+         if self.len() == 0 { return None; }
          unsafe {
              let s: &mut Slice<T> = cast::transmute(self);
-             &*raw::pop_ptr(s)
+             Some(&*raw::pop_ptr(s))
          }
      }
  }
@@@ -1487,7 -1490,7 +1491,7 @@@ impl<T> OwnedVector<T> for ~[T] 
  
      #[inline]
      fn reserve_at_least(&mut self, n: uint) {
 -        self.reserve(uint::next_power_of_two_opt(n).unwrap_or(n));
 +        self.reserve(checked_next_power_of_two(n).unwrap_or(n));
      }
  
      #[inline]
@@@ -2028,7 -2031,7 +2032,7 @@@ pub trait MutableVector<'a, T> 
      fn mut_iter(self) -> MutItems<'a, T>;
  
      /// Returns a mutable pointer to the last item in the vector.
-     fn mut_last(self) -> &'a mut T;
+     fn mut_last(self) -> Option<&'a mut T>;
  
      /// Returns a reversed iterator that allows modifying each value
      fn mut_rev_iter(self) -> RevMutItems<'a, T>;
       * Equivalent to:
       *
       * ```
+      *     if self.len() == 0 { return None; }
       *     let head = &mut self[0];
       *     *self = self.mut_slice_from(1);
-      *     head
+      *     Some(head)
       * ```
       *
-      * Fails if slice is empty.
+      * Returns `None` if slice is empty
       */
-     fn mut_shift_ref(&mut self) -> &'a mut T;
+     fn mut_shift_ref(&mut self) -> Option<&'a mut T>;
  
      /**
       * Returns a mutable reference to the last element in this slice
       * Equivalent to:
       *
       * ```
+      *     if self.len() == 0 { return None; }
       *     let tail = &mut self[self.len() - 1];
       *     *self = self.mut_slice_to(self.len() - 1);
-      *     tail
+      *     Some(tail)
       * ```
       *
-      * Fails if slice is empty.
+      * Returns `None` if slice is empty.
       */
-     fn mut_pop_ref(&mut self) -> &'a mut T;
+     fn mut_pop_ref(&mut self) -> Option<&'a mut T>;
  
      /// Swaps two elements in a vector.
      ///
@@@ -2282,21 -2287,21 +2288,21 @@@ impl<'a,T> MutableVector<'a, T> for &'
              let p = self.as_mut_ptr();
              if mem::size_of::<T>() == 0 {
                  MutItems{ptr: p,
 -                               end: (p as uint + self.len()) as *mut T,
 -                               lifetime: None}
 +                         end: (p as uint + self.len()) as *mut T,
 +                         marker: marker::ContravariantLifetime::<'a>}
              } else {
                  MutItems{ptr: p,
 -                               end: p.offset(self.len() as int),
 -                               lifetime: None}
 +                         end: p.offset(self.len() as int),
 +                         marker: marker::ContravariantLifetime::<'a>}
              }
          }
      }
  
      #[inline]
-     fn mut_last(self) -> &'a mut T {
+     fn mut_last(self) -> Option<&'a mut T> {
          let len = self.len();
-         if len == 0 { fail!("mut_last: empty vector") }
-         &mut self[len - 1]
+         if len == 0 { return None; }
+         Some(&mut self[len - 1])
      }
  
      #[inline]
          MutChunks { v: self, chunk_size: chunk_size }
      }
  
-     fn mut_shift_ref(&mut self) -> &'a mut T {
+     fn mut_shift_ref(&mut self) -> Option<&'a mut T> {
+         if self.len() == 0 { return None; }
          unsafe {
              let s: &mut Slice<T> = cast::transmute(self);
-             cast::transmute_mut(&*raw::shift_ptr(s))
+             Some(cast::transmute_mut(&*raw::shift_ptr(s)))
          }
      }
  
-     fn mut_pop_ref(&mut self) -> &'a mut T {
+     fn mut_pop_ref(&mut self) -> Option<&'a mut T> {
+         if self.len() == 0 { return None; }
          unsafe {
              let s: &mut Slice<T> = cast::transmute(self);
-             cast::transmute_mut(&*raw::pop_ptr(s))
+             Some(cast::transmute_mut(&*raw::pop_ptr(s)))
          }
      }
  
@@@ -2639,7 -2646,7 +2647,7 @@@ macro_rules! iterator 
          pub struct $name<'a, T> {
              priv ptr: $ptr,
              priv end: $ptr,
 -            priv lifetime: Option<$elem> // FIXME: #5922
 +            priv marker: marker::ContravariantLifetime<'a>,
          }
  
          impl<'a, T> Iterator<$elem> for $name<'a, T> {
@@@ -4195,34 -4202,26 +4203,26 @@@ mod tests 
      fn test_shift_ref() {
          let mut x: &[int] = [1, 2, 3, 4, 5];
          let h = x.shift_ref();
-         assert_eq!(*h, 1);
+         assert_eq!(*h.unwrap(), 1);
          assert_eq!(x.len(), 4);
          assert_eq!(x[0], 2);
          assert_eq!(x[3], 5);
-     }
  
-     #[test]
-     #[should_fail]
-     fn test_shift_ref_empty() {
-         let mut x: &[int] = [];
-         x.shift_ref();
+         let mut y: &[int] = [];
+         assert_eq!(y.shift_ref(), None);
      }
  
      #[test]
      fn test_pop_ref() {
          let mut x: &[int] = [1, 2, 3, 4, 5];
          let h = x.pop_ref();
-         assert_eq!(*h, 5);
+         assert_eq!(*h.unwrap(), 5);
          assert_eq!(x.len(), 4);
          assert_eq!(x[0], 1);
          assert_eq!(x[3], 4);
-     }
  
-     #[test]
-     #[should_fail]
-     fn test_pop_ref_empty() {
-         let mut x: &[int] = [];
-         x.pop_ref();
+         let mut y: &[int] = [];
+         assert!(y.pop_ref().is_none());
      }
  
      #[test]
      fn test_mut_shift_ref() {
          let mut x: &mut [int] = [1, 2, 3, 4, 5];
          let h = x.mut_shift_ref();
-         assert_eq!(*h, 1);
+         assert_eq!(*h.unwrap(), 1);
          assert_eq!(x.len(), 4);
          assert_eq!(x[0], 2);
          assert_eq!(x[3], 5);
-     }
  
-     #[test]
-     #[should_fail]
-     fn test_mut_shift_ref_empty() {
-         let mut x: &mut [int] = [];
-         x.mut_shift_ref();
+         let mut y: &mut [int] = [];
+         assert!(y.mut_shift_ref().is_none());
      }
  
      #[test]
      fn test_mut_pop_ref() {
          let mut x: &mut [int] = [1, 2, 3, 4, 5];
          let h = x.mut_pop_ref();
-         assert_eq!(*h, 5);
+         assert_eq!(*h.unwrap(), 5);
          assert_eq!(x.len(), 4);
          assert_eq!(x[0], 1);
          assert_eq!(x[3], 4);
+         let mut y: &mut [int] = [];
+         assert!(y.mut_pop_ref().is_none());
      }
  
      #[test]
-     #[should_fail]
-     fn test_mut_pop_ref_empty() {
-         let mut x: &mut [int] = [];
-         x.mut_pop_ref();
+     fn test_mut_last() {
+         let mut x = [1, 2, 3, 4, 5];
+         let h = x.mut_last();
+         assert_eq!(*h.unwrap(), 5);
+         let mut y: &mut [int] = [];
+         assert!(y.mut_last().is_none());
      }
  }