@@ -791,11 +791,16 @@ impl<T> Vec<T> {
791791 #[ inline]
792792 pub fn into_iter ( self ) -> MoveItems < T > {
793793 unsafe {
794- let iter = mem:: transmute ( self . as_slice ( ) . iter ( ) ) ;
795794 let ptr = self . ptr ;
796795 let cap = self . cap ;
796+ let begin = self . ptr as * const T ;
797+ let end = if mem:: size_of :: < T > ( ) == 0 {
798+ ( ptr as uint + self . len ( ) ) as * const T
799+ } else {
800+ ptr. offset ( self . len ( ) as int ) as * const T
801+ } ;
797802 mem:: forget ( self ) ;
798- MoveItems { allocation : ptr, cap : cap, iter : iter }
803+ MoveItems { allocation : ptr, cap : cap, ptr : begin , end : end }
799804 }
800805 }
801806
@@ -1719,7 +1724,8 @@ impl<T> MutableSeq<T> for Vec<T> {
17191724pub struct MoveItems < T > {
17201725 allocation : * mut T , // the block of memory allocated for the vector
17211726 cap : uint , // the capacity of the vector
1722- iter : Items < ' static , T >
1727+ ptr : * const T ,
1728+ end : * const T
17231729}
17241730
17251731impl < T > MoveItems < T > {
@@ -1728,7 +1734,7 @@ impl<T> MoveItems<T> {
17281734 pub fn unwrap ( mut self ) -> Vec < T > {
17291735 unsafe {
17301736 for _x in self { }
1731- let MoveItems { allocation, cap, iter : _iter } = self ;
1737+ let MoveItems { allocation, cap, ptr : _ptr , end : _end } = self ;
17321738 mem:: forget ( self ) ;
17331739 Vec { ptr : allocation, cap : cap, len : 0 }
17341740 }
@@ -1739,29 +1745,55 @@ impl<T> Iterator<T> for MoveItems<T> {
17391745 #[ inline]
17401746 fn next < ' a > ( & ' a mut self ) -> Option < T > {
17411747 unsafe {
1742- // Unsafely transmute from Items<'static, T> to Items<'a,
1743- // T> because otherwise the type checker requires that T
1744- // be bounded by 'static.
1745- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1746- iter. next ( ) . map ( |x| ptr:: read ( x) )
1748+ if self . ptr == self . end {
1749+ None
1750+ } else {
1751+ if mem:: size_of :: < T > ( ) == 0 {
1752+ // purposefully don't use 'ptr.offset' because for
1753+ // vectors with 0-size elements this would return the
1754+ // same pointer.
1755+ self . ptr = mem:: transmute ( self . ptr as uint + 1 ) ;
1756+
1757+ // Use a non-null pointer value
1758+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1759+ } else {
1760+ let old = self . ptr ;
1761+ self . ptr = self . ptr . offset ( 1 ) ;
1762+
1763+ Some ( ptr:: read ( old) )
1764+ }
1765+ }
17471766 }
17481767 }
17491768
17501769 #[ inline]
17511770 fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1752- self . iter . size_hint ( )
1771+ let diff = ( self . end as uint ) - ( self . ptr as uint ) ;
1772+ let size = mem:: size_of :: < T > ( ) ;
1773+ let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1774+ ( exact, Some ( exact) )
17531775 }
17541776}
17551777
17561778impl < T > DoubleEndedIterator < T > for MoveItems < T > {
17571779 #[ inline]
17581780 fn next_back < ' a > ( & ' a mut self ) -> Option < T > {
17591781 unsafe {
1760- // Unsafely transmute from Items<'static, T> to Items<'a,
1761- // T> because otherwise the type checker requires that T
1762- // be bounded by 'static.
1763- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1764- iter. next_back ( ) . map ( |x| ptr:: read ( x) )
1782+ if self . end == self . ptr {
1783+ None
1784+ } else {
1785+ if mem:: size_of :: < T > ( ) == 0 {
1786+ // See above for why 'ptr.offset' isn't used
1787+ self . end = mem:: transmute ( self . end as uint - 1 ) ;
1788+
1789+ // Use a non-null pointer value
1790+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1791+ } else {
1792+ self . end = self . end . offset ( -1 ) ;
1793+
1794+ Some ( ptr:: read ( mem:: transmute ( self . end ) ) )
1795+ }
1796+ }
17651797 }
17661798 }
17671799}
@@ -2473,6 +2505,36 @@ mod tests {
24732505 assert_eq ! ( v. map_in_place( |_| ZeroSized ) . as_slice( ) , [ ZeroSized , ZeroSized ] . as_slice( ) ) ;
24742506 }
24752507
2508+ #[ test]
2509+ fn test_move_items ( ) {
2510+ let mut vec = vec ! ( 1 i, 2 , 3 ) ;
2511+ let mut vec2 : Vec < int > = vec ! ( ) ;
2512+ for i in vec. into_iter ( ) {
2513+ vec2. push ( i) ;
2514+ }
2515+ assert ! ( vec2 == vec!( 1 i, 2 , 3 ) ) ;
2516+ }
2517+
2518+ #[ test]
2519+ fn test_move_items_reverse ( ) {
2520+ let mut vec = vec ! ( 1 i, 2 , 3 ) ;
2521+ let mut vec2 : Vec < int > = vec ! ( ) ;
2522+ for i in vec. into_iter ( ) . rev ( ) {
2523+ vec2. push ( i) ;
2524+ }
2525+ assert ! ( vec2 == vec!( 3 i, 2 , 1 ) ) ;
2526+ }
2527+
2528+ #[ test]
2529+ fn test_move_items_zero_sized ( ) {
2530+ let mut vec = vec ! ( ( ) , ( ) , ( ) ) ;
2531+ let mut vec2 : Vec < ( ) > = vec ! ( ) ;
2532+ for i in vec. into_iter ( ) {
2533+ vec2. push ( i) ;
2534+ }
2535+ assert ! ( vec2 == vec!( ( ) , ( ) , ( ) ) ) ;
2536+ }
2537+
24762538 #[ bench]
24772539 fn bench_new ( b : & mut Bencher ) {
24782540 b. iter ( || {
0 commit comments