Auto merge of #28265 - boblehest:master, r=bluss
In the last code snippet on the following page there is a bug in the implementation of Vec::drain(). https://doc.rust-lang.org/nightly/nomicon/vec-drain.html ```rust pub fn drain(&mut self) -> Drain<T> { // Oops, setting it to 0 while we still need the old value! self.len = 0; unsafe { Drain { // len is used to create a &[T] from &self here, // so we end up always creating an empty slice. iter: RawValIter::new(&self), vec: PhantomData, } } } ``` A simple test to verify that Drain is broken can be found here: https://play.rust-lang.org/?gist=30f579565e4bbf4836ce&version=nightly And here's one with a fixed implementation: https://play.rust-lang.org/?gist=2ec0c1a6dcf5defd7a53&version=nightly
This commit is contained in:
commit
a269e31a30
2 changed files with 16 additions and 11 deletions
|
|
@ -129,14 +129,16 @@ impl<'a, T> Drop for Drain<'a, T> {
|
|||
|
||||
impl<T> Vec<T> {
|
||||
pub fn drain(&mut self) -> Drain<T> {
|
||||
// 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
|
||||
// anyway, so why not do it now?
|
||||
self.len = 0;
|
||||
|
||||
unsafe {
|
||||
let iter = RawValIter::new(&self);
|
||||
|
||||
// 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*
|
||||
// anyway, so why not do it now?
|
||||
self.len = 0;
|
||||
|
||||
Drain {
|
||||
iter: RawValIter::new(&self),
|
||||
iter: iter,
|
||||
vec: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,13 +155,16 @@ impl<T> Vec<T> {
|
|||
}
|
||||
|
||||
pub fn drain(&mut self) -> Drain<T> {
|
||||
// this is a mem::forget safety thing. If this is forgotten, we just
|
||||
// leak the whole Vec's contents. Also we need to do this *eventually*
|
||||
// anyway, so why not do it now?
|
||||
self.len = 0;
|
||||
unsafe {
|
||||
let iter = RawValIter::new(&self);
|
||||
|
||||
// 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*
|
||||
// anyway, so why not do it now?
|
||||
self.len = 0;
|
||||
|
||||
Drain {
|
||||
iter: RawValIter::new(&self),
|
||||
iter: iter,
|
||||
vec: PhantomData,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue