Skip to content

Commit facc46f

Browse files
committed
BTreeMap::drain_filter: replace needless unsafety and test
1 parent 7d31ffc commit facc46f

File tree

2 files changed

+47
-20
lines changed

2 files changed

+47
-20
lines changed

src/liballoc/collections/btree/map.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -1681,19 +1681,12 @@ impl<'a, K: 'a, V: 'a> DrainFilterInner<'a, K, V> {
16811681
edge.reborrow().next_kv().ok().map(|kv| kv.into_kv())
16821682
}
16831683

1684-
unsafe fn next_kv(
1685-
&mut self,
1686-
) -> Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>> {
1687-
let edge = self.cur_leaf_edge.as_ref()?;
1688-
unsafe { ptr::read(edge).next_kv().ok() }
1689-
}
1690-
16911684
/// Implementation of a typical `DrainFilter::next` method, given the predicate.
16921685
pub(super) fn next<F>(&mut self, pred: &mut F) -> Option<(K, V)>
16931686
where
16941687
F: FnMut(&K, &mut V) -> bool,
16951688
{
1696-
while let Some(mut kv) = unsafe { self.next_kv() } {
1689+
while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() {
16971690
let (k, v) = kv.kv_mut();
16981691
if pred(k, v) {
16991692
*self.length -= 1;

src/liballoc/tests/btree/map.rs

+46-12
Original file line numberDiff line numberDiff line change
@@ -835,18 +835,16 @@ mod test_drain_filter {
835835
}
836836
}
837837

838-
let mut map = BTreeMap::new();
839-
map.insert(0, D);
840-
map.insert(4, D);
841-
map.insert(8, D);
838+
// Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
839+
let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
842840

843841
catch_unwind(move || {
844842
drop(map.drain_filter(|i, _| {
845843
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
846844
true
847845
}))
848846
})
849-
.ok();
847+
.unwrap_err();
850848

851849
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
852850
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
@@ -864,10 +862,8 @@ mod test_drain_filter {
864862
}
865863
}
866864

867-
let mut map = BTreeMap::new();
868-
map.insert(0, D);
869-
map.insert(4, D);
870-
map.insert(8, D);
865+
// Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
866+
let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
871867

872868
catch_unwind(AssertUnwindSafe(|| {
873869
drop(map.drain_filter(|i, _| {
@@ -878,7 +874,45 @@ mod test_drain_filter {
878874
}
879875
}))
880876
}))
881-
.ok();
877+
.unwrap_err();
878+
879+
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
880+
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
881+
assert_eq!(map.len(), 2);
882+
assert_eq!(map.first_entry().unwrap().key(), &4);
883+
assert_eq!(map.last_entry().unwrap().key(), &8);
884+
}
885+
886+
// Same as above, but attempt to use the iterator again after the panic in the predicate
887+
#[test]
888+
fn pred_panic_reuse() {
889+
static PREDS: AtomicUsize = AtomicUsize::new(0);
890+
static DROPS: AtomicUsize = AtomicUsize::new(0);
891+
892+
struct D;
893+
impl Drop for D {
894+
fn drop(&mut self) {
895+
DROPS.fetch_add(1, Ordering::SeqCst);
896+
}
897+
}
898+
899+
// Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
900+
let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
901+
902+
{
903+
let mut it = map.drain_filter(|i, _| {
904+
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
905+
match i {
906+
0 => true,
907+
_ => panic!(),
908+
}
909+
});
910+
catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
911+
// Iterator behaviour after a panic is explicitly unspecified,
912+
// so this is just the current implementation:
913+
let result = catch_unwind(AssertUnwindSafe(|| it.next()));
914+
assert!(matches!(result, Ok(None)));
915+
}
882916

883917
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
884918
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
@@ -1319,7 +1353,7 @@ fn test_into_iter_drop_leak_height_0() {
13191353
map.insert("d", D);
13201354
map.insert("e", D);
13211355

1322-
catch_unwind(move || drop(map.into_iter())).ok();
1356+
catch_unwind(move || drop(map.into_iter())).unwrap_err();
13231357

13241358
assert_eq!(DROPS.load(Ordering::SeqCst), 5);
13251359
}
@@ -1343,7 +1377,7 @@ fn test_into_iter_drop_leak_height_1() {
13431377
DROPS.store(0, Ordering::SeqCst);
13441378
PANIC_POINT.store(panic_point, Ordering::SeqCst);
13451379
let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
1346-
catch_unwind(move || drop(map.into_iter())).ok();
1380+
catch_unwind(move || drop(map.into_iter())).unwrap_err();
13471381
assert_eq!(DROPS.load(Ordering::SeqCst), size);
13481382
}
13491383
}

0 commit comments

Comments
 (0)