Skip to content

Commit a269e31

Browse files
committed
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
2 parents f84d53c + 97dd250 commit a269e31

File tree

2 files changed

+16
-11
lines changed

2 files changed

+16
-11
lines changed

src/doc/nomicon/vec-drain.md

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -129,14 +129,16 @@ impl<'a, T> Drop for Drain<'a, T> {
129129
130130
impl<T> Vec<T> {
131131
pub fn drain(&mut self) -> Drain<T> {
132-
// this is a mem::forget safety thing. If Drain is forgotten, we just
133-
// leak the whole Vec's contents. Also we need to do this eventually
134-
// anyway, so why not do it now?
135-
self.len = 0;
136-
137132
unsafe {
133+
let iter = RawValIter::new(&self);
134+
135+
// this is a mem::forget safety thing. If Drain is forgotten, we just
136+
// leak the whole Vec's contents. Also we need to do this *eventually*
137+
// anyway, so why not do it now?
138+
self.len = 0;
139+
138140
Drain {
139-
iter: RawValIter::new(&self),
141+
iter: iter,
140142
vec: PhantomData,
141143
}
142144
}

src/doc/nomicon/vec-final.md

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -155,13 +155,16 @@ impl<T> Vec<T> {
155155
}
156156

157157
pub fn drain(&mut self) -> Drain<T> {
158-
// this is a mem::forget safety thing. If this is forgotten, we just
159-
// leak the whole Vec's contents. Also we need to do this *eventually*
160-
// anyway, so why not do it now?
161-
self.len = 0;
162158
unsafe {
159+
let iter = RawValIter::new(&self);
160+
161+
// this is a mem::forget safety thing. If Drain is forgotten, we just
162+
// leak the whole Vec's contents. Also we need to do this *eventually*
163+
// anyway, so why not do it now?
164+
self.len = 0;
165+
163166
Drain {
164-
iter: RawValIter::new(&self),
167+
iter: iter,
165168
vec: PhantomData,
166169
}
167170
}

0 commit comments

Comments
 (0)