Skip to content

BTree: clarify order guarantee provided by searches #83147

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 4, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions library/alloc/src/collections/btree/map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,9 @@ impl<K, V> BTreeMap<K, V> {
///
/// Panics if range `start > end`.
/// Panics if range `start == end` and both bounds are `Excluded`.
/// May panic if the [`Ord`] implementation of type `T` is ill-defined,
/// either because it does not form a total order or because it does not
/// correspond to the [`Ord`] implementation of type `K`.
///
/// # Examples
///
Expand Down Expand Up @@ -1061,6 +1064,9 @@ impl<K, V> BTreeMap<K, V> {
///
/// Panics if range `start > end`.
/// Panics if range `start == end` and both bounds are `Excluded`.
/// May panic if the [`Ord`] implementation of type `T` is ill-defined,
/// either because it does not form a total order or because it does not
/// correspond to the [`Ord`] implementation of type `K`.
///
/// # Examples
///
Expand Down
15 changes: 11 additions & 4 deletions library/alloc/src/collections/btree/navigate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,18 @@ impl<BorrowType, K, V> LeafRange<BorrowType, K, V> {

impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::LeafOrInternal> {
/// Finds the distinct leaf edges delimiting a specified range in a tree.
/// Returns either a pair of different handles into the same tree or a pair
/// of empty options.
///
/// If such distinct edges exist, returns them in ascending order, meaning
/// that a non-zero number of calls to `next_unchecked` on the `front` of
/// the result and/or calls to `next_back_unchecked` on the `back` of the
/// result will eventually reach the same edge.
///
/// If there are no such edges, i.e., if the tree contains no key within
/// the range, returns a pair of empty options.
///
/// # Safety
/// Unless `BorrowType` is `Immut`, do not use the duplicate handles to
/// visit the same KV twice.
/// Unless `BorrowType` is `Immut`, do not use the handles to visit the same
/// KV twice.
unsafe fn find_leaf_edges_spanning_range<Q: ?Sized, R>(
self,
range: R,
Expand Down
15 changes: 12 additions & 3 deletions library/alloc/src/collections/btree/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,13 +68,18 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
/// of the range is different from the edge matching the upper bound, i.e.,
/// the nearest node that has at least one key contained in the range.
///
/// If found, returns an `Ok` with that node, the pair of edge indices in it
/// delimiting the range, and the corresponding pair of bounds for
/// continuing the search in the child nodes, in case the node is internal.
/// If found, returns an `Ok` with that node, the strictly ascending pair of
/// edge indices in the node delimiting the range, and the corresponding
/// pair of bounds for continuing the search in the child nodes, in case
/// the node is internal.
///
/// If not found, returns an `Err` with the leaf edge matching the entire
/// range.
///
/// As a diagnostic service, panics if the range specifies impossible bounds
/// or if it witnesses that the `Ord` implementation of `Q` violates total
/// order or is inconsistent with the `Ord` implementation of `K`.
///
/// The result is meaningful only if the tree is ordered by key.
pub fn search_tree_for_bifurcation<'r, Q: ?Sized, R>(
mut self,
Expand Down Expand Up @@ -115,6 +120,10 @@ impl<BorrowType: marker::BorrowType, K, V> NodeRef<BorrowType, K, V, marker::Lea
let (lower_edge_idx, lower_child_bound) = self.find_lower_bound_index(lower_bound);
let (upper_edge_idx, upper_child_bound) = self.find_upper_bound_index(upper_bound);
if lower_edge_idx > upper_edge_idx {
// Since we already checked the range bounds, this can only
// happen if `Q: Ord` does not implement a total order or does
// not correspond to the `K: Ord` implementation that is used
// while populating the tree.
panic!("Ord is ill-defined in BTreeMap range")
}
if lower_edge_idx < upper_edge_idx {
Expand Down