Skip to content

Commit 1bdc860

Browse files
authoredMar 21, 2020
Rollup merge of rust-lang#70111 - Mark-Simulacrum:btree-no-shared, r=cuviper
BTreeMap: remove shared root This replaces the shared root with `Option`s in the BTreeMap code, and then slightly cleans up the node manipulation code taking advantage of the removal of the shared root. I expect that further simplification is possible, but wanted to get this posted for initial review. Note that `BTreeMap::new()` continues to not allocate. Benchmarks seem within the margin of error/unaffected, as expected for an entirely predictable branch. ``` name alloc-bench-a ns/iter alloc-bench-b ns/iter diff ns/iter diff % speedup btree::map::iter_mut_20 20 21 1 5.00% x 0.95 btree::set::clone_100 1,360 1,439 79 5.81% x 0.95 btree::set::clone_100_and_into_iter 1,319 1,434 115 8.72% x 0.92 btree::set::clone_10k 143,515 150,991 7,476 5.21% x 0.95 btree::set::clone_10k_and_clear 142,792 152,916 10,124 7.09% x 0.93 btree::set::clone_10k_and_into_iter 146,019 154,561 8,542 5.85% x 0.94 ```
2 parents 0751e6a + bce7f6f commit 1bdc860

File tree

6 files changed

+223
-266
lines changed

6 files changed

+223
-266
lines changed
 

‎src/etc/gdb_rust_pretty_printing.py

+21-13
Original file line numberDiff line numberDiff line change
@@ -370,12 +370,17 @@ def to_string(self):
370370
("(len: %i)" % self.__val.get_wrapped_value()['map']['length']))
371371

372372
def children(self):
373-
root = self.__val.get_wrapped_value()['map']['root']
374-
node_ptr = root['node']
375-
i = 0
376-
for child in children_of_node(node_ptr, root['height'], False):
377-
yield (str(i), child)
378-
i = i + 1
373+
prev_idx = None
374+
innermap = GdbValue(self.__val.get_wrapped_value()['map'])
375+
if innermap.get_wrapped_value()['length'] > 0:
376+
root = GdbValue(innermap.get_wrapped_value()['root'])
377+
type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
378+
root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
379+
node_ptr = root['node']
380+
i = 0
381+
for child in children_of_node(node_ptr, root['height'], False):
382+
yield (str(i), child)
383+
i = i + 1
379384

380385

381386
class RustStdBTreeMapPrinter(object):
@@ -391,13 +396,16 @@ def to_string(self):
391396
("(len: %i)" % self.__val.get_wrapped_value()['length']))
392397

393398
def children(self):
394-
root = self.__val.get_wrapped_value()['root']
395-
node_ptr = root['node']
396-
i = 0
397-
for child in children_of_node(node_ptr, root['height'], True):
398-
yield (str(i), child[0])
399-
yield (str(i), child[1])
400-
i = i + 1
399+
if self.__val.get_wrapped_value()['length'] > 0:
400+
root = GdbValue(self.__val.get_wrapped_value()['root'])
401+
type_name = str(root.type.ty.name).replace('core::option::Option<', '')[:-1]
402+
root = root.get_wrapped_value().cast(gdb.lookup_type(type_name))
403+
node_ptr = root['node']
404+
i = 0
405+
for child in children_of_node(node_ptr, root['height'], True):
406+
yield (str(i), child[0])
407+
yield (str(i), child[1])
408+
i = i + 1
401409

402410

403411
class RustStdStringPrinter(object):

‎src/liballoc/collections/btree/map.rs

+116-83
Large diffs are not rendered by default.

‎src/liballoc/collections/btree/node.rs

+60-144
Original file line numberDiff line numberDiff line change
@@ -44,34 +44,7 @@ const B: usize = 6;
4444
pub const MIN_LEN: usize = B - 1;
4545
pub const CAPACITY: usize = 2 * B - 1;
4646

