Skip to content

Commit 8bb5a67

Browse files
committed
rollup merge of rust-lang#16993 : dschatzberg/items-bounds
2 parents 4c8d033 + 49e593c commit 8bb5a67

File tree

3 files changed

+81
-19
lines changed

3 files changed

+81
-19
lines changed

src/libcollections/btree/map.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,12 @@ struct AbsEntries<T> {
4646
}
4747

4848
/// An iterator over a BTreeMap's entries.
49-
pub struct Entries<'a, K, V> {
49+
pub struct Entries<'a, K: 'a, V: 'a> {
5050
inner: AbsEntries<Traversal<'a, K, V>>
5151
}
5252

5353
/// A mutable iterator over a BTreeMap's entries.
54-
pub struct MutEntries<'a, K, V> {
54+
pub struct MutEntries<'a, K: 'a, V: 'a> {
5555
inner: AbsEntries<MutTraversal<'a, K, V>>
5656
}
5757

src/libcollections/vec.rs

Lines changed: 77 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -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> {
17191724
pub 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

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

17561778
impl<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(1u)))
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!(1i, 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!(1i, 2, 3));
2516+
}
2517+
2518+
#[test]
2519+
fn test_move_items_reverse() {
2520+
let mut vec = vec!(1i, 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!(3i, 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(|| {

src/libcore/slice.rs

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

12191219
/// Immutable slice iterator
12201220
#[experimental = "needs review"]
1221-
pub struct Items<'a, T> {
1221+
pub struct Items<'a, T: 'a> {
12221222
ptr: *const T,
12231223
end: *const T,
12241224
marker: marker::ContravariantLifetime<'a>
@@ -1261,7 +1261,7 @@ impl<'a, T> RandomAccessIterator<&'a T> for Items<'a, T> {
12611261

12621262
/// Mutable slice iterator.
12631263
#[experimental = "needs review"]
1264-
pub struct MutItems<'a, T> {
1264+
pub struct MutItems<'a, T: 'a> {
12651265
ptr: *mut T,
12661266
end: *mut T,
12671267
marker: marker::ContravariantLifetime<'a>,

0 commit comments

Comments
 (0)