Skip to content

Commit 8cdf6ca

Browse files
author
The Miri Conjob Bot
committed
Merge from rustc
2 parents 06ade5c + b2fb12a commit 8cdf6ca

File tree

23 files changed

+1397
-681
lines changed

23 files changed

+1397
-681
lines changed

alloc/src/collections/btree/map.rs

Lines changed: 438 additions & 339 deletions
Large diffs are not rendered by default.

alloc/src/collections/btree/map/tests.rs

Lines changed: 87 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2349,127 +2349,166 @@ fn test_cursor() {
23492349
let map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
23502350

23512351
let mut cur = map.lower_bound(Bound::Unbounded);
2352-
assert_eq!(cur.key(), Some(&1));
2353-
cur.move_next();
2354-
assert_eq!(cur.key(), Some(&2));
2355-
assert_eq!(cur.peek_next(), Some((&3, &'c')));
2356-
cur.move_prev();
2357-
assert_eq!(cur.key(), Some(&1));
2352+
assert_eq!(cur.peek_next(), Some((&1, &'a')));
23582353
assert_eq!(cur.peek_prev(), None);
2354+
assert_eq!(cur.prev(), None);
2355+
assert_eq!(cur.next(), Some((&1, &'a')));
2356+
2357+
assert_eq!(cur.next(), Some((&2, &'b')));
2358+
2359+
assert_eq!(cur.peek_next(), Some((&3, &'c')));
2360+
assert_eq!(cur.prev(), Some((&2, &'b')));
2361+
assert_eq!(cur.peek_prev(), Some((&1, &'a')));
23592362

23602363
let mut cur = map.upper_bound(Bound::Excluded(&1));
2361-
assert_eq!(cur.key(), None);
2362-
cur.move_next();
2363-
assert_eq!(cur.key(), Some(&1));
2364-
cur.move_prev();
2365-
assert_eq!(cur.key(), None);
2366-
assert_eq!(cur.peek_prev(), Some((&3, &'c')));
2364+
assert_eq!(cur.peek_prev(), None);
2365+
assert_eq!(cur.next(), Some((&1, &'a')));
2366+
assert_eq!(cur.prev(), Some((&1, &'a')));
23672367
}
23682368

23692369
#[test]
23702370
fn test_cursor_mut() {
23712371
let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]);
23722372
let mut cur = map.lower_bound_mut(Bound::Excluded(&3));
2373-
assert_eq!(cur.key(), Some(&5));
2374-
cur.insert_before(4, 'd');
2375-
assert_eq!(cur.key(), Some(&5));
2373+
assert_eq!(cur.peek_next(), Some((&5, &mut 'e')));
2374+
assert_eq!(cur.peek_prev(), Some((&3, &mut 'c')));
2375+
2376+
cur.insert_before(4, 'd').unwrap();
2377+
assert_eq!(cur.peek_next(), Some((&5, &mut 'e')));
23762378
assert_eq!(cur.peek_prev(), Some((&4, &mut 'd')));
2377-
cur.move_next();
2378-
assert_eq!(cur.key(), None);
2379-
cur.insert_before(6, 'f');
2380-
assert_eq!(cur.key(), None);
2381-
assert_eq!(cur.remove_current(), None);
2382-
assert_eq!(cur.key(), None);
2383-
cur.insert_after(0, '?');
2384-
assert_eq!(cur.key(), None);
2385-
assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd'), (5, 'e'), (6, 'f')]));
2379+
2380+
assert_eq!(cur.next(), Some((&5, &mut 'e')));
2381+
assert_eq!(cur.peek_next(), None);
2382+
assert_eq!(cur.peek_prev(), Some((&5, &mut 'e')));
2383+
cur.insert_before(6, 'f').unwrap();
2384+
assert_eq!(cur.peek_next(), None);
2385+
assert_eq!(cur.peek_prev(), Some((&6, &mut 'f')));
2386+
assert_eq!(cur.remove_prev(), Some((6, 'f')));
2387+
assert_eq!(cur.remove_prev(), Some((5, 'e')));
2388+
assert_eq!(cur.remove_next(), None);
2389+
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')]));
23862390