47-
/// The underlying representation of leaf nodes. Note that it is often unsafe to actually store
48-
/// these, since only the first `len` keys and values are assumed to be initialized. As such,
49-
/// these should always be put behind pointers, and specifically behind `BoxedNode` in the owned
50-
/// case.
51-
///
52-
/// We have a separate type for the header and rely on it matching the prefix of `LeafNode`, in
53-
/// order to statically allocate a single dummy node to avoid allocations. This struct is
54-
/// `repr(C)` to prevent them from being reordered. `LeafNode` does not just contain a
55-
/// `NodeHeader` because we do not want unnecessary padding between `len` and the keys.
56-
/// Crucially, `NodeHeader` can be safely transmuted to different K and V. (This is exploited
57-
/// by `as_header`.)
58-
#[repr(C)]
59-
struct NodeHeader<K, V> {
60-
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
61-
/// This either points to an actual node or is null.
62-
parent: *const InternalNode<K, V>,
63-
64-
/// This node's index into the parent node's `edges` array.
65-
/// `*node.parent.edges[node.parent_idx]` should be the same thing as `node`.
66-
/// This is only guaranteed to be initialized when `parent` is non-null.
67-
parent_idx: MaybeUninit<u16>,
68-
69-
/// The number of keys and values this node stores.
70-
///
71-
/// This next to `parent_idx` to encourage the compiler to join `len` and
72-
/// `parent_idx` into the same 32-bit word, reducing space overhead.
73-
len: u16,
74-
}
47+
/// The underlying representation of leaf nodes.
7548
#[repr(C)]
7649
struct LeafNode<K, V> {
7750
/// We use `*const` as opposed to `*mut` so as to be covariant in `K` and `V`.
@@ -111,21 +84,6 @@ impl<K, V> LeafNode<K, V> {
11184
}
11285
}
11386

114-
impl<K, V> NodeHeader<K, V> {
115-
fn is_shared_root(&self) -> bool {
116-
ptr::eq(self, &EMPTY_ROOT_NODE as *const _ as *const _)
117-
}
118-
}
119-
120-
// We need to implement Sync here in order to make a static instance.
121-
unsafe impl Sync for NodeHeader<(), ()> {}
122-
123-
// An empty node used as a placeholder for the root node, to avoid allocations.
124-
// We use just a header in order to save space, since no operation on an empty tree will
125-
// ever take a pointer past the first key.
126-
static EMPTY_ROOT_NODE: NodeHeader<(), ()> =
127-
NodeHeader { parent: ptr::null(), parent_idx: MaybeUninit::uninit(), len: 0 };
128-
12987
/// The underlying representation of internal nodes. As with `LeafNode`s, these should be hidden
13088
/// behind `BoxedNode`s to prevent dropping uninitialized keys and values. Any pointer to an
13189
/// `InternalNode` can be directly casted to a pointer to the underlying `LeafNode` portion of the
@@ -154,12 +112,9 @@ impl<K, V> InternalNode<K, V> {
154112
}
155113

156114
/// A managed, non-null pointer to a node. This is either an owned pointer to
157-
/// `LeafNode<K, V>`, an owned pointer to `InternalNode<K, V>`, or a (not owned)
158-
/// pointer to `NodeHeader<(), ()` (more specifically, the pointer to EMPTY_ROOT_NODE).
159-
/// All of these types have a `NodeHeader<K, V>` prefix, meaning that they have at
160-
/// least the same size as `NodeHeader<K, V>` and store the same kinds of data at the same
161-
/// offsets; and they have a pointer alignment at least as large as `NodeHeader<K, V>`'s.
162-
/// However, `BoxedNode` contains no information as to which of the three types
115+
/// `LeafNode<K, V>` or an owned pointer to `InternalNode<K, V>`.
116+
///
117+
/// However, `BoxedNode` contains no information as to which of the two types
163118
/// of nodes it actually contains, and, partially due to this lack of information,
164119
/// has no destructor.
165120
struct BoxedNode<K, V> {
@@ -184,8 +139,9 @@ impl<K, V> BoxedNode<K, V> {
184139
}
185140
}
186141

