Skip to content

Commit 9008693

Browse files
committed
Auto merge of #74710 - JohnTitor:rollup-bdz4oee, r=JohnTitor
Rollup of 12 pull requests Successful merges: - #74361 (Improve doc theme logo display) - #74504 (Add right border bar to Dark and Light theme) - #74572 (Internally unify rustc_deprecated and deprecated) - #74601 (Clean up E0724 explanation) - #74623 (polymorphize GlobalAlloc::Function) - #74665 (Don't ICE on unconstrained anonymous lifetimes inside associated types.) - #74666 (More BTreeMap test cases, some exposing undefined behaviour) - #74669 (Fix typo) - #74677 (Remove needless unsafety from BTreeMap::drain_filter) - #74680 (Add missing backticks in diagnostics note) - #74694 (Clean up E0727 explanation) - #74703 (Fix ICE while building MIR with type errors) Failed merges: r? @ghost
2 parents 0820e54 + 01b069d commit 9008693

File tree

35 files changed

+443
-302
lines changed

35 files changed

+443
-302
lines changed

src/liballoc/collections/btree/map.rs

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

1675-
unsafe fn next_kv(
1676-
&mut self,
1677-
) -> Option<Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>> {
1678-
let edge = self.cur_leaf_edge.as_ref()?;
1679-
unsafe { ptr::read(edge).next_kv().ok() }
1680-
}
1681-
16821675
/// Implementation of a typical `DrainFilter::next` method, given the predicate.
16831676
pub(super) fn next<F>(&mut self, pred: &mut F) -> Option<(K, V)>
16841677
where
16851678
F: FnMut(&K, &mut V) -> bool,
16861679
{
1687-
while let Some(mut kv) = unsafe { self.next_kv() } {
1680+
while let Ok(mut kv) = self.cur_leaf_edge.take()?.next_kv() {
16881681
let (k, v) = kv.kv_mut();
16891682
if pred(k, v) {
16901683
*self.length -= 1;

src/liballoc/tests/btree/map.rs

+126-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::collections::BTreeMap;
33
use std::convert::TryFrom;
44
use std::fmt::Debug;
55
use std::iter::FromIterator;
6+
use std::mem;
67
use std::ops::Bound::{self, Excluded, Included, Unbounded};
78
use std::ops::RangeBounds;
89
use std::panic::{catch_unwind, AssertUnwindSafe};
@@ -25,6 +26,20 @@ const MIN_INSERTS_HEIGHT_1: usize = NODE_CAPACITY + 1;
2526
// It's not the minimum size: removing an element from such a tree does not always reduce height.
2627
const MIN_INSERTS_HEIGHT_2: usize = NODE_CAPACITY + (NODE_CAPACITY + 1) * NODE_CAPACITY + 1;
2728

29+
// Gather all references from a mutable iterator and make sure Miri notices if
30+
// using them is dangerous.
31+
fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator<Item = &'a mut T>) {
32+
// Gather all those references.
33+
let mut refs: Vec<&mut T> = iter.collect();
34+
// Use them all. Twice, to be sure we got all interleavings.
35+
for r in refs.iter_mut() {
36+
mem::swap(dummy, r);
37+
}
38+
for r in refs {
39+
mem::swap(dummy, r);
40+
}
41+
}
42+
2843
#[test]
2944
fn test_basic_large() {
3045
let mut map = BTreeMap::new();
@@ -268,7 +283,14 @@ fn test_iter_mut_mutation() {
268283
}
269284

270285
#[test]
286+
#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
271287
fn test_values_mut() {
288+
let mut a: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)).collect();
289+
test_all_refs(&mut 13, a.values_mut());
290+
}
291+
292+
#[test]
293+
fn test_values_mut_mutation() {
272294
let mut a = BTreeMap::new();
273295
a.insert(1, String::from("hello"));
274296
a.insert(2, String::from("goodbye"));
@@ -281,6 +303,36 @@ fn test_values_mut() {
281303
assert_eq!(values, [String::from("hello!"), String::from("goodbye!")]);
282304
}
283305

306+
#[test]
307+
#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
308+
fn test_iter_entering_root_twice() {
309+
let mut map: BTreeMap<_, _> = (0..2).map(|i| (i, i)).collect();
310+
let mut it = map.iter_mut();
311+
let front = it.next().unwrap();
312+
let back = it.next_back().unwrap();
313+
assert_eq!(front, (&0, &mut 0));
314+
assert_eq!(back, (&1, &mut 1));
315+
*front.1 = 24;
316+
*back.1 = 42;
317+
assert_eq!(front, (&0, &mut 24));
318+
assert_eq!(back, (&1, &mut 42));
319+
}
320+
321+
#[test]
322+
#[cfg_attr(miri, ignore)] // FIXME: fails in Miri <https://github.com/rust-lang/rust/issues/73915>
323+
fn test_iter_descending_to_same_node_twice() {
324+
let mut map: BTreeMap<_, _> = (0..MIN_INSERTS_HEIGHT_1).map(|i| (i, i)).collect();
325+
let mut it = map.iter_mut();
326+
// Descend into first child.
327+
let front = it.next().unwrap();
328+
// Descend into first child again, after running through second child.
329+
while it.next_back().is_some() {}
330+
// Check immutable access.
331+
assert_eq!(front, (&0, &mut 0));
332+
// Perform mutable access.
333+
*front.1 = 42;
334+
}
335+
284336
#[test]
285337
fn test_iter_mixed() {
286338
// Miri is too slow
@@ -835,18 +887,16 @@ mod test_drain_filter {
835887
}
836888
}
837889

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

843893
catch_unwind(move || {
844894
drop(map.drain_filter(|i, _| {
845895
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
846896
true
847897
}))
848898
})
849-
.ok();
899+
.unwrap_err();
850900

851901
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
852902
assert_eq!(DROPS.load(Ordering::SeqCst), 3);
@@ -864,10 +914,8 @@ mod test_drain_filter {
864914
}
865915
}
866916

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

872920
catch_unwind(AssertUnwindSafe(|| {
873921
drop(map.drain_filter(|i, _| {
@@ -878,7 +926,45 @@ mod test_drain_filter {
878926
}
879927
}))
880928
}))
881-
.ok();
929+
.unwrap_err();
930+
931+
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
932+
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
933+
assert_eq!(map.len(), 2);
934+
assert_eq!(map.first_entry().unwrap().key(), &4);
935+
assert_eq!(map.last_entry().unwrap().key(), &8);
936+
}
937+
938+
// Same as above, but attempt to use the iterator again after the panic in the predicate
939+
#[test]
940+
fn pred_panic_reuse() {
941+
static PREDS: AtomicUsize = AtomicUsize::new(0);
942+
static DROPS: AtomicUsize = AtomicUsize::new(0);
943+
944+
struct D;
945+
impl Drop for D {
946+
fn drop(&mut self) {
947+
DROPS.fetch_add(1, Ordering::SeqCst);
948+
}
949+
}
950+
951+
// Keys are multiples of 4, so that each key is counted by a hexadecimal digit.
952+
let mut map = (0..3).map(|i| (i * 4, D)).collect::<BTreeMap<_, _>>();
953+
954+
{
955+
let mut it = map.drain_filter(|i, _| {
956+
PREDS.fetch_add(1usize << i, Ordering::SeqCst);
957+
match i {
958+
0 => true,
959+
_ => panic!(),
960+
}
961+
});
962+
catch_unwind(AssertUnwindSafe(|| while it.next().is_some() {})).unwrap_err();
963+
// Iterator behaviour after a panic is explicitly unspecified,
964+
// so this is just the current implementation:
965+
let result = catch_unwind(AssertUnwindSafe(|| it.next()));
966+
assert!(matches!(result, Ok(None)));
967+
}
882968

883969
assert_eq!(PREDS.load(Ordering::SeqCst), 0x011);
884970
assert_eq!(DROPS.load(Ordering::SeqCst), 1);
@@ -1283,6 +1369,34 @@ fn test_split_off_empty_left() {
12831369
assert!(right.into_iter().eq(data));
12841370
}
12851371

1372+
// In a tree with 3 levels, if all but a part of the first leaf node is split off,
1373+
// make sure fix_top eliminates both top levels.
1374+
#[test]
1375+
fn test_split_off_tiny_left_height_2() {
1376+
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
1377+
let mut left: BTreeMap<_, _> = pairs.clone().collect();
1378+
let right = left.split_off(&1);
1379+
assert_eq!(left.len(), 1);
1380+
assert_eq!(right.len(), MIN_INSERTS_HEIGHT_2 - 1);
1381+
assert_eq!(*left.first_key_value().unwrap().0, 0);
1382+
assert_eq!(*right.first_key_value().unwrap().0, 1);
1383+
}
1384+
1385+
// In a tree with 3 levels, if only part of the last leaf node is split off,
1386+
// make sure fix_top eliminates both top levels.
1387+
#[test]
1388+
fn test_split_off_tiny_right_height_2() {
1389+
let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i));
1390+
let last = MIN_INSERTS_HEIGHT_2 - 1;
1391+
let mut left: BTreeMap<_, _> = pairs.clone().collect();
1392+
assert_eq!(*left.last_key_value().unwrap().0, last);
1393+
let right = left.split_off(&last);
1394+
assert_eq!(left.len(), MIN_INSERTS_HEIGHT_2 - 1);
1395+
assert_eq!(right.len(), 1);
1396+
assert_eq!(*left.last_key_value().unwrap().0, last - 1);
1397+
assert_eq!(*right.last_key_value().unwrap().0, last);
1398+
}
1399+
12861400
#[test]
12871401
fn test_split_off_large_random_sorted() {
12881402
// Miri is too slow
@@ -1319,7 +1433,7 @@ fn test_into_iter_drop_leak_height_0() {
13191433
map.insert("d", D);
13201434
map.insert("e", D);
13211435

1322-
catch_unwind(move || drop(map.into_iter())).ok();
1436+
catch_unwind(move || drop(map.into_iter())).unwrap_err();
13231437

13241438
assert_eq!(DROPS.load(Ordering::SeqCst), 5);
13251439
}
@@ -1343,7 +1457,7 @@ fn test_into_iter_drop_leak_height_1() {
13431457
DROPS.store(0, Ordering::SeqCst);
13441458
PANIC_POINT.store(panic_point, Ordering::SeqCst);
13451459
let map: BTreeMap<_, _> = (0..size).map(|i| (i, D)).collect();
1346-
catch_unwind(move || drop(map.into_iter())).ok();
1460+
catch_unwind(move || drop(map.into_iter())).unwrap_err();
13471461
assert_eq!(DROPS.load(Ordering::SeqCst), size);
13481462
}
13491463
}

