Skip to content

Commit 4184396

Browse files
committed
Add lifetime bounds on Items and MutItems.
This also requires a fix for Vec's MoveItems. This resolves issue #16941
1 parent b419e9e commit 4184396

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed

src/libcollections/vec.rs

Lines changed: 42 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -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> {
17731774
pub 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

17791781
impl<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(1u)))
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

18101828
impl<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(1u)))
1841+
} else {
1842+
self.end = self.end.offset(-1);
1843+
1844+
Some(ptr::read(mem::transmute(self.end)))
1845+
}
1846+
}
18191847
}
18201848
}
18211849
}

src/libcore/slice.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1163,7 +1163,7 @@ macro_rules! iterator {
11631163

11641164
/// Immutable slice iterator
11651165
#[experimental = "needs review"]
1166-
pub struct Items<'a, T> {
1166+
pub struct Items<'a, T: 'a> {
11671167
ptr: *const T,
11681168
end: *const T,
11691169
marker: marker::ContravariantLifetime<'a>
@@ -1206,7 +1206,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
12061206

12071207
/// Mutable slice iterator.
12081208
#[experimental = "needs review"]
1209-
pub struct MutItems<'a, T> {
1209+
pub struct MutItems<'a, T: 'a> {
12101210
ptr: *mut T,
12111211
end: *mut T,
12121212
marker: marker::ContravariantLifetime<'a>,

0 commit comments

Comments
 (0)