187-
/// Either an owned tree or a shared, empty tree. Note that this does not have a destructor,
188-
/// and must be cleaned up manually if it is an owned tree.
142+
/// An owned tree.
143+
///
144+
/// Note that this does not have a destructor, and must be cleaned up manually.
189145
pub struct Root<K, V> {
190146
node: BoxedNode<K, V>,
191147
/// The number of levels below the root node.
@@ -196,20 +152,6 @@ unsafe impl<K: Sync, V: Sync> Sync for Root<K, V> {}
196152
unsafe impl<K: Send, V: Send> Send for Root<K, V> {}
197153

198154
impl<K, V> Root<K, V> {
199-
/// Whether the instance of `Root` wraps a shared, empty root node. If not,
200-
/// the entire tree is uniquely owned by the owner of the `Root` instance.
201-
pub fn is_shared_root(&self) -> bool {
202-
self.as_ref().is_shared_root()
203-
}
204-
205-
/// Returns a shared tree, wrapping a shared root node that is eternally empty.
206-
pub fn shared_empty_root() -> Self {
207-
Root {
208-
node: unsafe { BoxedNode::from_ptr(NonNull::from(&EMPTY_ROOT_NODE).cast()) },
209-
height: 0,
210-
}
211-
}
212-
213155
/// Returns a new owned tree, with its own root node that is initially empty.
214156
pub fn new_leaf() -> Self {
215157
Root { node: BoxedNode::from_leaf(Box::new(unsafe { LeafNode::new() })), height: 0 }
@@ -245,7 +187,6 @@ impl<K, V> Root<K, V> {
245187
/// Adds a new internal node with a single edge, pointing to the previous root, and make that
246188
/// new node the root. This increases the height by 1 and is the opposite of `pop_level`.
247189
pub fn push_level(&mut self) -> NodeRef<marker::Mut<'_>, K, V, marker::Internal> {
248-
debug_assert!(!self.is_shared_root());
249190
let mut new_node = Box::new(unsafe { InternalNode::new() });
250191
new_node.edges[0].write(unsafe { BoxedNode::from_ptr(self.node.as_ptr()) });
251192

@@ -308,11 +249,6 @@ impl<K, V> Root<K, V> {
308249
/// `Leaf`, the `NodeRef` points to a leaf node, when this is `Internal` the
309250
/// `NodeRef` points to an internal node, and when this is `LeafOrInternal` the
310251
/// `NodeRef` could be pointing to either type of node.
311-
/// Note that in case of a leaf node, this might still be the shared root!
312-
/// Only turn this into a `LeafNode` reference if you know it is not the shared root!
313-
/// Shared references must be dereferenceable *for the entire size of their pointee*,
314-
/// so '&LeafNode` or `&InternalNode` pointing to the shared root is undefined behavior.
315-
/// Turning this into a `NodeHeader` reference is always safe.
316252
pub struct NodeRef<BorrowType, K, V, Type> {
317253
/// The number of levels below the node.
318254
height: usize,
@@ -354,7 +290,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
354290
/// Note that, despite being safe, calling this function can have the side effect
355291
/// of invalidating mutable references that unsafe code has created.
356292
pub fn len(&self) -> usize {
357-
self.as_header().len as usize
293+
self.as_leaf().len as usize
358294
}
359295

360296
/// Returns the height of this node in the whole tree. Zero height denotes the
@@ -374,35 +310,24 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
374310
NodeRef { height: self.height, node: self.node, root: self.root, _marker: PhantomData }
375311
}
376312

377-
/// Exposes the leaf "portion" of any leaf or internal node that is not the shared root.
313+
/// Exposes the leaf "portion" of any leaf or internal node.
378314
/// If the node is a leaf, this function simply opens up its data.
379315
/// If the node is an internal node, so not a leaf, it does have all the data a leaf has
380316
/// (header, keys and values), and this function exposes that.
381-
/// Unsafe because the node must not be the shared root. For more information,
382-
/// see the `NodeRef` comments.
383-
unsafe fn as_leaf(&self) -> &LeafNode<K, V> {
384-
debug_assert!(!self.is_shared_root());
385-
self.node.as_ref()
386-
}
387-
388-
fn as_header(&self) -> &NodeHeader<K, V> {
389-
unsafe { &*(self.node.as_ptr() as *const NodeHeader<K, V>) }
390-
}
391-
392-
/// Returns whether the node is the shared, empty root.
393-
pub fn is_shared_root(&self) -> bool {
394-
self.as_header().is_shared_root()
317+
fn as_leaf(&self) -> &LeafNode<K, V> {
318+
// The node must be valid for at least the LeafNode portion.
319+
// This is not a reference in the NodeRef type because we don't know if
320+
// it should be unique or shared.
321+
unsafe { self.node.as_ref() }
395322
}
396323

397324
/// Borrows a view into the keys stored in the node.
398-
/// Unsafe because the caller must ensure that the node is not the shared root.
399-
pub unsafe fn keys(&self) -> &[K] {
325+
pub fn keys(&self) -> &[K] {
400326
self.reborrow().into_key_slice()
401327
}
402328

403329
/// Borrows a view into the values stored in the node.
404-
/// Unsafe because the caller must ensure that the node is not the shared root.
405-
unsafe fn vals(&self) -> &[V] {
330+
fn vals(&self) -> &[V] {
406331
self.reborrow().into_val_slice()
407332
}
408333

@@ -416,7 +341,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
416341
pub fn ascend(
417342
self,
418343
) -> Result<Handle<NodeRef<BorrowType, K, V, marker::Internal>, marker::Edge>, Self> {
419-
let parent_as_leaf = self.as_header().parent as *const LeafNode<K, V>;
344+
let parent_as_leaf = self.as_leaf().parent as *const LeafNode<K, V>;
420345
if let Some(non_zero) = NonNull::new(parent_as_leaf as *mut _) {
421346
Ok(Handle {
422347
node: NodeRef {
@@ -425,7 +350,7 @@ impl<BorrowType, K, V, Type> NodeRef<BorrowType, K, V, Type> {
425350
root: self.root,
426351
_marker: PhantomData,
427352
},
428-
idx: unsafe { usize::from(*self.as_header().parent_idx.as_ptr()) },
353+
idx: unsafe { usize::from(*self.as_leaf().parent_idx.as_ptr()) },
429354
_marker: PhantomData,
430355
})
431356
} else {
@@ -464,7 +389,6 @@ impl<K, V> NodeRef<marker::Owned, K, V, marker::LeafOrInternal> {
464389
pub unsafe fn deallocate_and_ascend(
465390
self,
466391
) -> Option<Handle<NodeRef<marker::Owned, K, V, marker::Internal>, marker::Edge>> {
467-
assert!(!self.is_shared_root());
468392
let height = self.height;
469393
let node = self.node;
470394
let ret = self.ascend().ok();
@@ -507,41 +431,37 @@ impl<'a, K, V, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
507431
/// (header, keys and values), and this function exposes that.
508432
///
509433
/// Returns a raw ptr to avoid asserting exclusive access to the entire node.
510-
/// This also implies you can invoke this member on the shared root, but the resulting pointer
511-
/// might not be properly aligned and definitely would not allow accessing keys and values.
512434
fn as_leaf_mut(&mut self) -> *mut LeafNode<K, V> {
513435
self.node.as_ptr()
514436
}
515437

516-
/// Unsafe because the caller must ensure that the node is not the shared root.
517-
unsafe fn keys_mut(&mut self) -> &mut [K] {
518-
self.reborrow_mut().into_key_slice_mut()
438+
fn keys_mut(&mut self) -> &mut [K] {
439+
// SAFETY: the caller will not be able to call further methods on self
440+
// until the key slice reference is dropped, as we have unique access
441+
// for the lifetime of the borrow.
442+
unsafe { self.reborrow_mut().into_key_slice_mut() }
519443
}
520444

521-
/// Unsafe because the caller must ensure that the node is not the shared root.
522-
unsafe fn vals_mut(&mut self) -> &mut [V] {
523-
self.reborrow_mut().into_val_slice_mut()
445+
fn vals_mut(&mut self) -> &mut [V] {
446+
// SAFETY: the caller will not be able to call further methods on self
447+
// until the value slice reference is dropped, as we have unique access
448+
// for the lifetime of the borrow.
449+
unsafe { self.reborrow_mut().into_val_slice_mut() }
524450
}
525451
}
526452

527453
impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Immut<'a>, K, V, Type> {
528-
/// Unsafe because the caller must ensure that the node is not the shared root.
529-
unsafe fn into_key_slice(self) -> &'a [K] {
530-
debug_assert!(!self.is_shared_root());
531-
// We cannot be the shared root, so `as_leaf` is okay.
532-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len())
454+
fn into_key_slice(self) -> &'a [K] {
455+
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().keys), self.len()) }
533456
}
534457

535-
/// Unsafe because the caller must ensure that the node is not the shared root.
536-
unsafe fn into_val_slice(self) -> &'a [V] {
537-
debug_assert!(!self.is_shared_root());
538-
// We cannot be the shared root, so `as_leaf` is okay.
539-
slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len())
458+
fn into_val_slice(self) -> &'a [V] {
459+
unsafe { slice::from_raw_parts(MaybeUninit::first_ptr(&self.as_leaf().vals), self.len()) }
540460
}
541461

542-
/// Unsafe because the caller must ensure that the node is not the shared root.
543-
unsafe fn into_slices(self) -> (&'a [K], &'a [V]) {
544-
let k = ptr::read(&self);
462+
fn into_slices(self) -> (&'a [K], &'a [V]) {
463+
// SAFETY: equivalent to reborrow() except not requiring Type: 'a
464+
let k = unsafe { ptr::read(&self) };
545465
(k.into_key_slice(), self.into_val_slice())
546466
}
547467
}
@@ -553,37 +473,41 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef<marker::Mut<'a>, K, V, Type> {
553473
unsafe { &mut *(self.root as *mut Root<K, V>) }
554474
}
555475

556-
/// Unsafe because the caller must ensure that the node is not the shared root.
557-
unsafe fn into_key_slice_mut(mut self) -> &'a mut [K] {
558-
debug_assert!(!self.is_shared_root());
559-
// We cannot be the shared root, so `as_leaf_mut` is okay.
560-
slice::from_raw_parts_mut(
561-
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
562-
self.len(),
563-
)
476+
fn into_key_slice_mut(mut self) -> &'a mut [K] {
477+
// SAFETY: The keys of a node must always be initialized up to length.
478+
unsafe {
479+
slice::from_raw_parts_mut(
480+
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).keys),
481+
self.len(),
482+
)
483+
}
564484
}
565485

566-
/// Unsafe because the caller must ensure that the node is not the shared root.
567-
unsafe fn into_val_slice_mut(mut self) -> &'a mut [V] {
568-
debug_assert!(!self.is_shared_root());
569-
slice::from_raw_parts_mut(
570-
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
571-
self.len(),
572-
)
486+
fn into_val_slice_mut(mut self) -> &'a mut [V] {
487+
// SAFETY: The values of a node must always be initialized up to length.
488+
unsafe {
489+
slice::from_raw_parts_mut(
490+
MaybeUninit::first_ptr_mut(&mut (*self.as_leaf_mut()).vals),
491+
self.len(),
492+
)
493+
}
573494
}
574495

575-
/// Unsafe because the caller must ensure that the node is not the shared root.
576-
unsafe fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
577-
debug_assert!(!self.is_shared_root());
496+
fn into_slices_mut(mut self) -> (&'a mut [K], &'a mut [V]) {
578497
// We cannot use the getters here, because calling the second one
579498
// invalidates the reference returned by the first.
580499
// More precisely, it is the call to `len` that is the culprit,
581500
// because that creates a shared reference to the header, which *can*
582501
// overlap with the keys (and even the values, for ZST keys).
583502
let len = self.len();
584503
let leaf = self.as_leaf_mut();
585-
let keys = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len);
586-
let vals = slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len);
504+
// SAFETY: The keys and values of a node must always be initialized up to length.
505+
let keys = unsafe {
506+
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).keys), len)
507+
};
508+
let vals = unsafe {
509+
slice::from_raw_parts_mut(MaybeUninit::first_ptr_mut(&mut (*leaf).vals), len)
510+
};
587511
(keys, vals)
588512
}
589513
}
@@ -592,7 +516,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
592516
/// Adds a key/value pair the end of the node.
593517
pub fn push(&mut self, key: K, val: V) {
594518
assert!(self.len() < CAPACITY);
595-
debug_assert!(!self.is_shared_root());
596519

597520
let idx = self.len();
598521

@@ -607,7 +530,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Leaf> {
607530
/// Adds a key/value pair to the beginning of the node.
608531
pub fn push_front(&mut self, key: K, val: V) {
609532
assert!(self.len() < CAPACITY);
610-
debug_assert!(!self.is_shared_root());
611533

612534
unsafe {
613535
slice_insert(self.keys_mut(), 0, key);
@@ -624,7 +546,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
624546
pub fn push(&mut self, key: K, val: V, edge: Root<K, V>) {
625547
assert!(edge.height == self.height - 1);
626548
assert!(self.len() < CAPACITY);
627-
debug_assert!(!self.is_shared_root());
628549

629550
let idx = self.len();
630551

@@ -658,7 +579,6 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::Internal> {
658579
pub fn push_front(&mut self, key: K, val: V, edge: Root<K, V>) {
659580
assert!(edge.height == self.height - 1);
660581
assert!(self.len() < CAPACITY);
661-
debug_assert!(!self.is_shared_root());
662582

663583
unsafe {
664584
slice_insert(self.keys_mut(), 0, key);
@@ -744,8 +664,7 @@ impl<'a, K, V> NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal> {
744664
}
745665
}
746666

747-
/// Unsafe because the caller must ensure that the node is not the shared root.
748-
unsafe fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
667+
fn into_kv_pointers_mut(mut self) -> (*mut K, *mut V) {
749668
(self.keys_mut().as_mut_ptr(), self.vals_mut().as_mut_ptr())
750669
}
751670
}
@@ -904,7 +823,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge
904823
fn insert_fit(&mut self, key: K, val: V) -> *mut V {
905824
// Necessary for correctness, but in a private module
906825
debug_assert!(self.node.len() < CAPACITY);
907-
debug_assert!(!self.node.is_shared_root());
908826

909827
unsafe {
910828
slice_insert(self.node.keys_mut(), self.idx, key);
@@ -1081,7 +999,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
1081999
/// - All the key/value pairs to the right of this handle are put into a newly
10821000
/// allocated node.
10831001
pub fn split(mut self) -> (NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, K, V, Root<K, V>) {
1084-
assert!(!self.node.is_shared_root());
10851002
unsafe {
10861003
let mut new_node = Box::new(LeafNode::new());
10871004

@@ -1113,7 +1030,6 @@ impl<'a, K, V> Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::KV>
11131030
pub fn remove(
11141031
mut self,
11151032
) -> (Handle<NodeRef<marker::Mut<'a>, K, V, marker::Leaf>, marker::Edge>, K, V) {
1116-
assert!(!self.node.is_shared_root());
11171033
unsafe {
11181034
let k = slice_remove(self.node.keys_mut(), self.idx);
11191035
let v = slice_remove(self.node.vals_mut(), self.idx);

‎src/liballoc/collections/btree/search.rs

+7-10
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,16 @@ where
6767
Q: Ord,
6868
K: Borrow<Q>,
6969
{
70-
// This function is defined over all borrow types (immutable, mutable, owned),
71-
// and may be called on the shared root in each case.
70+
// This function is defined over all borrow types (immutable, mutable, owned).
7271
// Using `keys()` is fine here even if BorrowType is mutable, as all we return
7372
// is an index -- not a reference.
7473
let len = node.len();
75-
if len > 0 {
76-
let keys = unsafe { node.keys() }; // safe because a non-empty node cannot be the shared root
77-
for (i, k) in keys.iter().enumerate() {
78-
match key.cmp(k.borrow()) {
79-
Ordering::Greater => {}
80-
Ordering::Equal => return (i, true),
81-
Ordering::Less => return (i, false),
82-
}
74+
let keys = node.keys();
75+
for (i, k) in keys.iter().enumerate() {
76+
match key.cmp(k.borrow()) {
77+
Ordering::Greater => {}
78+
Ordering::Equal => return (i, true),
79+
Ordering::Less => return (i, false),
8380
}
8481
}
8582
(len, false)

‎src/liballoc/tests/btree/map.rs

+2-9
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ fn test_basic_large() {
6767
#[test]
6868
fn test_basic_small() {
6969
let mut map = BTreeMap::new();
70-
// Empty, shared root:
70+
// Empty, root is absent (None):
7171
assert_eq!(map.remove(&1), None);
7272
assert_eq!(map.len(), 0);
7373
assert_eq!(map.get(&1), None);
@@ -123,7 +123,7 @@ fn test_basic_small() {
123123
assert_eq!(map.values().collect::<Vec<_>>(), vec![&4]);
124124
assert_eq!(map.remove(&2), Some(4));
125125

126-
// Empty but private root:
126+
// Empty but root is owned (Some(...)):
127127
assert_eq!(map.len(), 0);
128128
assert_eq!(map.get(&1), None);
129129
assert_eq!(map.get_mut(&1), None);
@@ -263,13 +263,6 @@ fn test_iter_mut_mutation() {
263263
do_test_iter_mut_mutation::<Align32>(144);
264264
}
265265

266-
#[test]
267-
fn test_into_key_slice_with_shared_root_past_bounds() {
268-
let mut map: BTreeMap<Align32, ()> = BTreeMap::new();
269-
assert_eq!(map.get(&Align32(1)), None);
270-
assert_eq!(map.get_mut(&Align32(1)), None);
271-
}
272-
273266
#[test]
274267
fn test_values_mut() {
275268
let mut a = BTreeMap::new();

‎src/test/debuginfo/pretty-std-collections.rs

+17-7
Original file line numberDiff line numberDiff line change
@@ -17,35 +17,43 @@
1717
// gdb-command: print btree_set
1818
// gdb-check:$1 = BTreeSet<i32>(len: 15) = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14}
1919

20+
// gdb-command: print empty_btree_set
21+
// gdb-check:$2 = BTreeSet<i32>(len: 0)
22+
2023
// gdb-command: print btree_map
21-
// gdb-check:$2 = BTreeMap<i32, i32>(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
24+
// gdb-check:$3 = BTreeMap<i32, i32>(len: 15) = {[0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7, [8] = 8, [9] = 9, [10] = 10, [11] = 11, [12] = 12, [13] = 13, [14] = 14}
25+
26+
// gdb-command: print empty_btree_map
27+
// gdb-check:$4 = BTreeMap<i32, u32>(len: 0)
2228

2329
// gdb-command: print vec_deque
24-
// gdb-check:$3 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
30+
// gdb-check:$5 = VecDeque<i32>(len: 3, cap: 8) = {5, 3, 7}
2531

2632
// gdb-command: print vec_deque2
27-
// gdb-check:$4 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
33+
// gdb-check:$6 = VecDeque<i32>(len: 7, cap: 8) = {2, 3, 4, 5, 6, 7, 8}
2834

2935
#![allow(unused_variables)]
30-
use std::collections::BTreeSet;
3136
use std::collections::BTreeMap;
37+
use std::collections::BTreeSet;
3238
use std::collections::VecDeque;
3339

34-
3540
fn main() {
36-
3741
// BTreeSet
3842
let mut btree_set = BTreeSet::new();
3943
for i in 0..15 {
4044
btree_set.insert(i);
4145
}
4246

47+
let mut empty_btree_set: BTreeSet<i32> = BTreeSet::new();
48+
4349
// BTreeMap
4450
let mut btree_map = BTreeMap::new();
4551
for i in 0..15 {
4652
btree_map.insert(i, i);
4753
}
4854

55+
let mut empty_btree_map: BTreeMap<i32, u32> = BTreeMap::new();
56+
4957
// VecDeque
5058
let mut vec_deque = VecDeque::new();
5159
vec_deque.push_back(5);
@@ -63,4 +71,6 @@ fn main() {
6371
zzz(); // #break
6472
}
6573

66-
fn zzz() { () }
74+
fn zzz() {
75+
()
76+
}

0 commit comments

Comments
 (0)
Please sign in to comment.