src/libcore/iter/range.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ pub unsafe trait Step: Clone + PartialOrd + Sized {
3232
/// * `steps_between(&a, &b) == Some(n)` only if `a <= b`
3333
/// * Corollary: `steps_between(&a, &b) == Some(0)` if and only if `a == b`
3434
/// * Note that `a <= b` does _not_ imply `steps_between(&a, &b) != None`;
35-
/// this is the case wheen it would require more than `usize::MAX` steps to get to `b`
35+
/// this is the case when it would require more than `usize::MAX` steps to get to `b`
3636
/// * `steps_between(&a, &b) == None` if `a > b`
3737
fn steps_between(start: &Self, end: &Self) -> Option<usize>;
3838

src/libcore/ops/function.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
#[rustc_on_unimplemented(
6060
on(
6161
Args = "()",
62-
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
62+
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
6363
),
6464
message = "expected a `{Fn}<{Args}>` closure, found `{Self}`",
6565
label = "expected an `Fn<{Args}>` closure, found `{Self}`"
@@ -141,7 +141,7 @@ pub trait Fn<Args>: FnMut<Args> {
141141
#[rustc_on_unimplemented(
142142
on(
143143
Args = "()",
144-
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
144+
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
145145
),
146146
message = "expected a `{FnMut}<{Args}>` closure, found `{Self}`",
147147
label = "expected an `FnMut<{Args}>` closure, found `{Self}`"
@@ -215,7 +215,7 @@ pub trait FnMut<Args>: FnOnce<Args> {
215215
#[rustc_on_unimplemented(
216216
on(
217217
Args = "()",
218-
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}"
218+
note = "wrap the `{Self}` in a closure with no arguments: `|| {{ /* code */ }}`"
219219
),
220220
message = "expected a `{FnOnce}<{Args}>` closure, found `{Self}`",
221221
label = "expected an `FnOnce<{Args}>` closure, found `{Self}`"

0 commit comments

Comments
 (0)