Skip to content

Commit fb720c1

Browse files
authored
Rollup merge of rust-lang#147035 - joboet:extract_if_debug, r=tgross35
alloc: fix `Debug` implementation of `ExtractIf` I noticed this while reviewing rust-lang#141032. Calling `get` on the inner `Vec` never returns `Some` as the `Vec`'s length is temporarily set to zero while the `ExtractIf` exists.
2 parents 39ae65b + 0909712 commit fb720c1

File tree

2 files changed

+25
-1
lines changed

2 files changed

+25
-1
lines changed

library/alloc/src/vec/extract_if.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,20 @@ where
130130
A: Allocator,
131131
{
132132
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
133-
let peek = if self.idx < self.end { self.vec.get(self.idx) } else { None };
133+
let peek = if self.idx < self.end {
134+
// This has to use pointer arithmetic as `self.vec[self.idx]` or
135+
// `self.vec.get_unchecked(self.idx)` wouldn't work since we
136+
// temporarily set the length of `self.vec` to zero.
137+
//
138+
// SAFETY:
139+
// Since `self.idx` is smaller than `self.end` and `self.end` is
140+
// smaller than `self.old_len`, `idx` is valid for indexing the
141+
// buffer. Also, per the invariant of `self.idx`, this element
142+
// has not been inspected/moved out yet.
143+
Some(unsafe { &*self.vec.as_ptr().add(self.idx) })
144+
} else {
145+
None
146+
};
134147
f.debug_struct("ExtractIf").field("peek", &peek).finish_non_exhaustive()
135148
}
136149
}

library/alloctests/tests/vec.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,17 @@ fn extract_if_unconsumed() {
16501650
assert_eq!(vec, [1, 2, 3, 4]);
16511651
}
16521652

1653+
#[test]
1654+
fn extract_if_debug() {
1655+
let mut vec = vec![1, 2];
1656+
let mut drain = vec.extract_if(.., |&mut x| x % 2 != 0);
1657+
assert!(format!("{drain:?}").contains("Some(1)"));
1658+
drain.next();
1659+
assert!(format!("{drain:?}").contains("Some(2)"));
1660+
drain.next();
1661+
assert!(format!("{drain:?}").contains("None"));
1662+
}
1663+
16531664
#[test]
16541665
fn test_reserve_exact() {
16551666
// This is all the same as test_reserve

0 commit comments

Comments
 (0)