23872391
let mut cur = map.upper_bound_mut(Bound::Included(&5));
2388-
assert_eq!(cur.key(), Some(&5));
2389-
assert_eq!(cur.remove_current(), Some((5, 'e')));
2390-
assert_eq!(cur.key(), Some(&6));
2391-
assert_eq!(cur.remove_current_and_move_back(), Some((6, 'f')));
2392-
assert_eq!(cur.key(), Some(&4));
2393-
assert_eq!(map, BTreeMap::from([(0, '?'), (1, 'a'), (3, 'c'), (4, 'd')]));
2392+
assert_eq!(cur.peek_next(), None);
2393+
assert_eq!(cur.prev(), Some((&4, &mut 'd')));
2394+
assert_eq!(cur.peek_next(), Some((&4, &mut 'd')));
2395+
assert_eq!(cur.peek_prev(), Some((&3, &mut 'c')));
2396+
assert_eq!(cur.remove_next(), Some((4, 'd')));
2397+
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')]));
2398+
}
2399+
2400+
#[test]
2401+
fn test_cursor_mut_key() {
2402+
let mut map = BTreeMap::from([(1, 'a'), (3, 'c'), (5, 'e')]);
2403+
let mut cur = unsafe { map.lower_bound_mut(Bound::Excluded(&3)).with_mutable_key() };
2404+
assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e')));
2405+
assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c')));
2406+
2407+
cur.insert_before(4, 'd').unwrap();
2408+
assert_eq!(cur.peek_next(), Some((&mut 5, &mut 'e')));
2409+
assert_eq!(cur.peek_prev(), Some((&mut 4, &mut 'd')));
2410+
2411+
assert_eq!(cur.next(), Some((&mut 5, &mut 'e')));
2412+
assert_eq!(cur.peek_next(), None);
2413+
assert_eq!(cur.peek_prev(), Some((&mut 5, &mut 'e')));
2414+
cur.insert_before(6, 'f').unwrap();
2415+
assert_eq!(cur.peek_next(), None);
2416+
assert_eq!(cur.peek_prev(), Some((&mut 6, &mut 'f')));
2417+
assert_eq!(cur.remove_prev(), Some((6, 'f')));
2418+
assert_eq!(cur.remove_prev(), Some((5, 'e')));
2419+
assert_eq!(cur.remove_next(), None);
2420+
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c'), (4, 'd')]));
2421+
2422+
let mut cur = unsafe { map.upper_bound_mut(Bound::Included(&5)).with_mutable_key() };
2423+
assert_eq!(cur.peek_next(), None);
2424+
assert_eq!(cur.prev(), Some((&mut 4, &mut 'd')));
2425+
assert_eq!(cur.peek_next(), Some((&mut 4, &mut 'd')));
2426+
assert_eq!(cur.peek_prev(), Some((&mut 3, &mut 'c')));
2427+
assert_eq!(cur.remove_next(), Some((4, 'd')));
2428+
assert_eq!(map, BTreeMap::from([(1, 'a'), (3, 'c')]));
2429+
}
2430+
2431+
#[test]
2432+
fn test_cursor_empty() {
2433+
let mut map = BTreeMap::new();
2434+
let mut cur = map.lower_bound_mut(Bound::Excluded(&3));
2435+
assert_eq!(cur.peek_next(), None);
2436+
assert_eq!(cur.peek_prev(), None);
2437+
cur.insert_after(0, 0).unwrap();
2438+
assert_eq!(cur.peek_next(), Some((&0, &mut 0)));
2439+
assert_eq!(cur.peek_prev(), None);
2440+
assert_eq!(map, BTreeMap::from([(0, 0)]));
23942441
}
23952442

2396-
#[should_panic(expected = "key must be ordered above the previous element")]
23972443
#[test]
23982444
fn test_cursor_mut_insert_before_1() {
23992445
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24002446
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2401-
cur.insert_before(0, 'd');
2447+
cur.insert_before(0, 'd').unwrap_err();
24022448
}
24032449

2404-
#[should_panic(expected = "key must be ordered above the previous element")]
24052450
#[test]
24062451
fn test_cursor_mut_insert_before_2() {
24072452
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24082453
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2409-
cur.insert_before(1, 'd');
2454+
cur.insert_before(1, 'd').unwrap_err();
24102455
}
24112456

2412-
#[should_panic(expected = "key must be ordered below the current element")]
24132457
#[test]
24142458
fn test_cursor_mut_insert_before_3() {
24152459
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24162460
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2417-
cur.insert_before(2, 'd');
2461+
cur.insert_before(2, 'd').unwrap_err();
24182462
}
24192463

