Skip to content

Commit 8052601

Browse files
committed
Explicitly forget the zero remaining elements in vec::IntoIter::fold().
This seems to help LLVM notice that dropping the elements in the destructor is not necessary.
1 parent 90b6588 commit 8052601

File tree

2 files changed

+34
-0
lines changed

2 files changed

+34
-0
lines changed

library/alloc/src/vec/into_iter.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -329,6 +329,12 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
329329
accum = f(accum, tmp);
330330
}
331331
}
332+
333+
// There are in fact no remaining elements to forget, but by doing this we can avoid
334+
// potentially generating a needless loop to drop the elements that cannot exist at
335+
// this point.
336+
self.forget_remaining_elements();
337+
332338
accum
333339
}
334340

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//@ compile-flags: -Copt-level=3
2+
// Test that we can avoid generating an element dropping loop when `vec::IntoIter` is consumed.
3+
#![crate_type = "lib"]
4+
5+
use std::vec;
6+
7+
struct Bomb;
8+
impl Drop for Bomb {
9+
#[inline]
10+
fn drop(&mut self) {
11+
panic!("dropped")
12+
}
13+
}
14+
15+
/// This test case from https://users.rust-lang.org/t/unnecessary-drop-in-place-emitted-for-a-fully-consumed-intoiter/135119
16+
/// It should not emit any `drop::<Bomb>()` because every element is forgotten.
17+
// CHECK-LABEL: @vec_into_iter_drop_option
18+
#[no_mangle]
19+
pub fn vec_into_iter_drop_option(v: vec::Vec<(usize, Option<Bomb>)>) -> usize {
20+
// CHECK-NOT: panic
21+
// CHECK-NOT: Bomb$u20$as$u20$core..ops..drop..Drop
22+
let mut last = 0;
23+
v.into_iter().for_each(|(x, bomb)| {
24+
last = x;
25+
std::mem::forget(bomb);
26+
});
27+
last
28+
}

0 commit comments

Comments
 (0)