vec: limit unsafe to where it's actually needed

pull/415/head
Eva Pace 2 years ago
parent cfe77d0f5f
commit 195fbfbc55

@ -135,8 +135,7 @@ impl<'a, T> Drop for Drain<'a, T> {
impl<T> Vec<T> { impl<T> Vec<T> {
pub fn drain(&mut self) -> Drain<T> { pub fn drain(&mut self) -> Drain<T> {
unsafe { let iter = unsafe { RawValIter::new(&self) };
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just // this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually* // leak the whole Vec's contents. Also we need to do this *eventually*
@ -149,7 +148,6 @@ impl<T> Vec<T> {
} }
} }
} }
}
``` ```
For more details on the `mem::forget` problem, see the For more details on the `mem::forget` problem, see the

@ -138,14 +138,17 @@ impl<T> Vec<T> {
self.len - index, self.len - index,
); );
ptr::write(self.ptr().add(index), elem); ptr::write(self.ptr().add(index), elem);
self.len += 1;
} }
self.len += 1;
} }
pub fn remove(&mut self, index: usize) -> T { pub fn remove(&mut self, index: usize) -> T {
assert!(index < self.len, "index out of bounds"); assert!(index < self.len, "index out of bounds");
unsafe {
self.len -= 1; self.len -= 1;
unsafe {
let result = ptr::read(self.ptr().add(index)); let result = ptr::read(self.ptr().add(index));
ptr::copy( ptr::copy(
self.ptr().add(index + 1), self.ptr().add(index + 1),
@ -157,8 +160,7 @@ impl<T> Vec<T> {
} }
pub fn drain(&mut self) -> Drain<T> { pub fn drain(&mut self) -> Drain<T> {
unsafe { let iter = unsafe { RawValIter::new(&self) };
let iter = RawValIter::new(&self);
// this is a mem::forget safety thing. If Drain is forgotten, we just // this is a mem::forget safety thing. If Drain is forgotten, we just
// leak the whole Vec's contents. Also we need to do this *eventually* // leak the whole Vec's contents. Also we need to do this *eventually*
@ -171,7 +173,6 @@ impl<T> Vec<T> {
} }
} }
} }
}
impl<T> Drop for Vec<T> { impl<T> Drop for Vec<T> {
fn drop(&mut self) { fn drop(&mut self) {
@ -197,9 +198,10 @@ impl<T> IntoIterator for Vec<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> { fn into_iter(self) -> IntoIter<T> {
unsafe { let (iter, buf) = unsafe {
let iter = RawValIter::new(&self); (RawValIter::new(&self), ptr::read(&self.buf))
let buf = ptr::read(&self.buf); };
mem::forget(self); mem::forget(self);
IntoIter { IntoIter {
@ -208,7 +210,6 @@ impl<T> IntoIterator for Vec<T> {
} }
} }
} }
}
struct RawValIter<T> { struct RawValIter<T> {
start: *const T, start: *const T,

@ -28,8 +28,9 @@ pub fn insert(&mut self, index: usize, elem: T) {
self.len - index, self.len - index,
); );
ptr::write(self.ptr.as_ptr().add(index), elem); ptr::write(self.ptr.as_ptr().add(index), elem);
self.len += 1;
} }
self.len += 1;
} }
``` ```

@ -68,7 +68,6 @@ impl<T> IntoIterator for Vec<T> {
let cap = vec.cap; let cap = vec.cap;
let len = vec.len; let len = vec.len;
unsafe {
IntoIter { IntoIter {
buf: ptr, buf: ptr,
cap, cap,
@ -77,12 +76,11 @@ impl<T> IntoIterator for Vec<T> {
// can't offset off this pointer, it's not allocated! // can't offset off this pointer, it's not allocated!
ptr.as_ptr() ptr.as_ptr()
} else { } else {
ptr.as_ptr().add(len) unsafe { ptr.as_ptr().add(len) }
}, },
} }
} }
} }
}
``` ```
Here's iterating forward: Here's iterating forward:

@ -131,10 +131,9 @@ impl<T> IntoIterator for Vec<T> {
type Item = T; type Item = T;
type IntoIter = IntoIter<T>; type IntoIter = IntoIter<T>;
fn into_iter(self) -> IntoIter<T> { fn into_iter(self) -> IntoIter<T> {
unsafe {
// need to use ptr::read to unsafely move the buf out since it's // need to use ptr::read to unsafely move the buf out since it's
// not Copy, and Vec implements Drop (so we can't destructure it). // not Copy, and Vec implements Drop (so we can't destructure it).
let buf = ptr::read(&self.buf); let buf = unsafe { ptr::read(&self.buf) };
let len = self.len; let len = self.len;
mem::forget(self); mem::forget(self);
@ -144,13 +143,12 @@ impl<T> IntoIterator for Vec<T> {
// can't offset off of a pointer unless it's part of an allocation // can't offset off of a pointer unless it's part of an allocation
buf.ptr.as_ptr() buf.ptr.as_ptr()
} else { } else {
buf.ptr.as_ptr().add(len) unsafe { buf.ptr.as_ptr().add(len) }
}, },
_buf: buf, _buf: buf,
} }
} }
} }
}
``` ```
Much better. Much better.

Loading…
Cancel
Save