2420-
#[should_panic(expected = "key must be ordered below the current element")]
24212464
#[test]
24222465
fn test_cursor_mut_insert_before_4() {
24232466
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24242467
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2425-
cur.insert_before(3, 'd');
2468+
cur.insert_before(3, 'd').unwrap_err();
24262469
}
24272470

2428-
#[should_panic(expected = "key must be ordered above the current element")]
24292471
#[test]
24302472
fn test_cursor_mut_insert_after_1() {
24312473
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24322474
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2433-
cur.insert_after(1, 'd');
2475+
cur.insert_after(1, 'd').unwrap_err();
24342476
}
24352477

2436-
#[should_panic(expected = "key must be ordered above the current element")]
24372478
#[test]
24382479
fn test_cursor_mut_insert_after_2() {
24392480
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24402481
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2441-
cur.insert_after(2, 'd');
2482+
cur.insert_after(2, 'd').unwrap_err();
24422483
}
24432484

2444-
#[should_panic(expected = "key must be ordered below the next element")]
24452485
#[test]
24462486
fn test_cursor_mut_insert_after_3() {
24472487
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24482488
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2449-
cur.insert_after(3, 'd');
2489+
cur.insert_after(3, 'd').unwrap_err();
24502490
}
24512491

2452-
#[should_panic(expected = "key must be ordered below the next element")]
24532492
#[test]
24542493
fn test_cursor_mut_insert_after_4() {
24552494
let mut map = BTreeMap::from([(1, 'a'), (2, 'b'), (3, 'c')]);
24562495
let mut cur = map.upper_bound_mut(Bound::Included(&2));
2457-
cur.insert_after(4, 'd');
2496+
cur.insert_after(4, 'd').unwrap_err();
24582497
}
24592498

24602499
#[test]
24612500
fn cursor_peek_prev_agrees_with_cursor_mut() {
24622501
let mut map = BTreeMap::from([(1, 1), (2, 2), (3, 3)]);
24632502

24642503
let cursor = map.lower_bound(Bound::Excluded(&3));
2465-
assert!(cursor.key().is_none());
2504+
assert!(cursor.peek_next().is_none());
24662505

24672506
let prev = cursor.peek_prev();
24682507
assert_matches!(prev, Some((&3, _)));
24692508

24702509
// Shadow names so the two parts of this test match.
24712510
let mut cursor = map.lower_bound_mut(Bound::Excluded(&3));
2472-
assert!(cursor.key().is_none());
2511+
assert!(cursor.peek_next().is_none());
24732512

24742513
let prev = cursor.peek_prev();
24752514
assert_matches!(prev, Some((&3, _)));

alloc/src/collections/btree/node.rs

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -648,17 +648,36 @@ impl<K, V, Type> NodeRef<marker::Owned, K, V, Type> {
648648

649649
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
650650
/// Adds a key-value pair to the end of the node, and returns
651-
/// the mutable reference of the inserted value.
652-
pub fn push(&mut self, key: K, val: V) -> &mut V {
651+
/// a handle to the inserted value.
652+
///
653+
/// # Safety
654+
///
655+
/// The returned handle has an unbound lifetime.
656+
pub unsafe fn push_with_handle<'b>(
657+
&mut self,
658+
key: K,
659+
val: V,
660+
) -> Handle<NodeRef<marker::Mut<'b>, K, V, marker::Leaf>, marker::KV> {
653661
let len = self.len_mut();
654662
let idx = usize::from(*len);
655663
assert!(idx < CAPACITY);
656664
*len += 1;
657665
unsafe {
658666
self.key_area_mut(idx).write(key);
659-
self.val_area_mut(idx).write(val)
667+
self.val_area_mut(idx).write(val);
668+
Handle::new_kv(
669+
NodeRef { height: self.height, node: self.node, _marker: PhantomData },
670+
idx,
671+
)
660672
}
661673
}
674+
675+
/// Adds a key-value pair to the end of the node, and returns
676+
/// the mutable reference of the inserted value.
677+
pub fn push(&mut self, key: K, val: V) -> *mut V {
678+
// SAFETY: The unbound handle is no longer accessible.
679+
unsafe { self.push_with_handle(key, val).into_val_mut() }
680+
}
662681
}
663682

