@@ -845,11 +845,12 @@ impl<T> Vec<T> {
845845 #[ inline]
846846 pub fn into_iter ( self ) -> MoveItems < T > {
847847 unsafe {
848- let iter = mem:: transmute ( self . as_slice ( ) . iter ( ) ) ;
849848 let ptr = self . ptr ;
850849 let cap = self . cap ;
850+ let begin = self . ptr as * const T ;
851+ let end = ( self . ptr as uint + self . len ( ) ) as * const T ;
851852 mem:: forget ( self ) ;
852- MoveItems { allocation : ptr, cap : cap, iter : iter }
853+ MoveItems { allocation : ptr, cap : cap, ptr : begin , end : end }
853854 }
854855 }
855856
@@ -1773,7 +1774,8 @@ impl<T> MutableSeq<T> for Vec<T> {
17731774pub struct MoveItems < T > {
17741775 allocation : * mut T , // the block of memory allocated for the vector
17751776 cap : uint , // the capacity of the vector
1776- iter : Items < ' static , T >
1777+ ptr : * const T ,
1778+ end : * const T
17771779}
17781780
17791781impl < T > MoveItems < T > {
@@ -1793,29 +1795,55 @@ impl<T> Iterator<T> for MoveItems<T> {
17931795 #[ inline]
17941796 fn next < ' a > ( & ' a mut self ) -> Option < T > {
17951797 unsafe {
1796- // Unsafely transmute from Items<'static, T> to Items<'a,
1797- // T> because otherwise the type checker requires that T
1798- // be bounded by 'static.
1799- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1800- iter. next ( ) . map ( |x| ptr:: read ( x) )
1798+ if self . ptr == self . end {
1799+ None
1800+ } else {
1801+ if mem:: size_of :: < T > ( ) == 0 {
1802+ // purposefully don't use 'ptr.offset' because for
1803+ // vectors with 0-size elements this would return the
1804+ // same pointer.
1805+ self . ptr = mem:: transmute ( self . ptr as uint + 1 ) ;
1806+
1807+ // Use a non-null pointer value
1808+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1809+ } else {
1810+ let old = self . ptr ;
1811+ self . ptr = self . ptr . offset ( 1 ) ;
1812+
1813+ Some ( ptr:: read ( old) )
1814+ }
1815+ }
18011816 }
18021817 }
18031818
18041819 #[ inline]
18051820 fn size_hint ( & self ) -> ( uint , Option < uint > ) {
1806- self . iter . size_hint ( )
1821+ let diff = ( self . end as uint ) - ( self . ptr as uint ) ;
1822+ let size = mem:: size_of :: < T > ( ) ;
1823+ let exact = diff / ( if size == 0 { 1 } else { size} ) ;
1824+ ( exact, Some ( exact) )
18071825 }
18081826}
18091827
18101828impl < T > DoubleEndedIterator < T > for MoveItems < T > {
18111829 #[ inline]
18121830 fn next_back < ' a > ( & ' a mut self ) -> Option < T > {
18131831 unsafe {
1814- // Unsafely transmute from Items<'static, T> to Items<'a,
1815- // T> because otherwise the type checker requires that T
1816- // be bounded by 'static.
1817- let iter: & mut Items < ' a , T > = mem:: transmute ( & mut self . iter ) ;
1818- iter. next_back ( ) . map ( |x| ptr:: read ( x) )
1832+ if self . end == self . ptr {
1833+ None
1834+ } else {
1835+ if mem:: size_of :: < T > ( ) == 0 {
1836+ // See above for why 'ptr.offset' isn't used
1837+ self . end = mem:: transmute ( self . end as uint - 1 ) ;
1838+
1839+ // Use a non-null pointer value
1840+ Some ( ptr:: read ( mem:: transmute ( 1 u) ) )
1841+ } else {
1842+ self . end = self . end . offset ( -1 ) ;
1843+
1844+ Some ( ptr:: read ( mem:: transmute ( self . end ) ) )
1845+ }
1846+ }
18191847 }
18201848 }
18211849}
0 commit comments