664683
impl<'a, K: 'a, V: 'a> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
@@ -1100,10 +1119,10 @@ impl<'a, K: 'a, V: 'a, NodeType> Handle<NodeRef<marker::Mut<'a>, K, V, NodeType>
11001119
unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() }
11011120
}
11021121

1103-
pub fn into_kv_valmut(self) -> (&'a K, &'a mut V) {
1122+
pub fn into_kv_mut(self) -> (&'a mut K, &'a mut V) {
11041123
debug_assert!(self.idx < self.node.len());
11051124
let leaf = self.node.into_leaf_mut();
1106-
let k = unsafe { leaf.keys.get_unchecked(self.idx).assume_init_ref() };
1125+
let k = unsafe { leaf.keys.get_unchecked_mut(self.idx).assume_init_mut() };
11071126
let v = unsafe { leaf.vals.get_unchecked_mut(self.idx).assume_init_mut() };
11081127
(k, v)
11091128
}

core/src/intrinsics.rs

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2517,6 +2517,66 @@ extern "rust-intrinsic" {
25172517
where
25182518
G: FnOnce<ARG, Output = RET>,
25192519
F: FnOnce<ARG, Output = RET>;
2520+
2521+
/// Returns whether the argument's value is statically known at
2522+
/// compile-time.
2523+
///
2524+
/// This is useful when there is a way of writing the code that will
2525+
/// be *faster* when some variables have known values, but *slower*
2526+
/// in the general case: an `if is_val_statically_known(var)` can be used
2527+
/// to select between these two variants. The `if` will be optimized away
2528+
/// and only the desired branch remains.
2529+
///
2530+
/// Formally speaking, this function non-deterministically returns `true`
2531+
/// or `false`, and the caller has to ensure sound behavior for both cases.
2532+
/// In other words, the following code has *Undefined Behavior*:
2533+
///
2534+
/// ```
2535+
/// #![feature(is_val_statically_known)]
2536+
/// #![feature(core_intrinsics)]
2537+
/// # #![allow(internal_features)]
2538+
/// use std::hint::unreachable_unchecked;
2539+
/// use std::intrinsics::is_val_statically_known;
2540+
///
2541+
/// unsafe {
2542+
/// if !is_val_statically_known(0) { unreachable_unchecked(); }
2543+
/// }
2544+
/// ```
2545+
///
2546+
/// This also means that the following code's behavior is unspecified; it
2547+
/// may panic, or it may not:
2548+
///
2549+
/// ```no_run
2550+
/// #![feature(is_val_statically_known)]
2551+
/// #![feature(core_intrinsics)]
2552+
/// # #![allow(internal_features)]
2553+
/// use std::intrinsics::is_val_statically_known;
2554+
///
2555+
/// unsafe {
2556+
/// assert_eq!(is_val_statically_known(0), is_val_statically_known(0));
2557+
/// }
2558+
/// ```
2559+
///
2560+
/// Unsafe code may not rely on `is_val_statically_known` returning any
2561+
/// particular value, ever. However, the compiler will generally make it
2562+
/// return `true` only if the value of the argument is actually known.
2563+
///
2564+
/// When calling this in a `const fn`, both paths must be semantically
2565+
/// equivalent, that is, the result of the `true` branch and the `false`
2566+
/// branch must return the same value and have the same side-effects *no
2567+
/// matter what*.
2568+
#[rustc_const_unstable(feature = "is_val_statically_known", issue = "none")]
2569+
#[rustc_nounwind]
2570+
#[cfg(not(bootstrap))]
2571+
pub fn is_val_statically_known<T: Copy>(arg: T) -> bool;
2572+
}
2573+
2574+
// FIXME: Seems using `unstable` here completely ignores `rustc_allow_const_fn_unstable`
2575+
// and thus compiling stage0 core doesn't work.
2576+
#[rustc_const_stable(feature = "is_val_statically_known", since = "0.0.0")]
2577+
#[cfg(bootstrap)]
2578+
pub const unsafe fn is_val_statically_known<T: Copy>(_arg: T) -> bool {
2579+
false
25202580
}
25212581

25222582
// Some functions are defined here because they accidentally got made

core/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@
200200
//
201201
// Language features:
202202
// tidy-alphabetical-start
203+
#![cfg_attr(not(bootstrap), feature(is_val_statically_known))]
203204
#![feature(abi_unadjusted)]
204205
#![feature(adt_const_params)]
205206
#![feature(allow_internal_unsafe)]

0 commit comments

Comments
 (0)