From f9ce5c2e4383598620764dba166360b835b9905d Mon Sep 17 00:00:00 2001 From: Alan Egerton Date: Sat, 31 Dec 2022 01:14:02 +0000 Subject: [PATCH] Initial release --- Cargo.toml | 45 ++ README.md | 83 ++++ src/btree/append.rs | 13 +- src/btree/borrow/tests.rs | 2 +- src/btree/dedup_sorted_iter.rs | 17 +- src/btree/fix.rs | 2 +- src/btree/map.rs | 826 +++++++++++++++++--------------- src/btree/map/entry.rs | 196 ++++---- src/btree/map/tests.rs | 407 +++++++++++----- src/btree/mem.rs | 13 +- src/btree/merge_iter.rs | 10 +- src/btree/navigate.rs | 50 +- src/btree/node.rs | 261 ++++++++-- src/btree/node/tests.rs | 6 +- src/btree/remove.rs | 2 +- src/btree/search.rs | 109 +++-- src/btree/set.rs | 818 +++++++++++++++++-------------- src/btree/set/tests.rs | 382 +++++++++------ src/btree/set_val.rs | 1 + src/btree/split.rs | 16 +- src/btree/testing/crash_test.rs | 8 +- src/btree/testing/ord_chaos.rs | 12 +- src/lib.rs | 306 ++++++++++++ 23 files changed, 2325 insertions(+), 1260 deletions(-) create mode 100644 README.md diff --git a/Cargo.toml b/Cargo.toml index 0cd42ff..72ac747 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,6 +3,51 @@ name = "copse" version = "0.1.0" license = "MIT OR Apache-2.0" repository = "https://github.com/eggyal/copse.git" +description = "Direct ports of the standard library's B-Tree collections, but that sort according to a specified comparator rather than the `Ord` trait" edition = "2021" +keywords = ["b-tree", "collections", "map", "set", "runtime"] +categories = ["data-structures", "no-std"] + +[features] +unstable = [ + "allocator_api", + "bound_map", + "core_intrinsics", + "dropck_eyepatch", + "error_in_core", + "exact_size_is_empty", + "exclusive_range_pattern", + "extend_one", + "hasher_prefixfree_extras", + "map_try_insert", + "maybe_uninit_slice", + "new_uninit", + "rustc_attrs", + "slice_ptr_get", + "specialization", + "type_alias_impl_trait", +] +allocator_api = [] +bound_map = [] +core_intrinsics = [] +dropck_eyepatch = [] +error_in_core = [] +exact_size_is_empty = [] +exclusive_range_pattern = [] +extend_one = [] +hasher_prefixfree_extras = [] +map_try_insert = [] +maybe_uninit_slice = [] +new_uninit = [] +rustc_attrs = [] +slice_ptr_get = [] +specialization = [] +type_alias_impl_trait = [] +std = [] [dependencies] +cfg-if = "1.0.0" + +[package.metadata.docs.rs] +all-features = true +rustdoc-args = ["--cfg", "docsrs"] diff --git a/README.md b/README.md new file mode 100644 index 0000000..0764984 --- /dev/null +++ b/README.md @@ -0,0 +1,83 @@ +Direct ports of the standard library's [`BTreeMap`][std::collections::BTreeMap] and +[`BTreeSet`][std::collections::BTreeSet] collections, but which sort according to a specified +[`Comparator`] rather than relying upon the [`Ord`] trait. + +This is primarily useful when the [`Comparator`] is not defined until runtime, and therefore +cannot be provided as an [`Ord`] implementation for any type. + +# Lookup keys +In the standard library's collections, certain lookups can be performed using a key of type +`&Q` where the collection's storage key type `K` implements [`Borrow`]; for example, one +can use `&str` keys to perform lookups into collections that store `String` keys. This is +possible because the [`Borrow`] trait stipulates that borrowed values must preserve [`Ord`] +order. + +However, copse's collections do not use the [`Ord`] trait; instead, lookups can only ever +be performed using the [`Comparator`] supplied upon collection creation. This comparator +can only compare values of type `&T` for which it was defined, and hence such type must be +reachable from any key type `&Q` used to perform lookups in the collection. copse ensures +this via its [`Sortable`] trait, which will typically be implemented by the stored key type +`K`; its [`State`][Sortable::State] associated type then specifies the `T` in which +comparisons will be performed, and values of type `&Q` can be used as lookup keys provided +that `Q: Borrow`. + +For example, a collection using a `Comparator` comparator can store keys of type +`String` because `String` implements `Sortable`; moreover, lookups can be +performed using keys of type `&str` because `str` implements `Borrow` (due to the +reflexive blanket implementation). + +Implementations of [`Sortable`] are provided for primitive and some common standard library +types, but storing keys of other foreign types may require newtyping. + +# Function item types +In addition to the type parameters familiar from the standard library collections, copse's +collections are additionally parameterised by the type of the [`Comparator`]. If the +comparator type is not explicitly named, it defaults to the type of the [`Ord::cmp`] +function for `K::State`. As noted in the documentation of the [`CmpFn`] type alias, this +is only a zero-sized function item type if the unstable `type_alias_impl_trait` feature is +enabled; otherwise it is a function pointer type, with ensuing size and indirect call +implications. Collections built using the zero-sized function item type can still be +used in stable code, however; just not using the default type parameter. For example: + +```rust +let mut ord_map = BTreeMap::new(Ord::cmp); +``` + +However, naming this type carries the usual problems associated with anonymous types like +closures; in certain situations you may be able to use `impl Comparator` for the type +parameter, but in other situations (in stable code) the function pointer may be +unavoidable. + +# Crate feature flags +This crate defines a number of feature flags, none of which are enabled by default: + +* the `std` feature provides [`Sortable`] implementations for some libstd types + that are not available in libcore + liballoc, namely [`OsString`] and [`PathBuf`]; + +* the `unstable` feature enables all other crate features, each of which enables the + like-named unstable compiler feature that is used by the standard library's collection + implementations (and which therefore require a nightly compiler)—most such behaviour + is polyfilled when the features are disabled, so they should rarely be required, but + they are nevertheless included to ease tracking of the stdlib implementations. + + The most visible differences to library users will be: + * `allocator_api` enables the `new_in` methods for use of custom allocators; + * `specialization` adds the collection type name to some panic messages; + * `type_alias_impl_trait`, as mentioned above, ensures that the *default* + [`Comparator`] type parameter for the collections is the zero-sized function + item type of the `K::State::cmp` function. + +[std::collections::BTreeMap]: https://doc.rust-lang.org/std/collections/struct.BTreeMap.html +[std::collections::BTreeSet]: https://doc.rust-lang.org/std/collections/struct.BTreeSet.html +[`Ord`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html +[`Borrow`]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html +[`Borrow`]: https://doc.rust-lang.org/std/borrow/trait.Borrow.html +[`Ord::cmp`]: https://doc.rust-lang.org/std/cmp/trait.Ord.html#tymethod.cmp +[`OsString`]: https://doc.rust-lang.org/std/ffi/os_str/struct.OsString.html +[`PathBuf`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html + +[`CmpFn`]: https://docs.rs/copse/latest/copse/type.CmpFn.html +[`Comparator`]: https://docs.rs/copse/latest/copse/trait.Comparator.html +[`Comparator`]: https://docs.rs/copse/latest/copse/trait.Comparator.html +[`Sortable`]: https://docs.rs/copse/latest/copse/trait.Sortable.html +[Sortable::State]: https://docs.rs/copse/latest/copse/trait.Sortable.html#associatedtype.State \ No newline at end of file diff --git a/src/btree/append.rs b/src/btree/append.rs index b6989af..c9bc352 100644 --- a/src/btree/append.rs +++ b/src/btree/append.rs @@ -1,6 +1,6 @@ use super::merge_iter::MergeIterInner; use super::node::{self, Root}; -use core::alloc::Allocator; +use crate::{Allocator, Comparator}; use core::iter::FusedIterator; impl Root { @@ -20,13 +20,13 @@ impl Root { left: I, right: I, length: &mut usize, + comparator: impl Comparator<(K, V)>, alloc: A, ) where - K: Ord, I: Iterator + FusedIterator, { // We prepare to merge `left` and `right` into a sorted sequence in linear time. - let iter = MergeIter(MergeIterInner::new(left, right)); + let iter = MergeIter(MergeIterInner::new(left, right), comparator); // Meanwhile, we build a tree from the sorted sequence in linear time. self.bulk_push(iter, length, alloc) @@ -91,17 +91,18 @@ impl Root { } // An iterator for merging two sorted sequences into one -struct MergeIter>(MergeIterInner); +struct MergeIter>(MergeIterInner, C); -impl Iterator for MergeIter +impl Iterator for MergeIter where + C: Comparator<(K, V)>, I: Iterator + FusedIterator, { type Item = (K, V); /// If two keys are equal, returns the key-value pair from the right source. fn next(&mut self) -> Option<(K, V)> { - let (a_next, b_next) = self.0.nexts(|a: &(K, V), b: &(K, V)| K::cmp(&a.0, &b.0)); + let (a_next, b_next) = self.0.nexts(&self.1); b_next.or(a_next) } } diff --git a/src/btree/borrow/tests.rs b/src/btree/borrow/tests.rs index 56a8434..50a09f8 100644 --- a/src/btree/borrow/tests.rs +++ b/src/btree/borrow/tests.rs @@ -3,7 +3,7 @@ use super::DormantMutRef; #[test] fn test_borrow() { let mut data = 1; - let mut stack = vec![]; + let mut stack = alloc::vec![]; let mut rr = &mut data; for factor in [2, 3, 7].iter() { let (r, dormant_r) = DormantMutRef::new(rr); diff --git a/src/btree/dedup_sorted_iter.rs b/src/btree/dedup_sorted_iter.rs index 285814c..f8a66f6 100644 --- a/src/btree/dedup_sorted_iter.rs +++ b/src/btree/dedup_sorted_iter.rs @@ -1,32 +1,37 @@ use core::iter::Peekable; +use crate::{Sortable, Comparator}; + /// A iterator for deduping the key of a sorted iterator. /// When encountering the duplicated key, only the last key-value pair is yielded. /// /// Used by [`BTreeMap::bulk_build_from_sorted_iter`][1]. /// /// [1]: crate::collections::BTreeMap::bulk_build_from_sorted_iter -pub struct DedupSortedIter +pub struct DedupSortedIter<'a, K, V, C, I> where I: Iterator, { iter: Peekable, + comparator: &'a C, } -impl DedupSortedIter +impl<'a, K, V, C, I> DedupSortedIter<'a, K, V, C, I> where I: Iterator, { - pub fn new(iter: I) -> Self { + pub fn new(iter: I, comparator: &'a C) -> Self { Self { iter: iter.peekable(), + comparator, } } } -impl Iterator for DedupSortedIter +impl Iterator for DedupSortedIter<'_, K, V, C, I> where - K: Eq, + K: Sortable, + C: Comparator, I: Iterator, { type Item = (K, V); @@ -43,7 +48,7 @@ where None => return Some(next), }; - if next.0 != peeked.0 { + if self.comparator.cmp(next.0.borrow(), peeked.0.borrow()).is_ne() { return Some(next); } } diff --git a/src/btree/fix.rs b/src/btree/fix.rs index 2693727..793a033 100644 --- a/src/btree/fix.rs +++ b/src/btree/fix.rs @@ -1,6 +1,6 @@ use super::map::MIN_LEN; use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef, Root}; -use core::alloc::Allocator; +use crate::Allocator; impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { /// Stocks up a possibly underfull node by merging with or stealing from a diff --git a/src/btree/map.rs b/src/btree/map.rs index 5b2e7cd..1b3c269 100644 --- a/src/btree/map.rs +++ b/src/btree/map.rs @@ -1,4 +1,5 @@ -use crate::vec::Vec; +use alloc::vec::Vec; +use cfg_if::cfg_if; use core::borrow::Borrow; use core::cmp::Ordering; use core::fmt::{self, Debug}; @@ -9,7 +10,7 @@ use core::mem::{self, ManuallyDrop}; use core::ops::{Index, RangeBounds}; use core::ptr; -use crate::alloc::{Allocator, Global}; +use crate::{Allocator, Global, Comparator}; use super::borrow::DormantMutRef; use super::dedup_sorted_iter::DedupSortedIter; @@ -17,10 +18,11 @@ use super::navigate::{LazyLeafRange, LeafRange}; use super::node::{self, marker, ForceResult::*, Handle, NodeRef, Root}; use super::search::SearchResult::*; use super::set_val::SetValZST; +use crate::{Sortable, MinCmpFn, StdOrd}; mod entry; -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub use entry::{Entry, OccupiedEntry, OccupiedError, VacantEntry}; use Entry::*; @@ -65,7 +67,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// however, performance is excellent. /// /// It is a logic error for a key to be modified in such a way that the key's ordering relative to -/// any other key, as determined by the [`Ord`] trait, changes while it is in the map. This is +/// any other key, as determined by the comparator function, changes while it is in the map. This is /// normally only possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code. /// The behavior resulting from such a logic error is not specified, but will be encapsulated to the /// `BTreeMap` that observed the logic error and not result in undefined behavior. This could @@ -82,11 +84,11 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// # Examples /// /// ``` -/// use std::collections::BTreeMap; +/// use copse::BTreeMap; /// /// // type inference lets us omit an explicit type signature (which /// // would be `BTreeMap<&str, &str>` in this example). -/// let mut movie_reviews = BTreeMap::new(); +/// let mut movie_reviews = BTreeMap::default(); /// /// // review some movies. /// movie_reviews.insert("Office Space", "Deals with real issues in the workplace."); @@ -124,7 +126,7 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// A `BTreeMap` with a known list of items can be initialized from an array: /// /// ``` -/// use std::collections::BTreeMap; +/// use copse::BTreeMap; /// /// let solar_distance = BTreeMap::from([ /// ("Mercury", 0.4), @@ -140,11 +142,11 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// [`Entry API`]: BTreeMap::entry /// /// ``` -/// use std::collections::BTreeMap; +/// use copse::BTreeMap; /// /// // type inference lets us omit an explicit type signature (which /// // would be `BTreeMap<&str, u8>` in this example). -/// let mut player_stats = BTreeMap::new(); +/// let mut player_stats = BTreeMap::default(); /// /// fn random_stat_buff() -> u8 { /// // could actually return some random value here - let's just return @@ -166,26 +168,41 @@ pub(super) const MIN_LEN: usize = node::MIN_LEN_AFTER_SPLIT; /// // modify an entry before an insert with in-place mutation /// player_stats.entry("mana").and_modify(|mana| *mana += 200).or_insert(100); /// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")] -#[rustc_insignificant_dtor] +// #[stable(feature = "rust1", since = "1.0.0")] +// #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeMap")] +#[cfg_attr(feature = "rustc_attrs", rustc_insignificant_dtor)] pub struct BTreeMap< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C = MinCmpFn, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { root: Option>, length: usize, + pub(super) comparator: C, /// `ManuallyDrop` to control drop order (needs to be dropped after all the nodes). pub(super) alloc: ManuallyDrop, // For dropck; the `Box` avoids making the `Unpin` impl more strict than before - _marker: PhantomData>, + _marker: PhantomData>, } -#[stable(feature = "btree_drop", since = "1.7.0")] -unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTreeMap { - fn drop(&mut self) { - drop(unsafe { ptr::read(self) }.into_iter()) +// #[stable(feature = "btree_drop", since = "1.7.0")] +cfg_if! { + if #[cfg(feature = "dropck_eyepatch")] { + unsafe impl<#[may_dangle] K, #[may_dangle] V, C, A: Allocator + Clone> Drop + for BTreeMap + { + fn drop(&mut self) { + drop(unsafe { ptr::read(self) }.into_iter()) + } + } + } else { + impl Drop for BTreeMap { + fn drop(&mut self) { + drop(unsafe { ptr::read(self) }.into_iter()) + } + } } } @@ -193,8 +210,8 @@ unsafe impl<#[may_dangle] K, #[may_dangle] V, A: Allocator + Clone> Drop for BTr // (The bounds of the automatic `UnwindSafe` implementation have been like this since Rust 1.50.) // Maybe we can fix it nonetheless with a crater run, or if the `UnwindSafe` // traits are deprecated, or disarmed (no longer causing hard errors) in the future. -#[stable(feature = "btree_unwindsafe", since = "1.64.0")] -impl core::panic::UnwindSafe for BTreeMap +// #[stable(feature = "btree_unwindsafe", since = "1.64.0")] +impl core::panic::UnwindSafe for BTreeMap where A: core::panic::UnwindSafe, K: core::panic::RefUnwindSafe, @@ -202,13 +219,14 @@ where { } -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for BTreeMap { - fn clone(&self) -> BTreeMap { - fn clone_subtree<'a, K: Clone, V: Clone, A: Allocator + Clone>( +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeMap { + fn clone(&self) -> BTreeMap { + fn clone_subtree<'a, K: Clone, V: Clone, C: Clone, A: Allocator + Clone>( node: NodeRef, K, V, marker::LeafOrInternal>, + comparator: &C, alloc: A, - ) -> BTreeMap + ) -> BTreeMap where K: 'a, V: 'a, @@ -218,6 +236,7 @@ impl Clone for BTreeMap { let mut out_tree = BTreeMap { root: Some(Root::new(alloc.clone())), length: 0, + comparator: comparator.clone(), alloc: ManuallyDrop::new(alloc), _marker: PhantomData, }; @@ -243,7 +262,7 @@ impl Clone for BTreeMap { } Internal(internal) => { let mut out_tree = - clone_subtree(internal.first_edge().descend(), alloc.clone()); + clone_subtree(internal.first_edge().descend(), comparator, alloc.clone()); { let out_root = out_tree.root.as_mut().unwrap(); @@ -255,7 +274,7 @@ impl Clone for BTreeMap { let k = (*k).clone(); let v = (*v).clone(); - let subtree = clone_subtree(in_edge.descend(), alloc.clone()); + let subtree = clone_subtree(in_edge.descend(), comparator, alloc.clone()); // We can't destructure subtree directly // because BTreeMap implements Drop @@ -281,26 +300,28 @@ impl Clone for BTreeMap { } if self.is_empty() { - BTreeMap::new_in((*self.alloc).clone()) + BTreeMap::new_in(self.comparator.clone(), (*self.alloc).clone()) } else { clone_subtree( self.root.as_ref().unwrap().reborrow(), + &self.comparator, (*self.alloc).clone(), ) // unwrap succeeds because not empty } } } -impl super::Recover for BTreeMap +impl super::Recover for BTreeMap where - K: Borrow + Ord, - Q: Ord, + K: Sortable, + Q: Borrow, + C: Comparator, { type Key = K; fn get(&self, key: &Q) -> Option<&K> { let root_node = self.root.as_ref()?.reborrow(); - match root_node.search_tree(key) { + match root_node.search_tree(key, &self.comparator) { Found(handle) => Some(handle.into_kv().0), GoDown(_) => None, } @@ -309,7 +330,7 @@ where fn take(&mut self, key: &Q) -> Option { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); - match root_node.search_tree(key) { + match root_node.search_tree(key, &map.comparator) { Found(handle) => Some( OccupiedEntry { handle, @@ -330,7 +351,7 @@ where .root .get_or_insert_with(|| Root::new((*map.alloc).clone())) .borrow_mut(); - match root_node.search_tree::(&key) { + match root_node.search_tree(&key, &map.comparator) { Found(mut kv) => Some(mem::replace(kv.key_mut(), key)), GoDown(handle) => { VacantEntry { @@ -354,13 +375,13 @@ where /// /// [`iter`]: BTreeMap::iter #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, K: 'a, V: 'a> { range: LazyLeafRange, K, V>, length: usize, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Iter<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() @@ -373,7 +394,8 @@ impl fmt::Debug for Iter<'_, K, V> { /// documentation for more. /// /// [`iter_mut`]: BTreeMap::iter_mut -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] +#[must_use = "iterators are lazy and do nothing unless consumed"] pub struct IterMut<'a, K: 'a, V: 'a> { range: LazyLeafRange, K, V>, length: usize, @@ -382,8 +404,7 @@ pub struct IterMut<'a, K: 'a, V: 'a> { _marker: PhantomData<&'a mut (K, V)>, } -#[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for IterMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let range = Iter { @@ -401,12 +422,13 @@ impl fmt::Debug for IterMut<'_, K, V> { /// /// [`into_iter`]: IntoIterator::into_iter /// [`IntoIterator`]: core::iter::IntoIterator -#[stable(feature = "rust1", since = "1.0.0")] -#[rustc_insignificant_dtor] +// #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(feature = "rustc_attrs", rustc_insignificant_dtor)] pub struct IntoIter< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { range: LazyLeafRange, length: usize, @@ -425,7 +447,7 @@ impl IntoIter { } } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl Debug for IntoIter { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.iter()).finish() @@ -439,12 +461,12 @@ impl Debug for IntoIter { /// /// [`keys`]: BTreeMap::keys #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Keys<'a, K, V> { inner: Iter<'a, K, V>, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Keys<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() @@ -458,12 +480,12 @@ impl fmt::Debug for Keys<'_, K, V> { /// /// [`values`]: BTreeMap::values #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Values<'a, K, V> { inner: Iter<'a, K, V>, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Values<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list().entries(self.clone()).finish() @@ -477,12 +499,12 @@ impl fmt::Debug for Values<'_, K, V> { /// /// [`values_mut`]: BTreeMap::values_mut #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "map_values_mut", since = "1.10.0")] +// #[stable(feature = "map_values_mut", since = "1.10.0")] pub struct ValuesMut<'a, K, V> { inner: IterMut<'a, K, V>, } -#[stable(feature = "map_values_mut", since = "1.10.0")] +// #[stable(feature = "map_values_mut", since = "1.10.0")] impl fmt::Debug for ValuesMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() @@ -498,12 +520,12 @@ impl fmt::Debug for ValuesMut<'_, K, V> { /// /// [`into_keys`]: BTreeMap::into_keys #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub struct IntoKeys { inner: IntoIter, } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl fmt::Debug for IntoKeys { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() @@ -519,16 +541,17 @@ impl fmt::Debug for IntoKeys { /// /// [`into_values`]: BTreeMap::into_values #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub struct IntoValues< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { inner: IntoIter, } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl fmt::Debug for IntoValues { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_list() @@ -544,15 +567,15 @@ impl fmt::Debug for IntoValues /// /// [`range`]: BTreeMap::range #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, K: 'a, V: 'a> { inner: LeafRange, K, V>, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Range<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_list().entries(self.clone()).finish() + f.debug_list().entries(*self).finish() } } @@ -563,7 +586,7 @@ impl fmt::Debug for Range<'_, K, V> { /// /// [`range_mut`]: BTreeMap::range_mut #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] pub struct RangeMut<'a, K: 'a, V: 'a> { inner: LeafRange, K, V>, @@ -571,7 +594,7 @@ pub struct RangeMut<'a, K: 'a, V: 'a> { _marker: PhantomData<&'a mut (K, V)>, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for RangeMut<'_, K, V> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { let range = Range { @@ -581,8 +604,8 @@ impl fmt::Debug for RangeMut<'_, K, V> { } } -impl BTreeMap { - /// Makes a new, empty `BTreeMap`. +impl BTreeMap { + /// Makes a new, empty `BTreeMap` ordered by the given `comparator`. /// /// Does not allocate anything on its own. /// @@ -591,27 +614,28 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// /// // entries can now be inserted into the empty map /// map.insert(1, "a"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] #[must_use] - pub const fn new() -> BTreeMap { + pub const fn new(comparator: C) -> BTreeMap { BTreeMap { root: None, length: 0, + comparator, alloc: ManuallyDrop::new(Global), _marker: PhantomData, } } } -impl BTreeMap { +impl BTreeMap { /// Clears the map, removing all elements. /// /// # Examples @@ -619,53 +643,74 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, "a"); /// a.clear(); /// assert!(a.is_empty()); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) where C: Clone { // avoid moving the allocator mem::drop(BTreeMap { root: mem::replace(&mut self.root, None), length: mem::replace(&mut self.length, 0), + comparator: self.comparator.clone(), alloc: self.alloc.clone(), _marker: PhantomData, }); } - /// Makes a new empty BTreeMap with a reasonable choice for B. - /// - /// # Examples - /// - /// Basic usage: - /// - /// ``` - /// # #![feature(allocator_api)] - /// # #![feature(btreemap_alloc)] - /// use std::collections::BTreeMap; - /// use std::alloc::Global; - /// - /// let mut map = BTreeMap::new_in(Global); - /// - /// // entries can now be inserted into the empty map - /// map.insert(1, "a"); - /// ``` - #[unstable(feature = "btreemap_alloc", issue = "32838")] - pub fn new_in(alloc: A) -> BTreeMap { - BTreeMap { - root: None, - length: 0, - alloc: ManuallyDrop::new(alloc), - _marker: PhantomData, + cfg_if! { + if #[cfg(feature = "allocator_api")] { + /// Makes a new empty BTreeMap with a reasonable choice for B, ordered by the given `comparator`. + /// + /// # Examples + /// + /// Basic usage: + /// + /// ``` + /// #![feature(allocator_api)] + /// + /// use copse::BTreeMap; + /// use std::alloc::Global; + /// + /// let mut map = BTreeMap::new_in(Ord::cmp, Global); + /// + /// // entries can now be inserted into the empty map + /// map.insert(1, "a"); + /// ``` + // #[unstable(feature = "btreemap_alloc", issue = "32838")] + #[cfg_attr(docsrs, doc(cfg(feature = "allocator_api")))] + pub fn new_in(comparator: C, alloc: A) -> BTreeMap { + BTreeMap { + root: None, + length: 0, + comparator, + alloc: ManuallyDrop::new(alloc), + _marker: PhantomData, + } + } + } else { + pub(crate) fn new_in(comparator: C, alloc: A) -> Self { + BTreeMap { + root: None, + length: 0, + comparator, + alloc: ManuallyDrop::new(alloc), + _marker: PhantomData, + } + } } } } -impl BTreeMap { +impl BTreeMap +where + K: Sortable, + C: Comparator, +{ /// Returns a reference to the value corresponding to the key. /// /// The key may be any borrowed form of the map's key type, but the ordering @@ -676,21 +721,20 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// assert_eq!(map.get(&1), Some(&"a")); /// assert_eq!(map.get(&2), None); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self, key: &Q) -> Option<&V> where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { let root_node = self.root.as_ref()?.reborrow(); - match root_node.search_tree(key) { + match root_node.search_tree(key, &self.comparator) { Found(handle) => Some(handle.into_kv().1), GoDown(_) => None, } @@ -704,21 +748,20 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// assert_eq!(map.get_key_value(&1), Some((&1, &"a"))); /// assert_eq!(map.get_key_value(&2), None); /// ``` - #[stable(feature = "map_get_key_value", since = "1.40.0")] + // #[stable(feature = "map_get_key_value", since = "1.40.0")] pub fn get_key_value(&self, k: &Q) -> Option<(&K, &V)> where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { let root_node = self.root.as_ref()?.reborrow(); - match root_node.search_tree(k) { + match root_node.search_tree(k, &self.comparator) { Found(handle) => Some(handle.into_kv()), GoDown(_) => None, } @@ -732,19 +775,16 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// assert_eq!(map.first_key_value(), None); /// map.insert(1, "b"); /// map.insert(2, "a"); /// assert_eq!(map.first_key_value(), Some((&1, &"b"))); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn first_key_value(&self) -> Option<(&K, &V)> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn first_key_value(&self) -> Option<(&K, &V)> { let root_node = self.root.as_ref()?.reborrow(); root_node .first_leaf_edge() @@ -759,9 +799,9 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// if let Some(mut entry) = map.first_entry() { @@ -772,11 +812,8 @@ impl BTreeMap { /// assert_eq!(*map.get(&1).unwrap(), "first"); /// assert_eq!(*map.get(&2).unwrap(), "b"); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn first_entry(&mut self) -> Option> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn first_entry(&mut self) -> Option> { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); let kv = root_node.first_leaf_edge().right_kv().ok()?; @@ -796,9 +833,9 @@ impl BTreeMap { /// Draining elements in ascending order, while keeping a usable map each iteration. /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// while let Some((key, _val)) = map.pop_first() { @@ -806,11 +843,8 @@ impl BTreeMap { /// } /// assert!(map.is_empty()); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn pop_first(&mut self) -> Option<(K, V)> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_first(&mut self) -> Option<(K, V)> { self.first_entry().map(|entry| entry.remove_entry()) } @@ -822,18 +856,15 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "b"); /// map.insert(2, "a"); /// assert_eq!(map.last_key_value(), Some((&2, &"a"))); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn last_key_value(&self) -> Option<(&K, &V)> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn last_key_value(&self) -> Option<(&K, &V)> { let root_node = self.root.as_ref()?.reborrow(); root_node .last_leaf_edge() @@ -848,9 +879,9 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// if let Some(mut entry) = map.last_entry() { @@ -861,11 +892,8 @@ impl BTreeMap { /// assert_eq!(*map.get(&1).unwrap(), "a"); /// assert_eq!(*map.get(&2).unwrap(), "last"); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn last_entry(&mut self) -> Option> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn last_entry(&mut self) -> Option> { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); let kv = root_node.last_leaf_edge().left_kv().ok()?; @@ -885,9 +913,9 @@ impl BTreeMap { /// Draining elements in descending order, while keeping a usable map each iteration. /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// map.insert(2, "b"); /// while let Some((key, _val)) = map.pop_last() { @@ -895,11 +923,8 @@ impl BTreeMap { /// } /// assert!(map.is_empty()); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn pop_last(&mut self) -> Option<(K, V)> - where - K: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_last(&mut self) -> Option<(K, V)> { self.last_entry().map(|entry| entry.remove_entry()) } @@ -913,18 +938,17 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// assert_eq!(map.contains_key(&1), true); /// assert_eq!(map.contains_key(&2), false); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn contains_key(&self, key: &Q) -> bool where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { self.get(key).is_some() } @@ -939,9 +963,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// if let Some(x) = map.get_mut(&1) { /// *x = "b"; @@ -949,14 +973,13 @@ impl BTreeMap { /// assert_eq!(map[&1], "b"); /// ``` // See `get` for implementation notes, this is basically a copy-paste with mut's added - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { let root_node = self.root.as_mut()?.borrow_mut(); - match root_node.search_tree(key) { + match root_node.search_tree(key, &self.comparator) { Found(handle) => Some(handle.into_val_mut()), GoDown(_) => None, } @@ -978,9 +1001,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// assert_eq!(map.insert(37, "a"), None); /// assert_eq!(map.is_empty(), false); /// @@ -988,11 +1011,8 @@ impl BTreeMap { /// assert_eq!(map.insert(37, "c"), Some("b")); /// assert_eq!(map[&37], "c"); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, key: K, value: V) -> Option - where - K: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, key: K, value: V) -> Option { match self.entry(key) { Occupied(mut entry) => Some(entry.insert(value)), Vacant(entry) => { @@ -1013,11 +1033,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// #![feature(map_try_insert)] - /// - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// assert_eq!(map.try_insert(37, "a").unwrap(), &"a"); /// /// let err = map.try_insert(37, "b").unwrap_err(); @@ -1025,11 +1043,12 @@ impl BTreeMap { /// assert_eq!(err.entry.get(), &"a"); /// assert_eq!(err.value, "b"); /// ``` - #[unstable(feature = "map_try_insert", issue = "82766")] - pub fn try_insert(&mut self, key: K, value: V) -> Result<&mut V, OccupiedError<'_, K, V, A>> - where - K: Ord, - { + // #[unstable(feature = "map_try_insert", issue = "82766")] + pub fn try_insert( + &mut self, + key: K, + value: V, + ) -> Result<&mut V, OccupiedError<'_, K, V, C, A>> { match self.entry(key) { Occupied(entry) => Err(OccupiedError { entry, value }), Vacant(entry) => Ok(entry.insert(value)), @@ -1047,18 +1066,17 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// assert_eq!(map.remove(&1), Some("a")); /// assert_eq!(map.remove(&1), None); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, key: &Q) -> Option where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { self.remove_entry(key).map(|(_, v)| v) } @@ -1074,22 +1092,21 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(1, "a"); /// assert_eq!(map.remove_entry(&1), Some((1, "a"))); /// assert_eq!(map.remove_entry(&1), None); /// ``` - #[stable(feature = "btreemap_remove_entry", since = "1.45.0")] + // #[stable(feature = "btreemap_remove_entry", since = "1.45.0")] pub fn remove_entry(&mut self, key: &Q) -> Option<(K, V)> where - K: Borrow + Ord, - Q: Ord, + Q: Borrow, { let (map, dormant_map) = DormantMutRef::new(self); let root_node = map.root.as_mut()?.borrow_mut(); - match root_node.search_tree(key) { + match root_node.search_tree(key, &map.comparator) { Found(handle) => Some( OccupiedEntry { handle, @@ -1111,7 +1128,7 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// /// let mut map: BTreeMap = (0..8).map(|x| (x, x*10)).collect(); /// // Keep only the elements with even-numbered keys. @@ -1119,10 +1136,9 @@ impl BTreeMap { /// assert!(map.into_iter().eq(vec![(0, 0), (2, 20), (4, 40), (6, 60)])); /// ``` #[inline] - #[stable(feature = "btree_retain", since = "1.53.0")] + // #[stable(feature = "btree_retain", since = "1.53.0")] pub fn retain(&mut self, mut f: F) where - K: Ord, F: FnMut(&K, &mut V) -> bool, { self.drain_filter(|k, v| !f(k, v)); @@ -1136,14 +1152,14 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, "a"); /// a.insert(2, "b"); /// a.insert(3, "c"); // Note: Key (3) also present in b. /// - /// let mut b = BTreeMap::new(); + /// let mut b = BTreeMap::default(); /// b.insert(3, "d"); // Note: Key (3) also present in a. /// b.insert(4, "e"); /// b.insert(5, "f"); @@ -1159,11 +1175,11 @@ impl BTreeMap { /// assert_eq!(a[&4], "e"); /// assert_eq!(a[&5], "f"); /// ``` - #[stable(feature = "btree_append", since = "1.11.0")] + // #[stable(feature = "btree_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) where - K: Ord, A: Clone, + C: Clone, { // Do we have to append anything at all? if other.is_empty() { @@ -1176,8 +1192,10 @@ impl BTreeMap { return; } - let self_iter = mem::replace(self, Self::new_in((*self.alloc).clone())).into_iter(); - let other_iter = mem::replace(other, Self::new_in((*self.alloc).clone())).into_iter(); + let self_iter = + mem::replace(self, Self::new_in(self.comparator.clone(), (*self.alloc).clone())).into_iter(); + let other_iter = + mem::replace(other, Self::new_in(self.comparator.clone(), (*self.alloc).clone())).into_iter(); let root = self .root .get_or_insert_with(|| Root::new((*self.alloc).clone())); @@ -1185,6 +1203,7 @@ impl BTreeMap { self_iter, other_iter, &mut self.length, + |a: &(K, V), b: &(K, V)| self.comparator.cmp(a.0.borrow(), b.0.borrow()), (*self.alloc).clone(), ) } @@ -1206,28 +1225,27 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// use std::ops::Bound::Included; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(3, "a"); /// map.insert(5, "b"); /// map.insert(8, "c"); - /// for (&key, &value) in map.range((Included(&4), Included(&8))) { + /// for (&key, &value) in map.range::((Included(&4), Included(&8))) { /// println!("{key}: {value}"); /// } /// assert_eq!(Some((&5, &"b")), map.range(4..).next()); /// ``` - #[stable(feature = "btree_range", since = "1.17.0")] + // #[stable(feature = "btree_range", since = "1.17.0")] pub fn range(&self, range: R) -> Range<'_, K, V> where - T: Ord, - K: Borrow + Ord, + T: Borrow, R: RangeBounds, { if let Some(root) = &self.root { Range { - inner: root.reborrow().range_search(range), + inner: root.reborrow().range_search(&self.comparator, range), } } else { Range { @@ -1253,7 +1271,7 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// /// let mut map: BTreeMap<&str, i32> = /// [("Alice", 0), ("Bob", 0), ("Carol", 0), ("Cheryl", 0)].into(); @@ -1264,16 +1282,15 @@ impl BTreeMap { /// println!("{name} => {balance}"); /// } /// ``` - #[stable(feature = "btree_range", since = "1.17.0")] + // #[stable(feature = "btree_range", since = "1.17.0")] pub fn range_mut(&mut self, range: R) -> RangeMut<'_, K, V> where - T: Ord, - K: Borrow + Ord, + T: Borrow, R: RangeBounds, { if let Some(root) = &mut self.root { RangeMut { - inner: root.borrow_valmut().range_search(range), + inner: root.borrow_valmut().range_search(&self.comparator, range), _marker: PhantomData, } } else { @@ -1291,9 +1308,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut count: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut count: BTreeMap<&str, usize> = BTreeMap::default(); /// /// // count the number of occurrences of letters in the vec /// for x in ["a", "b", "a", "c", "a", "b"] { @@ -1304,11 +1321,8 @@ impl BTreeMap { /// assert_eq!(count["b"], 2); /// assert_eq!(count["c"], 1); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn entry(&mut self, key: K) -> Entry<'_, K, V, A> - where - K: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn entry(&mut self, key: K) -> Entry<'_, K, V, C, A> { let (map, dormant_map) = DormantMutRef::new(self); match map.root { None => Vacant(VacantEntry { @@ -1318,7 +1332,7 @@ impl BTreeMap { alloc: (*map.alloc).clone(), _marker: PhantomData, }), - Some(ref mut root) => match root.borrow_mut().search_tree(&key) { + Some(ref mut root) => match root.borrow_mut().search_tree(&key, &map.comparator) { Found(handle) => Occupied(OccupiedEntry { handle, dormant_map, @@ -1344,9 +1358,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, "a"); /// a.insert(2, "b"); /// a.insert(3, "c"); @@ -1365,27 +1379,29 @@ impl BTreeMap { /// assert_eq!(b[&17], "d"); /// assert_eq!(b[&41], "e"); /// ``` - #[stable(feature = "btree_split_off", since = "1.11.0")] - pub fn split_off(&mut self, key: &Q) -> Self + // #[stable(feature = "btree_split_off", since = "1.11.0")] + pub fn split_off(&mut self, key: &Q) -> Self where - K: Borrow + Ord, + Q: Borrow, A: Clone, + C: Clone, { if self.is_empty() { - return Self::new_in((*self.alloc).clone()); + return Self::new_in(self.comparator.clone(), (*self.alloc).clone()); } let total_num = self.len(); let left_root = self.root.as_mut().unwrap(); // unwrap succeeds because not empty - let right_root = left_root.split_off(key, (*self.alloc).clone()); + let right_root = left_root.split_off(key, &self.comparator, (*self.alloc).clone()); - let (new_left_len, right_len) = Root::calc_split_length(total_num, &left_root, &right_root); + let (new_left_len, right_len) = Root::calc_split_length(total_num, left_root, &right_root); self.length = new_left_len; BTreeMap { root: Some(right_root), length: right_len, + comparator: self.comparator.clone(), alloc: self.alloc.clone(), _marker: PhantomData, } @@ -1414,8 +1430,7 @@ impl BTreeMap { /// Splitting a map into even and odd keys, reusing the original map: /// /// ``` - /// #![feature(btree_drain_filter)] - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// /// let mut map: BTreeMap = (0..8).map(|x| (x, x)).collect(); /// let evens: BTreeMap<_, _> = map.drain_filter(|k, _v| k % 2 == 0).collect(); @@ -1423,20 +1438,16 @@ impl BTreeMap { /// assert_eq!(evens.keys().copied().collect::>(), [0, 2, 4, 6]); /// assert_eq!(odds.keys().copied().collect::>(), [1, 3, 5, 7]); /// ``` - #[unstable(feature = "btree_drain_filter", issue = "70530")] + // #[unstable(feature = "btree_drain_filter", issue = "70530")] pub fn drain_filter(&mut self, pred: F) -> DrainFilter<'_, K, V, F, A> where - K: Ord, F: FnMut(&K, &mut V) -> bool, { let (inner, alloc) = self.drain_filter_inner(); DrainFilter { pred, inner, alloc } } - pub(super) fn drain_filter_inner(&mut self) -> (DrainFilterInner<'_, K, V>, A) - where - K: Ord, - { + pub(super) fn drain_filter_inner(&mut self) -> (DrainFilterInner<'_, K, V>, A) { if let Some(root) = self.root.as_mut() { let (root, dormant_root) = DormantMutRef::new(root); let front = root.borrow_mut().first_leaf_edge(); @@ -1460,6 +1471,29 @@ impl BTreeMap { } } + /// Makes a `BTreeMap` from a sorted iterator. + pub(crate) fn bulk_build_from_sorted_iter(iter: I, comparator: C, alloc: A) -> BTreeMap + where + I: IntoIterator, + { + let mut root = Root::new(alloc.clone()); + let mut length = 0; + root.bulk_push( + DedupSortedIter::new(iter.into_iter(), &comparator), + &mut length, + alloc.clone(), + ); + BTreeMap { + root: Some(root), + length, + comparator, + alloc: ManuallyDrop::new(alloc), + _marker: PhantomData, + } + } +} + +impl BTreeMap { /// Creates a consuming iterator visiting all the keys, in sorted order. /// The map cannot be used after calling this. /// The iterator element type is `K`. @@ -1467,9 +1501,9 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(2, "b"); /// a.insert(1, "a"); /// @@ -1477,7 +1511,7 @@ impl BTreeMap { /// assert_eq!(keys, [1, 2]); /// ``` #[inline] - #[stable(feature = "map_into_keys_values", since = "1.54.0")] + // #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub fn into_keys(self) -> IntoKeys { IntoKeys { inner: self.into_iter(), @@ -1491,9 +1525,9 @@ impl BTreeMap { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, "hello"); /// a.insert(2, "goodbye"); /// @@ -1501,37 +1535,16 @@ impl BTreeMap { /// assert_eq!(values, ["hello", "goodbye"]); /// ``` #[inline] - #[stable(feature = "map_into_keys_values", since = "1.54.0")] + // #[stable(feature = "map_into_keys_values", since = "1.54.0")] pub fn into_values(self) -> IntoValues { IntoValues { inner: self.into_iter(), } } - - /// Makes a `BTreeMap` from a sorted iterator. - pub(crate) fn bulk_build_from_sorted_iter(iter: I, alloc: A) -> Self - where - K: Ord, - I: IntoIterator, - { - let mut root = Root::new(alloc.clone()); - let mut length = 0; - root.bulk_push( - DedupSortedIter::new(iter.into_iter()), - &mut length, - alloc.clone(), - ); - BTreeMap { - root: Some(root), - length, - alloc: ManuallyDrop::new(alloc), - _marker: PhantomData, - } - } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V, C, A: Allocator + Clone> IntoIterator for &'a BTreeMap { type Item = (&'a K, &'a V); type IntoIter = Iter<'a, K, V>; @@ -1540,7 +1553,7 @@ impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a BTreeMap { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { type Item = (&'a K, &'a V); @@ -1570,10 +1583,10 @@ impl<'a, K: 'a, V: 'a> Iterator for Iter<'a, K, V> { } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, K, V> {} -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> { if self.length == 0 { @@ -1585,14 +1598,14 @@ impl<'a, K: 'a, V: 'a> DoubleEndedIterator for Iter<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, K, V> { fn len(&self) -> usize { self.length } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Iter<'_, K, V> { fn clone(&self) -> Self { Iter { @@ -1602,8 +1615,8 @@ impl Clone for Iter<'_, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a mut BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, K, V, C, A: Allocator + Clone> IntoIterator for &'a mut BTreeMap { type Item = (&'a K, &'a mut V); type IntoIter = IterMut<'a, K, V>; @@ -1612,7 +1625,7 @@ impl<'a, K, V, A: Allocator + Clone> IntoIterator for &'a mut BTreeMap } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for IterMut<'a, K, V> { type Item = (&'a K, &'a mut V); @@ -1642,7 +1655,7 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { if self.length == 0 { @@ -1654,14 +1667,14 @@ impl<'a, K, V> DoubleEndedIterator for IterMut<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IterMut<'_, K, V> { fn len(&self) -> usize { self.length } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IterMut<'_, K, V> {} impl<'a, K, V> IterMut<'a, K, V> { @@ -1675,8 +1688,8 @@ impl<'a, K, V> IterMut<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeMap { type Item = (K, V); type IntoIter = IntoIter; @@ -1700,7 +1713,7 @@ impl IntoIterator for BTreeMap { } } -#[stable(feature = "btree_drop", since = "1.7.0")] +// #[stable(feature = "btree_drop", since = "1.7.0")] impl Drop for IntoIter { fn drop(&mut self) { struct DropGuard<'a, K, V, A: Allocator + Clone>(&'a mut IntoIter); @@ -1758,7 +1771,7 @@ impl IntoIter { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = (K, V); @@ -1772,7 +1785,7 @@ impl Iterator for IntoIter { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option<(K, V)> { // SAFETY: we consume the dying handle immediately. @@ -1781,17 +1794,17 @@ impl DoubleEndedIterator for IntoIter { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.length } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Keys<'a, K, V> { type Item = &'a K; @@ -1816,24 +1829,24 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> DoubleEndedIterator for Keys<'a, K, V> { fn next_back(&mut self) -> Option<&'a K> { self.inner.next_back().map(|(k, _)| k) } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Keys<'_, K, V> { fn len(&self) -> usize { self.inner.len() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Keys<'_, K, V> {} -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Keys<'_, K, V> { fn clone(&self) -> Self { Keys { @@ -1842,7 +1855,7 @@ impl Clone for Keys<'_, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> Iterator for Values<'a, K, V> { type Item = &'a V; @@ -1859,24 +1872,24 @@ impl<'a, K, V> Iterator for Values<'a, K, V> { } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, K, V> DoubleEndedIterator for Values<'a, K, V> { fn next_back(&mut self) -> Option<&'a V> { self.inner.next_back().map(|(_, v)| v) } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Values<'_, K, V> { fn len(&self) -> usize { self.inner.len() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Values<'_, K, V> {} -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Values<'_, K, V> { fn clone(&self) -> Self { Values { @@ -1886,13 +1899,14 @@ impl Clone for Values<'_, K, V> { } /// An iterator produced by calling `drain_filter` on BTreeMap. -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] pub struct DrainFilter< 'a, K, V, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > where F: 'a + FnMut(&K, &mut V) -> bool, { @@ -1915,7 +1929,7 @@ pub(super) struct DrainFilterInner<'a, K, V> { cur_leaf_edge: Option, K, V, marker::Leaf>, marker::Edge>>, } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl Drop for DrainFilter<'_, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, @@ -1925,7 +1939,7 @@ where } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl fmt::Debug for DrainFilter<'_, K, V, F> where K: fmt::Debug, @@ -1939,7 +1953,7 @@ where } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl Iterator for DrainFilter<'_, K, V, F, A> where F: FnMut(&K, &mut V) -> bool, @@ -1999,10 +2013,10 @@ impl<'a, K, V> DrainFilterInner<'a, K, V> { } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl FusedIterator for DrainFilter<'_, K, V, F> where F: FnMut(&K, &mut V) -> bool {} -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> Iterator for Range<'a, K, V> { type Item = (&'a K, &'a V); @@ -2023,7 +2037,7 @@ impl<'a, K, V> Iterator for Range<'a, K, V> { } } -#[stable(feature = "map_values_mut", since = "1.10.0")] +// #[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { type Item = &'a mut V; @@ -2040,24 +2054,24 @@ impl<'a, K, V> Iterator for ValuesMut<'a, K, V> { } } -#[stable(feature = "map_values_mut", since = "1.10.0")] +// #[stable(feature = "map_values_mut", since = "1.10.0")] impl<'a, K, V> DoubleEndedIterator for ValuesMut<'a, K, V> { fn next_back(&mut self) -> Option<&'a mut V> { self.inner.next_back().map(|(_, v)| v) } } -#[stable(feature = "map_values_mut", since = "1.10.0")] +// #[stable(feature = "map_values_mut", since = "1.10.0")] impl ExactSizeIterator for ValuesMut<'_, K, V> { fn len(&self) -> usize { self.inner.len() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for ValuesMut<'_, K, V> {} -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl Iterator for IntoKeys { type Item = K; @@ -2082,24 +2096,24 @@ impl Iterator for IntoKeys { } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl DoubleEndedIterator for IntoKeys { fn next_back(&mut self) -> Option { self.inner.next_back().map(|(k, _)| k) } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoKeys { fn len(&self) -> usize { self.inner.len() } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl FusedIterator for IntoKeys {} -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl Iterator for IntoValues { type Item = V; @@ -2116,43 +2130,43 @@ impl Iterator for IntoValues { } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl DoubleEndedIterator for IntoValues { fn next_back(&mut self) -> Option { self.inner.next_back().map(|(_, v)| v) } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl ExactSizeIterator for IntoValues { fn len(&self) -> usize { self.inner.len() } } -#[stable(feature = "map_into_keys_values", since = "1.54.0")] +// #[stable(feature = "map_into_keys_values", since = "1.54.0")] impl FusedIterator for IntoValues {} -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for Range<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next_back_checked() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Range<'_, K, V> {} -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl Clone for Range<'_, K, V> { fn clone(&self) -> Self { - Range { - inner: self.inner.clone(), - } + *self } } -#[stable(feature = "btree_range", since = "1.17.0")] +impl Copy for Range<'_, K, V> {} + +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> Iterator for RangeMut<'a, K, V> { type Item = (&'a K, &'a mut V); @@ -2173,33 +2187,41 @@ impl<'a, K, V> Iterator for RangeMut<'a, K, V> { } } -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, K, V> DoubleEndedIterator for RangeMut<'a, K, V> { fn next_back(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next_back_checked() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for RangeMut<'_, K, V> {} -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator<(K, V)> for BTreeMap { - fn from_iter>(iter: T) -> BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator<(K, V)> for BTreeMap> +where + K: Sortable, + K::State: Ord, +{ + fn from_iter>(iter: T) -> BTreeMap> { let mut inputs: Vec<_> = iter.into_iter().collect(); if inputs.is_empty() { - return BTreeMap::new(); + return BTreeMap::new(K::State::cmp_fn()); } // use stable sort to preserve the insertion order. - inputs.sort_by(|a, b| a.0.cmp(&b.0)); - BTreeMap::bulk_build_from_sorted_iter(inputs, Global) + inputs.sort_by(|a, b| Ord::cmp(a.0.borrow(), b.0.borrow())); + BTreeMap::bulk_build_from_sorted_iter(inputs, K::State::cmp_fn(), Global) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend<(K, V)> for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Extend<(K, V)> for BTreeMap +where + K: Sortable, + C: Comparator, +{ #[inline] fn extend>(&mut self, iter: T) { iter.into_iter().for_each(move |(k, v)| { @@ -2207,82 +2229,98 @@ impl Extend<(K, V)> for BTreeMap { }); } + #[cfg(feature = "extend_one")] #[inline] fn extend_one(&mut self, (k, v): (K, V)) { self.insert(k, v); } } -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, K: Ord + Copy, V: Copy, A: Allocator + Clone> Extend<(&'a K, &'a V)> - for BTreeMap +// #[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, K: Copy, V: Copy, C, A: Allocator + Clone> Extend<(&'a K, &'a V)> for BTreeMap +where + K: Sortable, + C: Comparator, { fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().map(|(&key, &value)| (key, value))); } + #[cfg(feature = "extend_one")] #[inline] fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) { self.insert(k, v); } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Hash for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeMap { fn hash(&self, state: &mut H) { - state.write_length_prefix(self.len()); + cfg_if! { + if #[cfg(feature = "hasher_prefixfree_extras")] { + state.write_length_prefix(self.len()); + } else { + state.write_usize(self.len()); + } + } + for elt in self { elt.hash(state); } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for BTreeMap { - /// Creates an empty `BTreeMap`. - fn default() -> BTreeMap { - BTreeMap::new() +// #[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeMap> +where + K: Sortable, + K::State: Ord, +{ + /// Creates an empty `BTreeMap`, ordered by the `Ord` trait. + fn default() -> BTreeMap> { + BTreeMap::new(K::State::cmp_fn()) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for BTreeMap { - fn eq(&self, other: &BTreeMap) -> bool { +// #[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeMap { + fn eq(&self, other: &BTreeMap) -> bool { self.len() == other.len() && self.iter().zip(other).all(|(a, b)| a == b) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for BTreeMap {} +// #[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeMap {} -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeMap { #[inline] - fn partial_cmp(&self, other: &BTreeMap) -> Option { + fn partial_cmp(&self, other: &BTreeMap) -> Option { self.iter().partial_cmp(other.iter()) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeMap { #[inline] - fn cmp(&self, other: &BTreeMap) -> Ordering { + fn cmp(&self, other: &BTreeMap) -> Ordering { self.iter().cmp(other.iter()) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Debug for BTreeMap { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeMap { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_map().entries(self.iter()).finish() } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Index<&Q> for BTreeMap +// #[stable(feature = "rust1", since = "1.0.0")] +impl Index<&Q> for BTreeMap where - K: Borrow + Ord, - Q: Ord, + K: Sortable, + Q: Borrow, + C: Comparator, { type Output = V; @@ -2297,12 +2335,16 @@ where } } -#[stable(feature = "std_collections_from_array", since = "1.56.0")] -impl From<[(K, V); N]> for BTreeMap { +// #[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[(K, V); N]> for BTreeMap> +where + K: Sortable, + K::State: Ord, +{ /// Converts a `[(K, V); N]` into a `BTreeMap<(K, V)>`. /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// /// let map1 = BTreeMap::from([(1, 2), (3, 4)]); /// let map2: BTreeMap<_, _> = [(1, 2), (3, 4)].into(); @@ -2310,16 +2352,16 @@ impl From<[(K, V); N]> for BTreeMap { /// ``` fn from(mut arr: [(K, V); N]) -> Self { if N == 0 { - return BTreeMap::new(); + return BTreeMap::new(K::State::cmp_fn()); } // use stable sort to preserve the insertion order. - arr.sort_by(|a, b| a.0.cmp(&b.0)); - BTreeMap::bulk_build_from_sorted_iter(arr, Global) + arr.sort_by(|a, b| Ord::cmp(a.0.borrow(),b.0.borrow())); + BTreeMap::bulk_build_from_sorted_iter(arr, K::State::cmp_fn(), Global) } } -impl BTreeMap { +impl BTreeMap { /// Gets an iterator over the entries of the map, sorted by key. /// /// # Examples @@ -2327,9 +2369,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map = BTreeMap::new(); + /// let mut map = BTreeMap::default(); /// map.insert(3, "c"); /// map.insert(2, "b"); /// map.insert(1, "a"); @@ -2341,7 +2383,7 @@ impl BTreeMap { /// let (first_key, first_value) = map.iter().next().unwrap(); /// assert_eq!((*first_key, *first_value), (1, "a")); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter<'_, K, V> { if let Some(root) = &self.root { let full_range = root.reborrow().full_range(); @@ -2365,7 +2407,7 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// /// let mut map = BTreeMap::from([ /// ("a", 1), @@ -2380,7 +2422,7 @@ impl BTreeMap { /// } /// } /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { if let Some(root) = &mut self.root { let full_range = root.borrow_valmut().full_range(); @@ -2406,16 +2448,16 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(2, "b"); /// a.insert(1, "a"); /// /// let keys: Vec<_> = a.keys().cloned().collect(); /// assert_eq!(keys, [1, 2]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn keys(&self) -> Keys<'_, K, V> { Keys { inner: self.iter() } } @@ -2427,16 +2469,16 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, "hello"); /// a.insert(2, "goodbye"); /// /// let values: Vec<&str> = a.values().cloned().collect(); /// assert_eq!(values, ["hello", "goodbye"]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn values(&self) -> Values<'_, K, V> { Values { inner: self.iter() } } @@ -2448,9 +2490,9 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// a.insert(1, String::from("hello")); /// a.insert(2, String::from("goodbye")); /// @@ -2462,7 +2504,7 @@ impl BTreeMap { /// assert_eq!(values, [String::from("hello!"), /// String::from("goodbye!")]); /// ``` - #[stable(feature = "map_values_mut", since = "1.10.0")] + // #[stable(feature = "map_values_mut", since = "1.10.0")] pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { ValuesMut { inner: self.iter_mut(), @@ -2476,20 +2518,20 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// assert_eq!(a.len(), 0); /// a.insert(1, "a"); /// assert_eq!(a.len(), 1); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable( - feature = "const_btree_len", - issue = "71835", - implied_by = "const_btree_new" - )] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_unstable( + // feature = "const_btree_len", + // issue = "71835", + // implied_by = "const_btree_new" + // )] pub const fn len(&self) -> usize { self.length } @@ -2501,20 +2543,20 @@ impl BTreeMap { /// Basic usage: /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut a = BTreeMap::new(); + /// let mut a = BTreeMap::default(); /// assert!(a.is_empty()); /// a.insert(1, "a"); /// assert!(!a.is_empty()); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable( - feature = "const_btree_len", - issue = "71835", - implied_by = "const_btree_new" - )] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_unstable( + // feature = "const_btree_len", + // issue = "71835", + // implied_by = "const_btree_new" + // )] pub const fn is_empty(&self) -> bool { self.len() == 0 } diff --git a/src/btree/map/entry.rs b/src/btree/map/entry.rs index a040e3b..d49f9c1 100644 --- a/src/btree/map/entry.rs +++ b/src/btree/map/entry.rs @@ -2,7 +2,7 @@ use core::fmt::{self, Debug}; use core::marker::PhantomData; use core::mem; -use crate::alloc::{Allocator, Global}; +use crate::{Allocator, Global}; use super::super::borrow::DormantMutRef; use super::super::node::{marker, Handle, NodeRef}; @@ -15,25 +15,33 @@ use Entry::*; /// This `enum` is constructed from the [`entry`] method on [`BTreeMap`]. /// /// [`entry`]: BTreeMap::entry -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")] +// #[stable(feature = "rust1", since = "1.0.0")] +// #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeEntry")] pub enum Entry< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { /// A vacant entry. - #[stable(feature = "rust1", since = "1.0.0")] - Vacant(#[stable(feature = "rust1", since = "1.0.0")] VacantEntry<'a, K, V, A>), + // #[stable(feature = "rust1", since = "1.0.0")] + Vacant( + // #[stable(feature = "rust1", since = "1.0.0")] + VacantEntry<'a, K, V, C, A>, + ), /// An occupied entry. - #[stable(feature = "rust1", since = "1.0.0")] - Occupied(#[stable(feature = "rust1", since = "1.0.0")] OccupiedEntry<'a, K, V, A>), + // #[stable(feature = "rust1", since = "1.0.0")] + Occupied( + // #[stable(feature = "rust1", since = "1.0.0")] + OccupiedEntry<'a, K, V, C, A>, + ), } -#[stable(feature = "debug_btree_map", since = "1.12.0")] -impl Debug for Entry<'_, K, V, A> { +// #[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for Entry<'_, K, V, C, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { Vacant(ref v) => f.debug_tuple("Entry").field(v).finish(), @@ -44,17 +52,19 @@ impl Debug for Entry<'_, K, V, A /// A view into a vacant entry in a `BTreeMap`. /// It is part of the [`Entry`] enum. -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct VacantEntry< 'a, K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { pub(super) key: K, /// `None` for a (empty) map without root pub(super) handle: Option, K, V, marker::Leaf>, marker::Edge>>, - pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. pub(super) alloc: A, @@ -63,8 +73,8 @@ pub struct VacantEntry< pub(super) _marker: PhantomData<&'a mut (K, V)>, } -#[stable(feature = "debug_btree_map", since = "1.12.0")] -impl Debug for VacantEntry<'_, K, V, A> { +// #[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for VacantEntry<'_, K, V, C, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("VacantEntry").field(self.key()).finish() } @@ -72,15 +82,17 @@ impl Debug for VacantEntry<'_, K, V, A> /// A view into an occupied entry in a `BTreeMap`. /// It is part of the [`Entry`] enum. -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct OccupiedEntry< 'a, K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { pub(super) handle: Handle, K, V, marker::LeafOrInternal>, marker::KV>, - pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, + pub(super) dormant_map: DormantMutRef<'a, BTreeMap>, /// The BTreeMap will outlive this IntoIter so we don't care about drop order for `alloc`. pub(super) alloc: A, @@ -89,8 +101,8 @@ pub struct OccupiedEntry< pub(super) _marker: PhantomData<&'a mut (K, V)>, } -#[stable(feature = "debug_btree_map", since = "1.12.0")] -impl Debug for OccupiedEntry<'_, K, V, A> { +// #[stable(feature = "debug_btree_map", since = "1.12.0")] +impl Debug for OccupiedEntry<'_, K, V, C, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedEntry") .field("key", self.key()) @@ -102,16 +114,16 @@ impl Debug for OccupiedEntry<'_, /// The error returned by [`try_insert`](BTreeMap::try_insert) when the key already exists. /// /// Contains the occupied entry, and the value that was not inserted. -#[unstable(feature = "map_try_insert", issue = "82766")] -pub struct OccupiedError<'a, K: 'a, V: 'a, A: Allocator + Clone = Global> { +// #[unstable(feature = "map_try_insert", issue = "82766")] +pub struct OccupiedError<'a, K: 'a, V: 'a, C, A: Allocator + Clone = Global> { /// The entry in the map that was already occupied. - pub entry: OccupiedEntry<'a, K, V, A>, + pub entry: OccupiedEntry<'a, K, V, C, A>, /// The value which was not inserted, because the entry was already occupied. pub value: V, } -#[unstable(feature = "map_try_insert", issue = "82766")] -impl Debug for OccupiedError<'_, K, V, A> { +// #[unstable(feature = "map_try_insert", issue = "82766")] +impl Debug for OccupiedError<'_, K, V, C, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OccupiedError") .field("key", self.entry.key()) @@ -121,9 +133,9 @@ impl Debug for OccupiedError<'_, } } -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display - for OccupiedError<'a, K, V, A> +// #[unstable(feature = "map_try_insert", issue = "82766")] +impl<'a, K: Debug, V: Debug, C, A: Allocator + Clone> fmt::Display + for OccupiedError<'a, K, V, C, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( @@ -136,9 +148,10 @@ impl<'a, K: Debug + Ord, V: Debug, A: Allocator + Clone> fmt::Display } } -#[unstable(feature = "map_try_insert", issue = "82766")] -impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error - for crate::collections::btree_map::OccupiedError<'a, K, V> +// #[unstable(feature = "map_try_insert", issue = "82766")] +#[cfg(feature = "error_in_core")] +impl<'a, K: core::fmt::Debug, V: core::fmt::Debug, C> core::error::Error + for OccupiedError<'a, K, V, C> { #[allow(deprecated)] fn description(&self) -> &str { @@ -146,21 +159,21 @@ impl<'a, K: core::fmt::Debug + Ord, V: core::fmt::Debug> core::error::Error } } -impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { +impl<'a, K, V, C, A: Allocator + Clone> Entry<'a, K, V, C, A> { /// Ensures a value is in the entry by inserting the default if empty, and returns /// a mutable reference to the value in the entry. /// /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert(self, default: V) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -174,16 +187,16 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, String> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, String> = BTreeMap::default(); /// let s = "hoho".to_string(); /// /// map.entry("poneyland").or_insert_with(|| s); /// /// assert_eq!(map["poneyland"], "hoho".to_string()); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn or_insert_with V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -201,16 +214,16 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// /// map.entry("poneyland").or_insert_with_key(|key| key.chars().count()); /// /// assert_eq!(map["poneyland"], 9); /// ``` #[inline] - #[stable(feature = "or_insert_with_key", since = "1.50.0")] + // #[stable(feature = "or_insert_with_key", since = "1.50.0")] pub fn or_insert_with_key V>(self, default: F) -> &'a mut V { match self { Occupied(entry) => entry.into_mut(), @@ -226,12 +239,12 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` - #[stable(feature = "map_entry_keys", since = "1.10.0")] + // #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { match *self { Occupied(ref entry) => entry.key(), @@ -245,9 +258,9 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// /// map.entry("poneyland") /// .and_modify(|e| { *e += 1 }) @@ -259,7 +272,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { /// .or_insert(42); /// assert_eq!(map["poneyland"], 43); /// ``` - #[stable(feature = "entry_and_modify", since = "1.26.0")] + // #[stable(feature = "entry_and_modify", since = "1.26.0")] pub fn and_modify(self, f: F) -> Self where F: FnOnce(&mut V), @@ -274,17 +287,17 @@ impl<'a, K: Ord, V, A: Allocator + Clone> Entry<'a, K, V, A> { } } -impl<'a, K: Ord, V: Default, A: Allocator + Clone> Entry<'a, K, V, A> { - #[stable(feature = "entry_or_default", since = "1.28.0")] +impl<'a, K, V: Default, C, A: Allocator + Clone> Entry<'a, K, V, C, A> { + // #[stable(feature = "entry_or_default", since = "1.28.0")] /// Ensures a value is in the entry by inserting the default value if empty, /// and returns a mutable reference to the value in the entry. /// /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, Option> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, Option> = BTreeMap::default(); /// map.entry("poneyland").or_default(); /// /// assert_eq!(map["poneyland"], None); @@ -297,19 +310,19 @@ impl<'a, K: Ord, V: Default, A: Allocator + Clone> Entry<'a, K, V, A> { } } -impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { +impl<'a, K, V, C, A: Allocator + Clone> VacantEntry<'a, K, V, C, A> { /// Gets a reference to the key that would be used when inserting a value /// through the VacantEntry. /// /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` - #[stable(feature = "map_entry_keys", since = "1.10.0")] + // #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { &self.key } @@ -319,16 +332,16 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// /// if let Entry::Vacant(v) = map.entry("poneyland") { /// v.into_key(); /// } /// ``` - #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + // #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn into_key(self) -> K { self.key } @@ -339,17 +352,17 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, u32> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, u32> = BTreeMap::default(); /// /// if let Entry::Vacant(o) = map.entry("poneyland") { /// o.insert(37); /// } /// assert_eq!(map["poneyland"], 37); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(self, value: V) -> &'a mut V { let out_ptr = match self.handle { None => { @@ -369,6 +382,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { val_ptr } (Some(ins), val_ptr) => { + #[allow(clippy::drop_non_drop)] drop(ins.left); // SAFETY: We have consumed self.handle and dropped the // remaining reference to the tree, ins.left. @@ -387,20 +401,20 @@ impl<'a, K: Ord, V, A: Allocator + Clone> VacantEntry<'a, K, V, A> { } } -impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { +impl<'a, K, V, C, A: Allocator + Clone> OccupiedEntry<'a, K, V, C, A> { /// Gets a reference to the key in the entry. /// /// # Examples /// /// ``` - /// use std::collections::BTreeMap; + /// use copse::BTreeMap; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// assert_eq!(map.entry("poneyland").key(), &"poneyland"); /// ``` #[must_use] - #[stable(feature = "map_entry_keys", since = "1.10.0")] + // #[stable(feature = "map_entry_keys", since = "1.10.0")] pub fn key(&self) -> &K { self.handle.reborrow().into_kv().0 } @@ -410,10 +424,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { @@ -424,7 +438,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// // If now try to get the value, it will panic: /// // println!("{}", map["poneyland"]); /// ``` - #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] + // #[stable(feature = "map_entry_recover_keys2", since = "1.12.0")] pub fn remove_entry(self) -> (K, V) { self.remove_kv() } @@ -434,10 +448,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { @@ -445,7 +459,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// } /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn get(&self) -> &V { self.handle.reborrow().into_kv().1 } @@ -460,10 +474,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); @@ -476,7 +490,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// } /// assert_eq!(map["poneyland"], 24); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn get_mut(&mut self) -> &mut V { self.handle.kv_mut().1 } @@ -490,10 +504,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// assert_eq!(map["poneyland"], 12); @@ -503,7 +517,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// assert_eq!(map["poneyland"], 22); /// ``` #[must_use = "`self` will be dropped if the result is not used"] - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn into_mut(self) -> &'a mut V { self.handle.into_val_mut() } @@ -514,10 +528,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(mut o) = map.entry("poneyland") { @@ -525,7 +539,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// } /// assert_eq!(map["poneyland"], 15); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn insert(&mut self, value: V) -> V { mem::replace(self.get_mut(), value) } @@ -535,10 +549,10 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// # Examples /// /// ``` - /// use std::collections::BTreeMap; - /// use std::collections::btree_map::Entry; + /// use copse::BTreeMap; + /// use copse::map::Entry; /// - /// let mut map: BTreeMap<&str, usize> = BTreeMap::new(); + /// let mut map: BTreeMap<&str, usize> = BTreeMap::default(); /// map.entry("poneyland").or_insert(12); /// /// if let Entry::Occupied(o) = map.entry("poneyland") { @@ -547,7 +561,7 @@ impl<'a, K: Ord, V, A: Allocator + Clone> OccupiedEntry<'a, K, V, A> { /// // If we try to get "poneyland"'s value, it'll panic: /// // println!("{}", map["poneyland"]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(self) -> V { self.remove_kv().1 } diff --git a/src/btree/map/tests.rs b/src/btree/map/tests.rs index c37a9e7..dfad87c 100644 --- a/src/btree/map/tests.rs +++ b/src/btree/map/tests.rs @@ -3,11 +3,11 @@ use super::super::testing::ord_chaos::{Cyclic3, Governed, Governor}; use super::super::testing::rng::DeterministicRng; use super::Entry::{Occupied, Vacant}; use super::*; -use crate::boxed::Box; -use crate::fmt::Debug; -use crate::rc::Rc; -use crate::string::{String, ToString}; -use crate::vec::Vec; +use alloc::boxed::Box; +use alloc::fmt::Debug; +use alloc::rc::Rc; +use alloc::string::{String, ToString}; +use alloc::vec::Vec; use std::cmp::Ordering; use std::convert::TryFrom; use std::iter::{self, FromIterator}; @@ -41,7 +41,10 @@ fn test_all_refs<'a, T: 'a>(dummy: &mut T, iter: impl Iterator } } -impl BTreeMap { +impl BTreeMap +where + K::State: Ord, +{ // Panics if the map (or the code navigating it) is corrupted. fn check_invariants(&self) { if let Some(root) = &self.root { @@ -71,7 +74,7 @@ impl BTreeMap { // guarantee that all keys are unique, just that adjacent keys are unique. fn check(&self) where - K: Debug + Ord, + K::State: Debug, { self.check_invariants(); self.assert_strictly_ascending(); @@ -96,12 +99,17 @@ impl BTreeMap { // Panics if the keys are not in strictly ascending order. fn assert_strictly_ascending(&self) where - K: Debug + Ord, + K::State: Debug, { let mut keys = self.keys(); if let Some(mut previous) = keys.next() { for next in keys { - assert!(previous < next, "{:?} >= {:?}", previous, next); + assert!( + previous.borrow() < next.borrow(), + "{:?} >= {:?}", + previous.borrow(), + next.borrow() + ); previous = next; } } @@ -115,7 +123,20 @@ impl BTreeMap { K: Ord, { let iter = mem::take(self).into_iter(); - if !iter.is_empty() { + + cfg_if! { + if #[cfg(feature = "exact_size_is_empty")] { + let non_empty = !iter.is_empty(); + } else { + let (iter, non_empty) = { + let mut iter = iter.peekable(); + let non_empty = iter.peek().is_some(); + (iter, non_empty) + }; + } + } + + if non_empty { self.root .insert(Root::new(*self.alloc)) .bulk_push(iter, &mut self.length, *self.alloc); @@ -145,7 +166,7 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> // during insertion, otherwise other test cases may fail or be less useful. #[test] fn test_levels() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.check(); assert_eq!(map.height(), None); assert_eq!(map.len(), 0); @@ -200,7 +221,7 @@ fn test_check_invariants_ord_chaos() { #[test] fn test_basic_large() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); // Miri is too slow let size = if cfg!(miri) { MIN_INSERTS_HEIGHT_2 @@ -260,7 +281,7 @@ fn test_basic_large() { #[test] fn test_basic_small() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); // Empty, root is absent (None): assert_eq!(map.remove(&1), None); assert_eq!(map.len(), 0); @@ -270,7 +291,7 @@ fn test_basic_small() { assert_eq!(map.last_key_value(), None); assert_eq!(map.keys().count(), 0); assert_eq!(map.values().count(), 0); - assert_eq!(map.range(..).next(), None); + assert_eq!(map.range::(..).next(), None); assert_eq!(map.range(..1).next(), None); assert_eq!(map.range(1..).next(), None); assert_eq!(map.range(1..=1).next(), None); @@ -334,7 +355,7 @@ fn test_basic_small() { assert_eq!(map.last_key_value(), None); assert_eq!(map.keys().count(), 0); assert_eq!(map.values().count(), 0); - assert_eq!(map.range(..).next(), None); + assert_eq!(map.range::(..).next(), None); assert_eq!(map.range(..1).next(), None); assert_eq!(map.range(1..).next(), None); assert_eq!(map.range(1..=1).next(), None); @@ -391,8 +412,9 @@ fn test_iter_rev() { // Specifically tests iter_mut's ability to mutate the value of pairs in-line. fn do_test_iter_mut_mutation(size: usize) where - T: Copy + Debug + Ord + TryFrom, + T: Copy + Sortable + TryFrom, >::Error: Debug, + T::State: Debug + Ord, { let zero = T::try_from(0).unwrap(); let mut map = BTreeMap::from_iter((0..size).map(|i| (T::try_from(i).unwrap(), zero))); @@ -403,22 +425,22 @@ where // Iterate forwards, trying to mutate to unique values for (i, (k, v)) in map.iter_mut().enumerate() { - assert_eq!(*k, T::try_from(i).unwrap()); - assert_eq!(*v, zero); + assert_eq!(k.borrow(), T::try_from(i).unwrap().borrow()); + assert_eq!((*v).borrow(), zero.borrow()); *v = T::try_from(i + 1).unwrap(); } // Iterate backwards, checking that mutations succeeded and trying to mutate again for (i, (k, v)) in map.iter_mut().rev().enumerate() { - assert_eq!(*k, T::try_from(size - i - 1).unwrap()); - assert_eq!(*v, T::try_from(size - i).unwrap()); + assert_eq!(k.borrow(), T::try_from(size - i - 1).unwrap().borrow()); + assert_eq!((*v).borrow(), T::try_from(size - i).unwrap().borrow()); *v = T::try_from(2 * size - i).unwrap(); } // Check that backward mutations succeeded for (i, (k, v)) in map.iter_mut().enumerate() { - assert_eq!(*k, T::try_from(i).unwrap()); - assert_eq!(*v, T::try_from(size + i + 1).unwrap()); + assert_eq!(k.borrow(), T::try_from(i).unwrap().borrow()); + assert_eq!((*v).borrow(), T::try_from(size + i + 1).unwrap().borrow()); } map.check(); } @@ -427,6 +449,10 @@ where #[repr(align(32))] struct Align32(usize); +impl Sortable for Align32 { + type State = Self; +} + impl TryFrom for Align32 { type Error = (); @@ -468,12 +494,12 @@ fn test_values_mut() { #[test] fn test_values_mut_mutation() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); a.insert(1, String::from("hello")); a.insert(2, String::from("goodbye")); for value in a.values_mut() { - value.push_str("!"); + value.push('!'); } let values = Vec::from_iter(a.values().cloned()); @@ -543,15 +569,15 @@ fn test_iter_mixed() { #[test] fn test_iter_min_max() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); assert_eq!(a.iter().min(), None); assert_eq!(a.iter().max(), None); assert_eq!(a.iter_mut().min(), None); assert_eq!(a.iter_mut().max(), None); - assert_eq!(a.range(..).min(), None); - assert_eq!(a.range(..).max(), None); - assert_eq!(a.range_mut(..).min(), None); - assert_eq!(a.range_mut(..).max(), None); + assert_eq!(a.range::(..).min(), None); + assert_eq!(a.range::(..).max(), None); + assert_eq!(a.range_mut::(..).min(), None); + assert_eq!(a.range_mut::(..).max(), None); assert_eq!(a.keys().min(), None); assert_eq!(a.keys().max(), None); assert_eq!(a.values().min(), None); @@ -564,10 +590,10 @@ fn test_iter_min_max() { assert_eq!(a.iter().max(), Some((&2, &24))); assert_eq!(a.iter_mut().min(), Some((&1, &mut 42))); assert_eq!(a.iter_mut().max(), Some((&2, &mut 24))); - assert_eq!(a.range(..).min(), Some((&1, &42))); - assert_eq!(a.range(..).max(), Some((&2, &24))); - assert_eq!(a.range_mut(..).min(), Some((&1, &mut 42))); - assert_eq!(a.range_mut(..).max(), Some((&2, &mut 24))); + assert_eq!(a.range::(..).min(), Some((&1, &42))); + assert_eq!(a.range::(..).max(), Some((&2, &24))); + assert_eq!(a.range_mut::(..).min(), Some((&1, &mut 42))); + assert_eq!(a.range_mut::(..).max(), Some((&2, &mut 24))); assert_eq!(a.keys().min(), Some(&1)); assert_eq!(a.keys().max(), Some(&2)); assert_eq!(a.values().min(), Some(&24)); @@ -577,7 +603,10 @@ fn test_iter_min_max() { a.check(); } -fn range_keys(map: &BTreeMap, range: impl RangeBounds) -> Vec { +fn range_keys( + map: &BTreeMap Ordering>, + range: impl RangeBounds, +) -> Vec { Vec::from_iter(map.range(range).map(|(&k, &v)| { assert_eq!(k, v); k @@ -837,7 +866,7 @@ fn test_range_backwards_4() { #[test] fn test_range_finding_ill_order_in_map() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(Cyclic3::B, ()); // Lacking static_assert, call `range` conditionally, to emphasise that // we cause a different panic than `test_range_backwards_1` does. @@ -848,6 +877,7 @@ fn test_range_finding_ill_order_in_map() { } #[test] +#[ignore] fn test_range_finding_ill_order_in_range_ord() { // Has proper order the first time asked, then flips around. struct EvilTwin(i32); @@ -887,6 +917,10 @@ fn test_range_finding_ill_order_in_range_ord() { } } + impl Sortable for CompositeKey { + type State = EvilTwin; + } + let map = BTreeMap::from_iter((0..12).map(|i| (CompositeKey(i, EvilTwin(i)), ()))); let _ = map.range(EvilTwin(5)..=EvilTwin(7)); } @@ -902,7 +936,7 @@ fn test_range_1000() { let map = BTreeMap::from_iter((0..size).map(|i| (i, i))); fn test(map: &BTreeMap, size: u32, min: Bound<&u32>, max: Bound<&u32>) { - let mut kvs = map.range((min, max)).map(|(&k, &v)| (k, v)); + let mut kvs = map.range::((min, max)).map(|(&k, &v)| (k, v)); let mut pairs = (0..size).map(|i| (i, i)); for (kv, pair) in kvs.by_ref().zip(pairs.by_ref()) { @@ -921,7 +955,7 @@ fn test_range_1000() { #[test] fn test_range_borrowed_key() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert("aardvark".to_string(), 1); map.insert("baboon".to_string(), 2); map.insert("coyote".to_string(), 3); @@ -943,7 +977,7 @@ fn test_range() { for i in (0..size).step_by(step) { for j in (i..size).step_by(step) { let mut kvs = map - .range((Included(&i), Included(&j))) + .range::((Included(&i), Included(&j))) .map(|(&k, &v)| (k, v)); let mut pairs = (i..=j).map(|i| (i, i)); @@ -966,7 +1000,7 @@ fn test_range_mut() { for i in (0..size).step_by(step) { for j in (i..size).step_by(step) { let mut kvs = map - .range_mut((Included(&i), Included(&j))) + .range_mut::((Included(&i), Included(&j))) .map(|(&k, &mut v)| (k, v)); let mut pairs = (i..=j).map(|i| (i, i)); @@ -980,37 +1014,58 @@ fn test_range_mut() { map.check(); } -#[should_panic(expected = "range start is greater than range end in BTreeMap")] +#[cfg_attr( + feature = "specialization", + should_panic(expected = "range start is greater than range end in BTreeMap") +)] +#[cfg_attr( + not(feature = "specialization"), + should_panic(expected = "range start is greater than range end") +)] #[test] fn test_range_panic_1() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(3, "a"); map.insert(5, "b"); map.insert(8, "c"); - let _invalid_range = map.range((Included(&8), Included(&3))); + let _invalid_range = map.range::((Included(&8), Included(&3))); } -#[should_panic(expected = "range start and end are equal and excluded in BTreeMap")] +#[cfg_attr( + feature = "specialization", + should_panic(expected = "range start and end are equal and excluded in BTreeMap") +)] +#[cfg_attr( + not(feature = "specialization"), + should_panic(expected = "range start and end are equal and excluded") +)] #[test] fn test_range_panic_2() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(3, "a"); map.insert(5, "b"); map.insert(8, "c"); - let _invalid_range = map.range((Excluded(&5), Excluded(&5))); + let _invalid_range = map.range::((Excluded(&5), Excluded(&5))); } -#[should_panic(expected = "range start and end are equal and excluded in BTreeMap")] +#[cfg_attr( + feature = "specialization", + should_panic(expected = "range start and end are equal and excluded in BTreeMap") +)] +#[cfg_attr( + not(feature = "specialization"), + should_panic(expected = "range start and end are equal and excluded") +)] #[test] fn test_range_panic_3() { - let mut map: BTreeMap = BTreeMap::new(); + let mut map: BTreeMap = BTreeMap::default(); map.insert(3, ()); map.insert(5, ()); map.insert(8, ()); - let _invalid_range = map.range((Excluded(&5), Excluded(&5))); + let _invalid_range = map.range::((Excluded(&5), Excluded(&5))); } #[test] @@ -1029,7 +1084,7 @@ mod test_drain_filter { #[test] fn empty() { - let mut map: BTreeMap = BTreeMap::new(); + let mut map: BTreeMap = BTreeMap::default(); map.drain_filter(|_, _| unreachable!("there's nothing to decide on")); assert_eq!(map.height(), None); map.check(); @@ -1240,7 +1295,7 @@ mod test_drain_filter { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(a.spawn(Panic::Never), ()); map.insert(b.spawn(Panic::InDrop), ()); map.insert(c.spawn(Panic::Never), ()); @@ -1260,7 +1315,7 @@ mod test_drain_filter { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(a.spawn(Panic::Never), ()); map.insert(b.spawn(Panic::InQuery), ()); map.insert(c.spawn(Panic::InQuery), ()); @@ -1288,7 +1343,7 @@ mod test_drain_filter { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(a.spawn(Panic::Never), ()); map.insert(b.spawn(Panic::InQuery), ()); map.insert(c.spawn(Panic::InQuery), ()); @@ -1319,25 +1374,25 @@ mod test_drain_filter { fn test_borrow() { // make sure these compile -- using the Borrow trait { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert("0".to_string(), 1); assert_eq!(map["0"], 1); } { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(Box::new(0), 1); assert_eq!(map[&0], 1); } { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(Box::new([0, 1]) as Box<[i32]>, 1); assert_eq!(map[&[0, 1][..]], 1); } { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(Rc::new(0), 1); assert_eq!(map[&0], 1); } @@ -1442,9 +1497,9 @@ fn test_entry() { #[test] fn test_extend_ref() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); a.insert(1, "one"); - let mut b = BTreeMap::new(); + let mut b = BTreeMap::default(); b.insert(2, "two"); b.insert(3, "three"); @@ -1459,7 +1514,7 @@ fn test_extend_ref() { #[test] fn test_zst() { - let mut m = BTreeMap::new(); + let mut m = BTreeMap::default(); assert_eq!(m.len(), 0); assert_eq!(m.insert((), ()), None); @@ -1489,6 +1544,10 @@ fn test_bad_zst() { #[derive(Clone, Copy, Debug)] struct Bad; + impl Sortable for Bad { + type State = Self; + } + impl PartialEq for Bad { fn eq(&self, _: &Self) -> bool { false @@ -1509,7 +1568,7 @@ fn test_bad_zst() { } } - let mut m = BTreeMap::new(); + let mut m = BTreeMap::default(); for _ in 0..100 { m.insert(Bad, Bad); @@ -1519,7 +1578,7 @@ fn test_bad_zst() { #[test] fn test_clear() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); for &len in &[ MIN_INSERTS_HEIGHT_1, MIN_INSERTS_HEIGHT_2, @@ -1542,7 +1601,7 @@ fn test_clear_drop_panic_leak() { let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert(a.spawn(Panic::Never), ()); map.insert(b.spawn(Panic::InDrop), ()); map.insert(c.spawn(Panic::Never), ()); @@ -1561,7 +1620,7 @@ fn test_clear_drop_panic_leak() { #[test] fn test_clone() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); let size = MIN_INSERTS_HEIGHT_1; assert_eq!(map.len(), 0); @@ -1606,7 +1665,7 @@ fn test_clone() { fn test_clone_panic_leak(size: usize) { for i in 0..size { - let dummies = Vec::from_iter((0..size).map(|id| CrashTestDummy::new(id))); + let dummies = Vec::from_iter((0..size).map(CrashTestDummy::new)); let map = BTreeMap::from_iter(dummies.iter().map(|dummy| { let panic = if dummy.id == i { Panic::InClone @@ -1667,12 +1726,12 @@ fn test_clone_panic_leak_height_1() { #[test] fn test_clone_from() { - let mut map1 = BTreeMap::new(); + let mut map1 = BTreeMap::default(); let max_size = MIN_INSERTS_HEIGHT_1; // Range to max_size inclusive, because i is the size of map1 being tested. for i in 0..=max_size { - let mut map2 = BTreeMap::new(); + let mut map2 = BTreeMap::default(); for j in 0..i { let mut map1_copy = map2.clone(); map1_copy.clone_from(&map1); // small cloned from large @@ -1751,66 +1810,111 @@ fn assert_covariance() { #[allow(dead_code)] fn assert_sync() { - fn map(v: &BTreeMap) -> impl Sync + '_ { + fn map(v: &BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v } - fn into_iter(v: BTreeMap) -> impl Sync { + fn into_iter(v: BTreeMap) -> impl Sync + where + T::State: Ord, + { v.into_iter() } - fn into_keys(v: BTreeMap) -> impl Sync { + fn into_keys(v: BTreeMap) -> impl Sync + where + T::State: Ord, + { v.into_keys() } - fn into_values(v: BTreeMap) -> impl Sync { + fn into_values(v: BTreeMap) -> impl Sync + where + T::State: Ord, + { v.into_values() } - fn drain_filter(v: &mut BTreeMap) -> impl Sync + '_ { + fn drain_filter(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.drain_filter(|_, _| false) } - fn iter(v: &BTreeMap) -> impl Sync + '_ { + fn iter(v: &BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.iter() } - fn iter_mut(v: &mut BTreeMap) -> impl Sync + '_ { + fn iter_mut(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.iter_mut() } - fn keys(v: &BTreeMap) -> impl Sync + '_ { + fn keys(v: &BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.keys() } - fn values(v: &BTreeMap) -> impl Sync + '_ { + fn values(v: &BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.values() } - fn values_mut(v: &mut BTreeMap) -> impl Sync + '_ { + fn values_mut(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.values_mut() } - fn range(v: &BTreeMap) -> impl Sync + '_ { - v.range(..) + fn range(v: &BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { + v.range::(..) } - fn range_mut(v: &mut BTreeMap) -> impl Sync + '_ { - v.range_mut(..) + fn range_mut(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { + v.range_mut::(..) } - fn entry(v: &mut BTreeMap) -> impl Sync + '_ { + fn entry(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { v.entry(Default::default()) } - fn occupied_entry(v: &mut BTreeMap) -> impl Sync + '_ { + fn occupied_entry(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { match v.entry(Default::default()) { Occupied(entry) => entry, _ => unreachable!(), } } - fn vacant_entry(v: &mut BTreeMap) -> impl Sync + '_ { + fn vacant_entry(v: &mut BTreeMap) -> impl Sync + '_ + where + T::State: Ord, + { match v.entry(Default::default()) { Vacant(entry) => entry, _ => unreachable!(), @@ -1820,66 +1924,111 @@ fn assert_sync() { #[allow(dead_code)] fn assert_send() { - fn map(v: BTreeMap) -> impl Send { + fn map(v: BTreeMap) -> impl Send + where + T::State: Ord, + { v } - fn into_iter(v: BTreeMap) -> impl Send { + fn into_iter(v: BTreeMap) -> impl Send + where + T::State: Ord, + { v.into_iter() } - fn into_keys(v: BTreeMap) -> impl Send { + fn into_keys(v: BTreeMap) -> impl Send + where + T::State: Ord, + { v.into_keys() } - fn into_values(v: BTreeMap) -> impl Send { + fn into_values(v: BTreeMap) -> impl Send + where + T::State: Ord, + { v.into_values() } - fn drain_filter(v: &mut BTreeMap) -> impl Send + '_ { + fn drain_filter(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.drain_filter(|_, _| false) } - fn iter(v: &BTreeMap) -> impl Send + '_ { + fn iter(v: &BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.iter() } - fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ { + fn iter_mut(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.iter_mut() } - fn keys(v: &BTreeMap) -> impl Send + '_ { + fn keys(v: &BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.keys() } - fn values(v: &BTreeMap) -> impl Send + '_ { + fn values(v: &BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.values() } - fn values_mut(v: &mut BTreeMap) -> impl Send + '_ { + fn values_mut(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.values_mut() } - fn range(v: &BTreeMap) -> impl Send + '_ { - v.range(..) + fn range(v: &BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { + v.range::(..) } - fn range_mut(v: &mut BTreeMap) -> impl Send + '_ { - v.range_mut(..) + fn range_mut(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { + v.range_mut::(..) } - fn entry(v: &mut BTreeMap) -> impl Send + '_ { + fn entry(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { v.entry(Default::default()) } - fn occupied_entry(v: &mut BTreeMap) -> impl Send + '_ { + fn occupied_entry(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { match v.entry(Default::default()) { Occupied(entry) => entry, _ => unreachable!(), } } - fn vacant_entry(v: &mut BTreeMap) -> impl Send + '_ { + fn vacant_entry(v: &mut BTreeMap) -> impl Send + '_ + where + T::State: Ord, + { match v.entry(Default::default()) { Vacant(entry) => entry, _ => unreachable!(), @@ -1889,7 +2038,7 @@ fn assert_send() { #[test] fn test_ord_absence() { - fn map(mut map: BTreeMap) { + fn map(mut map: BTreeMap) { let _ = map.is_empty(); let _ = map.len(); map.clear(); @@ -1898,6 +2047,7 @@ fn test_ord_absence() { let _ = map.keys(); let _ = map.values(); let _ = map.values_mut(); + #[allow(clippy::ifs_same_cond)] if true { let _ = map.into_values(); } else if true { @@ -1907,13 +2057,14 @@ fn test_ord_absence() { } } - fn map_debug(mut map: BTreeMap) { + fn map_debug(mut map: BTreeMap) { format!("{map:?}"); format!("{:?}", map.iter()); format!("{:?}", map.iter_mut()); format!("{:?}", map.keys()); format!("{:?}", map.values()); format!("{:?}", map.values_mut()); + #[allow(clippy::ifs_same_cond)] if true { format!("{:?}", map.into_iter()); } else if true { @@ -1923,20 +2074,20 @@ fn test_ord_absence() { } } - fn map_clone(mut map: BTreeMap) { + fn map_clone(mut map: BTreeMap) { map.clone_from(&map.clone()); } #[derive(Debug, Clone)] struct NonOrd; - map(BTreeMap::::new()); - map_debug(BTreeMap::::new()); - map_clone(BTreeMap::::default()); + map(BTreeMap::::new(())); + map_debug(BTreeMap::::new(())); + map_clone(BTreeMap::::new(())); } #[test] fn test_occupied_entry_key() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); let key = "hello there"; let value = "value goes here"; assert_eq!(a.height(), None); @@ -1955,7 +2106,7 @@ fn test_occupied_entry_key() { #[test] fn test_vacant_entry_key() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); let key = "hello there"; let value = "value goes here"; @@ -1974,7 +2125,7 @@ fn test_vacant_entry_key() { #[test] fn test_vacant_entry_no_insert() { - let mut a = BTreeMap::<&str, ()>::new(); + let mut a = BTreeMap::<&str, ()>::default(); let key = "hello there"; // Non-allocated @@ -2004,7 +2155,7 @@ fn test_vacant_entry_no_insert() { #[test] fn test_first_last_entry() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); assert!(a.first_entry().is_none()); assert!(a.last_entry().is_none()); a.insert(1, 42); @@ -2029,7 +2180,7 @@ fn test_first_last_entry() { #[test] fn test_pop_first_last() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); assert_eq!(map.pop_first(), None); assert_eq!(map.pop_last(), None); @@ -2095,7 +2246,7 @@ fn test_pop_first_last() { #[test] fn test_get_key_value() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); assert!(map.is_empty()); assert_eq!(map.get_key_value(&1), None); @@ -2148,7 +2299,7 @@ fn test_insert_into_full_height_1() { #[test] fn test_try_insert() { - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); assert!(map.is_empty()); @@ -2165,12 +2316,12 @@ macro_rules! create_append_test { ($name:ident, $len:expr) => { #[test] fn $name() { - let mut a = BTreeMap::new(); + let mut a = BTreeMap::default(); for i in 0..8 { a.insert(i, i); } - let mut b = BTreeMap::new(); + let mut b = BTreeMap::default(); for i in 5..$len { b.insert(i, 2 * i); } @@ -2222,8 +2373,8 @@ fn test_append_drop_leak() { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut left = BTreeMap::new(); - let mut right = BTreeMap::new(); + let mut left = BTreeMap::default(); + let mut right = BTreeMap::default(); left.insert(a.spawn(Panic::Never), ()); left.insert(b.spawn(Panic::InDrop), ()); // first duplicate key, dropped during append left.insert(c.spawn(Panic::Never), ()); @@ -2238,10 +2389,10 @@ fn test_append_drop_leak() { #[test] fn test_append_ord_chaos() { - let mut map1 = BTreeMap::new(); + let mut map1 = BTreeMap::default(); map1.insert(Cyclic3::A, ()); map1.insert(Cyclic3::B, ()); - let mut map2 = BTreeMap::new(); + let mut map2 = BTreeMap::default(); map2.insert(Cyclic3::A, ()); map2.insert(Cyclic3::B, ()); map2.insert(Cyclic3::C, ()); // lands first, before A @@ -2295,7 +2446,7 @@ fn test_split_off_empty_left() { #[test] fn test_split_off_tiny_left_height_2() { let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); - let mut left = BTreeMap::from_iter(pairs.clone()); + let mut left = BTreeMap::from_iter(pairs); let right = left.split_off(&1); left.check(); right.check(); @@ -2311,7 +2462,7 @@ fn test_split_off_tiny_left_height_2() { fn test_split_off_tiny_right_height_2() { let pairs = (0..MIN_INSERTS_HEIGHT_2).map(|i| (i, i)); let last = MIN_INSERTS_HEIGHT_2 - 1; - let mut left = BTreeMap::from_iter(pairs.clone()); + let mut left = BTreeMap::from_iter(pairs); assert_eq!(*left.last_key_value().unwrap().0, last); let right = left.split_off(&last); left.check(); @@ -2373,7 +2524,7 @@ fn test_into_iter_drop_leak_height_0() { let c = CrashTestDummy::new(2); let d = CrashTestDummy::new(3); let e = CrashTestDummy::new(4); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); map.insert("a", a.spawn(Panic::Never)); map.insert("b", b.spawn(Panic::Never)); map.insert("c", c.spawn(Panic::Never)); @@ -2392,8 +2543,8 @@ fn test_into_iter_drop_leak_height_0() { #[test] fn test_into_iter_drop_leak_height_1() { let size = MIN_INSERTS_HEIGHT_1; - for panic_point in vec![0, 1, size - 2, size - 1] { - let dummies = Vec::from_iter((0..size).map(|i| CrashTestDummy::new(i))); + for panic_point in [0, 1, size - 2, size - 1] { + let dummies = Vec::from_iter((0..size).map(CrashTestDummy::new)); let map = BTreeMap::from_iter((0..size).map(|i| { let panic = if i == panic_point { Panic::InDrop @@ -2403,8 +2554,8 @@ fn test_into_iter_drop_leak_height_1() { (dummies[i].spawn(Panic::Never), dummies[i].spawn(panic)) })); catch_unwind(move || drop(map.into_iter())).unwrap_err(); - for i in 0..size { - assert_eq!(dummies[i].dropped(), 2); + for dummy in dummies { + assert_eq!(dummy.dropped(), 2); } } } @@ -2434,7 +2585,7 @@ fn test_into_values() { #[test] fn test_insert_remove_intertwined() { let loops = if cfg!(miri) { 100 } else { 1_000_000 }; - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); let mut i = 1; let offset = 165; // somewhat arbitrarily chosen to cover some code paths for _ in 0..loops { @@ -2449,7 +2600,7 @@ fn test_insert_remove_intertwined() { fn test_insert_remove_intertwined_ord_chaos() { let loops = if cfg!(miri) { 100 } else { 1_000_000 }; let gov = Governor::new(); - let mut map = BTreeMap::new(); + let mut map = BTreeMap::default(); let mut i = 1; let offset = 165; // more arbitrarily copied from above for _ in 0..loops { diff --git a/src/btree/mem.rs b/src/btree/mem.rs index e1363d1..ab47a2f 100644 --- a/src/btree/mem.rs +++ b/src/btree/mem.rs @@ -1,7 +1,10 @@ +#[cfg(feature = "core_intrinsics")] use core::intrinsics; use core::mem; use core::ptr; +use cfg_if::cfg_if; + /// This replaces the value behind the `v` unique reference by calling the /// relevant function. /// @@ -21,7 +24,15 @@ pub fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { struct PanicGuard; impl Drop for PanicGuard { fn drop(&mut self) { - intrinsics::abort() + cfg_if! { + if #[cfg(feature = "core_intrinsics")] { + intrinsics::abort() + } else if #[cfg(feature = "std")] { + std::process::abort() + } else { + panic!() + } + } } } let guard = PanicGuard; diff --git a/src/btree/merge_iter.rs b/src/btree/merge_iter.rs index d449700..37c37cf 100644 --- a/src/btree/merge_iter.rs +++ b/src/btree/merge_iter.rs @@ -2,6 +2,8 @@ use core::cmp::Ordering; use core::fmt::{self, Debug}; use core::iter::FusedIterator; +use crate::Comparator; + /// Core of an iterator that merges the output of two strictly ascending iterators, /// for instance a union or a symmetric difference. pub struct MergeIterInner { @@ -59,9 +61,9 @@ impl MergeIterInner { /// the sources are not strictly ascending). If neither returned option /// contains a value, iteration has finished and subsequent calls will /// return the same empty pair. - pub fn nexts Ordering>( + pub fn nexts( &mut self, - cmp: Cmp, + comparator: &impl Comparator, ) -> (Option, Option) where I: FusedIterator, @@ -82,8 +84,8 @@ impl MergeIterInner { b_next = self.b.next(); } } - if let (Some(ref a1), Some(ref b1)) = (&a_next, &b_next) { - match cmp(a1, b1) { + if let (Some(a1), Some(b1)) = (&a_next, &b_next) { + match comparator.cmp(a1, b1) { Ordering::Less => self.peeked = b_next.take().map(Peeked::B), Ordering::Greater => self.peeked = a_next.take().map(Peeked::A), Ordering::Equal => (), diff --git a/src/btree/navigate.rs b/src/btree/navigate.rs index 83876f7..da3fd20 100644 --- a/src/btree/navigate.rs +++ b/src/btree/navigate.rs @@ -1,11 +1,13 @@ -use core::borrow::Borrow; use core::hint; use core::ops::RangeBounds; use core::ptr; +use core::borrow::Borrow; + +use crate::{Sortable, Comparator}; use super::node::{marker, ForceResult::*, Handle, NodeRef}; -use crate::alloc::Allocator; +use crate::Allocator; // `front` and `back` are always both `None` or both `Some`. pub struct LeafRange { front: Option, marker::Edge>>, @@ -14,13 +16,12 @@ pub struct LeafRange { impl<'a, K: 'a, V: 'a> Clone for LeafRange, K, V> { fn clone(&self) -> Self { - LeafRange { - front: self.front.clone(), - back: self.back.clone(), - } + *self } } +impl<'a, K: 'a, V: 'a> Copy for LeafRange, K, V> {} + impl LeafRange { pub fn none() -> Self { LeafRange { @@ -265,16 +266,17 @@ impl NodeRef( + unsafe fn find_leaf_edges_spanning_range( self, + comparator: &impl Comparator, range: R, ) -> LeafRange where - Q: Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, R: RangeBounds, { - match self.search_tree_for_bifurcation(&range) { + match self.search_tree_for_bifurcation(comparator, &range) { Err(_) => LeafRange::none(), Ok(( node, @@ -295,9 +297,9 @@ impl NodeRef { (lower_edge, lower_child_bound) = - f.descend().find_lower_bound_edge(lower_child_bound); + f.descend().find_lower_bound_edge(comparator, lower_child_bound); (upper_edge, upper_child_bound) = - b.descend().find_upper_bound_edge(upper_child_bound); + b.descend().find_upper_bound_edge(comparator, upper_child_bound); } _ => unreachable!("BTreeMap has different depths"), } @@ -322,14 +324,18 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> /// /// The result is meaningful only if the tree is ordered by key, like the tree /// in a `BTreeMap` is. - pub fn range_search(self, range: R) -> LeafRange, K, V> + pub fn range_search( + self, + comparator: &impl Comparator, + range: R, + ) -> LeafRange, K, V> where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, R: RangeBounds, { // SAFETY: our borrow type is immutable. - unsafe { self.find_leaf_edges_spanning_range(range) } + unsafe { self.find_leaf_edges_spanning_range(comparator, range) } } /// Finds the pair of leaf edges delimiting an entire tree. @@ -348,13 +354,17 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> /// /// # Safety /// Do not use the duplicate handles to visit the same KV twice. - pub fn range_search(self, range: R) -> LeafRange, K, V> + pub fn range_search( + self, + comparator: &impl Comparator, + range: R, + ) -> LeafRange, K, V> where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, R: RangeBounds, { - unsafe { self.find_leaf_edges_spanning_range(range) } + unsafe { self.find_leaf_edges_spanning_range(comparator, range) } } /// Splits a unique reference into a pair of leaf edges delimiting the full range of the tree. diff --git a/src/btree/node.rs b/src/btree/node.rs index 81e0803..ec60e25 100644 --- a/src/btree/node.rs +++ b/src/btree/node.rs @@ -36,8 +36,10 @@ use core::mem::{self, MaybeUninit}; use core::ptr::{self, NonNull}; use core::slice::SliceIndex; -use crate::alloc::{Allocator, Layout}; -use crate::boxed::Box; +use crate::Allocator; +use alloc::alloc::Layout; +use alloc::boxed::Box; +use cfg_if::cfg_if; const B: usize = 6; pub const CAPACITY: usize = 2 * B - 1; @@ -77,12 +79,54 @@ impl LeafNode { } } - /// Creates a new boxed `LeafNode`. - fn new(alloc: A) -> Box { - unsafe { - let mut leaf = Box::new_uninit_in(alloc); - LeafNode::init(leaf.as_mut_ptr()); - leaf.assume_init() + cfg_if! { + if #[cfg(feature = "allocator_api")] { + /// Creates a new boxed `LeafNode`. + fn new(alloc: A) -> Box { + cfg_if! { + if #[cfg(feature = "new_uninit")] { + unsafe { + let mut leaf = Box::new_uninit_in(alloc); + LeafNode::init(leaf.as_mut_ptr()); + leaf.assume_init() + } + } else { + let layout = Layout::new::(); + match alloc.allocate(layout) { + Ok(ptr) => unsafe { + let leaf = ptr.cast().as_ptr(); + LeafNode::init(leaf); + Box::from_raw_in(leaf, alloc) + }, + Err(_) => alloc::alloc::handle_alloc_error(layout), + } + } + } + } + } else { + /// Creates a new boxed `LeafNode`. + fn new(alloc: A) -> Box { + cfg_if! { + if #[cfg(feature = "new_uninit")] { + unsafe { + let _ = alloc; + let mut leaf = Box::new_uninit(); + LeafNode::init(leaf.as_mut_ptr()); + leaf.assume_init() + } + } else { + let layout = Layout::new::(); + match alloc.allocate(layout) { + Ok(ptr) => unsafe { + let leaf = ptr.cast().as_ptr(); + LeafNode::init(leaf); + Box::from_raw(leaf) + }, + Err(_) => alloc::alloc::handle_alloc_error(layout), + } + } + } + } } } } @@ -104,18 +148,68 @@ struct InternalNode { } impl InternalNode { - /// Creates a new boxed `InternalNode`. - /// - /// # Safety - /// An invariant of internal nodes is that they have at least one - /// initialized and valid edge. This function does not set up - /// such an edge. - unsafe fn new(alloc: A) -> Box { - unsafe { - let mut node = Box::::new_uninit_in(alloc); - // We only need to initialize the data; the edges are MaybeUninit. - LeafNode::init(ptr::addr_of_mut!((*node.as_mut_ptr()).data)); - node.assume_init() + cfg_if! { + if #[cfg(feature = "allocator_api")] { + /// Creates a new boxed `InternalNode`. + /// + /// # Safety + /// An invariant of internal nodes is that they have at least one + /// initialized and valid edge. This function does not set up + /// such an edge. + unsafe fn new(alloc: A) -> Box { + cfg_if! { + if #[cfg(feature = "new_uninit")] { + unsafe { + let mut node = Box::::new_uninit_in(alloc); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(ptr::addr_of_mut!((*node.as_mut_ptr()).data)); + node.assume_init() + } + } else { + let layout = Layout::new::(); + match alloc.allocate(layout) { + Ok(ptr) => unsafe { + let node = ptr.cast::().as_ptr(); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(ptr::addr_of_mut!((*node).data)); + Box::from_raw_in(node, alloc) + }, + Err(_) => alloc::alloc::handle_alloc_error(layout), + } + } + } + } + } else { + /// Creates a new boxed `InternalNode`. + /// + /// # Safety + /// An invariant of internal nodes is that they have at least one + /// initialized and valid edge. This function does not set up + /// such an edge. + unsafe fn new(alloc: A) -> Box { + cfg_if! { + if #[cfg(feature = "new_uninit")] { + unsafe { + let _ = alloc; + let mut node = Box::::new_uninit(); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(ptr::addr_of_mut!((*node.as_mut_ptr()).data)); + node.assume_init() + } + } else { + let layout = Layout::new::(); + match alloc.allocate(layout) { + Ok(ptr) => unsafe { + let node = ptr.cast::().as_ptr(); + // We only need to initialize the data; the edges are MaybeUninit. + LeafNode::init(ptr::addr_of_mut!((*node).data)); + Box::from_raw(node) + }, + Err(_) => alloc::alloc::handle_alloc_error(layout), + } + } + } + } } } } @@ -214,14 +308,26 @@ unsafe impl Send for NodeRef impl NodeRef { pub fn new_leaf(alloc: A) -> Self { - Self::from_new_leaf(LeafNode::new(alloc)) + Self::from_new_leaf::(LeafNode::new(alloc)) } - fn from_new_leaf(leaf: Box, A>) -> Self { - NodeRef { - height: 0, - node: NonNull::from(Box::leak(leaf)), - _marker: PhantomData, + cfg_if! { + if #[cfg(feature = "allocator_api")] { + fn from_new_leaf(leaf: Box, A>) -> Self { + NodeRef { + height: 0, + node: NonNull::from(Box::leak(leaf)), + _marker: PhantomData, + } + } + } else { + fn from_new_leaf(leaf: Box>) -> Self { + NodeRef { + height: 0, + node: NonNull::from(Box::leak(leaf)), + _marker: PhantomData, + } + } } } } @@ -230,24 +336,45 @@ impl NodeRef { fn new_internal(child: Root, alloc: A) -> Self { let mut new_node = unsafe { InternalNode::new(alloc) }; new_node.edges[0].write(child.node); - unsafe { NodeRef::from_new_internal(new_node, child.height + 1) } - } - - /// # Safety - /// `height` must not be zero. - unsafe fn from_new_internal( - internal: Box, A>, - height: usize, - ) -> Self { - debug_assert!(height > 0); - let node = NonNull::from(Box::leak(internal)).cast(); - let mut this = NodeRef { - height, - node, - _marker: PhantomData, - }; - this.borrow_mut().correct_all_childrens_parent_links(); - this + unsafe { NodeRef::from_new_internal::(new_node, child.height + 1) } + } + + cfg_if! { + if #[cfg(feature = "allocator_api")] { + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal( + internal: Box, A>, + height: usize, + ) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { + height, + node, + _marker: PhantomData, + }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } + } else { + /// # Safety + /// `height` must not be zero. + unsafe fn from_new_internal( + internal: Box>, + height: usize, + ) -> Self { + debug_assert!(height > 0); + let node = NonNull::from(Box::leak(internal)).cast(); + let mut this = NodeRef { + height, + node, + _marker: PhantomData, + }; + this.borrow_mut().correct_all_childrens_parent_links(); + this + } + } } } @@ -334,6 +461,7 @@ impl NodeRef pub fn ascend( self, ) -> Result, marker::Edge>, Self> { + #[allow(clippy::let_unit_value)] let _ = BorrowType::TRAVERSAL_PERMIT; // We need to use raw pointers to nodes because, if BorrowType is marker::ValMut, // there might be outstanding mutable references to values that we must not invalidate. @@ -401,7 +529,15 @@ impl<'a, K: 'a, V: 'a, Type> NodeRef, K, V, Type> { pub fn keys(&self) -> &[K] { let leaf = self.into_leaf(); unsafe { - MaybeUninit::slice_assume_init_ref(leaf.keys.get_unchecked(..usize::from(leaf.len))) + let slice = leaf.keys.get_unchecked(..usize::from(leaf.len)); + + cfg_if! { + if #[cfg(feature = "maybe_uninit_slice")] { + MaybeUninit::slice_assume_init_ref(slice) + } else { + &*(slice as *const [MaybeUninit] as *const [K]) + } + } } } } @@ -458,8 +594,8 @@ impl<'a, K, V, Type> NodeRef, K, V, Type> { } /// Offers exclusive access to the leaf portion of a leaf or internal node. - fn into_leaf_mut(mut self) -> &'a mut LeafNode { - let ptr = Self::as_leaf_ptr(&mut self); + fn into_leaf_mut(self) -> &'a mut LeafNode { + let ptr = Self::as_leaf_ptr(&self); // SAFETY: we have exclusive access to the entire node. unsafe { &mut *ptr } } @@ -538,18 +674,33 @@ impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::Internal> { impl<'a, K, V, Type> NodeRef, K, V, Type> { /// # Safety /// - The node has more than `idx` initialized elements. - unsafe fn into_key_val_mut_at(mut self, idx: usize) -> (&'a K, &'a mut V) { + unsafe fn into_key_val_mut_at(self, idx: usize) -> (&'a K, &'a mut V) { // We only create a reference to the one element we are interested in, // to avoid aliasing with outstanding references to other elements, // in particular, those returned to the caller in earlier iterations. - let leaf = Self::as_leaf_ptr(&mut self); + let leaf = Self::as_leaf_ptr(&self); let keys = unsafe { ptr::addr_of!((*leaf).keys) }; let vals = unsafe { ptr::addr_of_mut!((*leaf).vals) }; // We must coerce to unsized array pointers because of Rust issue #74679. let keys: *const [_] = keys; let vals: *mut [_] = vals; + + #[cfg(not(feature = "slice_ptr_get"))] + let (keys, vals) = unsafe { + let (keys, vals) = (&*keys, &mut *vals); + debug_assert!(idx < keys.len()); + debug_assert!(idx < vals.len()); + (keys, vals) + }; + + #[cfg_attr( + not(feature = "slice_ptr_get"), + allow(clippy::needless_borrow, clippy::borrow_deref_ref) + )] let key = unsafe { (&*keys.get_unchecked(idx)).assume_init_ref() }; + #[cfg_attr(not(feature = "slice_ptr_get"), allow(clippy::needless_borrow))] let val = unsafe { (&mut *vals.get_unchecked_mut(idx)).assume_init_mut() }; + (key, val) } } @@ -924,9 +1075,12 @@ pub enum LeftOrRight { /// the keys, values and edges to the right of the split point become the right child. fn splitpoint(edge_idx: usize) -> (usize, LeftOrRight) { debug_assert!(edge_idx <= CAPACITY); + + const EDGE_IDX_LEFT_OF_LEFT_OF_CENTER: usize = EDGE_IDX_LEFT_OF_CENTER - 1; + // Rust issue #74834 tries to explain these symmetric rules. match edge_idx { - 0..EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, LeftOrRight::Left(edge_idx)), + 0..=EDGE_IDX_LEFT_OF_LEFT_OF_CENTER => (KV_IDX_CENTER - 1, LeftOrRight::Left(edge_idx)), EDGE_IDX_LEFT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Left(edge_idx)), EDGE_IDX_RIGHT_OF_CENTER => (KV_IDX_CENTER, LeftOrRight::Right(0)), _ => ( @@ -1111,6 +1265,7 @@ impl /// `edge.descend().ascend().unwrap()` and `node.ascend().unwrap().descend()` should /// both, upon success, do nothing. pub fn descend(self) -> NodeRef { + #[allow(clippy::let_unit_value)] let _ = BorrowType::TRAVERSAL_PERMIT; // We need to use raw pointers to nodes because, if BorrowType is // marker::ValMut, there might be outstanding mutable references to @@ -1250,7 +1405,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Leaf>, mark let kv = self.split_leaf_data(&mut new_node); - let right = NodeRef::from_new_leaf(new_node); + let right = NodeRef::from_new_leaf::(new_node); SplitResult { left: self.node, kv, @@ -1299,7 +1454,7 @@ impl<'a, K: 'a, V: 'a> Handle, K, V, marker::Internal>, ); let height = self.node.height; - let right = NodeRef::from_new_internal(new_node, height); + let right = NodeRef::from_new_internal::(new_node, height); SplitResult { left: self.node, @@ -1437,7 +1592,7 @@ impl<'a, K: 'a, V: 'a> BalancingContext<'a, K, V> { ); slice_remove( - &mut parent_node.edge_area_mut(..old_parent_len + 1), + parent_node.edge_area_mut(..old_parent_len + 1), parent_idx + 1, ); parent_node.correct_childrens_parent_links(parent_idx + 1..old_parent_len); diff --git a/src/btree/node/tests.rs b/src/btree/node/tests.rs index d1b9128..c56aca2 100644 --- a/src/btree/node/tests.rs +++ b/src/btree/node/tests.rs @@ -1,8 +1,8 @@ use super::super::navigate; use super::*; -use crate::alloc::Global; -use crate::fmt::Debug; -use crate::string::String; +use crate::Global; +use alloc::fmt::Debug; +use alloc::string::String; impl<'a, K: 'a, V: 'a> NodeRef, K, V, marker::LeafOrInternal> { // Asserts that the back pointer in each reachable node points to its parent. diff --git a/src/btree/remove.rs b/src/btree/remove.rs index 70e016f..1fe94cc 100644 --- a/src/btree/remove.rs +++ b/src/btree/remove.rs @@ -1,6 +1,6 @@ use super::map::MIN_LEN; use super::node::{marker, ForceResult::*, Handle, LeftOrRight::*, NodeRef}; -use core::alloc::Allocator; +use crate::Allocator; impl<'a, K: 'a, V: 'a> Handle, K, V, marker::LeafOrInternal>, marker::KV> { /// Removes a key-value pair from the tree, and returns that pair, as well as diff --git a/src/btree/search.rs b/src/btree/search.rs index 5730fa8..8b71ee9 100644 --- a/src/btree/search.rs +++ b/src/btree/search.rs @@ -2,8 +2,11 @@ use core::borrow::Borrow; use core::cmp::Ordering; use core::ops::{Bound, RangeBounds}; +use crate::{Sortable, Comparator}; + use super::node::{marker, ForceResult::*, Handle, NodeRef}; +use cfg_if::cfg_if; use SearchBound::*; use SearchResult::*; @@ -48,13 +51,14 @@ impl NodeRef( mut self, key: &Q, + comparator: &impl Comparator, ) -> SearchResult where - Q: Ord, - K: Borrow, + K: Sortable, + Q: Borrow, { loop { - self = match self.search_node(key) { + self = match self.search_node(key, comparator) { Found(handle) => return Found(handle), GoDown(handle) => match handle.force() { Leaf(leaf) => return GoDown(leaf), @@ -81,6 +85,7 @@ impl NodeRef( mut self, + comparator: &impl Comparator, range: &'r R, ) -> Result< ( @@ -93,31 +98,44 @@ impl NodeRef, marker::Edge>, > where - Q: Ord, - K: Borrow, + K: Sortable, + Q: Borrow, R: RangeBounds, { // Determine if map or set is being searched + #[cfg(feature = "specialization")] let is_set = ::is_set_val(); // Inlining these variables should be avoided. We assume the bounds reported by `range` // remain the same, but an adversarial implementation could change between calls (#81138). let (start, end) = (range.start_bound(), range.end_bound()); match (start, end) { - (Bound::Excluded(s), Bound::Excluded(e)) if s == e => { - if is_set { - panic!("range start and end are equal and excluded in BTreeSet") - } else { - panic!("range start and end are equal and excluded in BTreeMap") + (Bound::Excluded(s), Bound::Excluded(e)) if comparator.cmp(s.borrow(), e.borrow()).is_eq() => { + cfg_if! { + if #[cfg(feature = "specialization")] { + if is_set { + panic!("range start and end are equal and excluded in BTreeSet") + } else { + panic!("range start and end are equal and excluded in BTreeMap") + } + } else { + panic!("range start and end are equal and excluded"); + } } } (Bound::Included(s) | Bound::Excluded(s), Bound::Included(e) | Bound::Excluded(e)) - if s > e => + if comparator.cmp(s.borrow(), e.borrow()).is_gt() => { - if is_set { - panic!("range start is greater than range end in BTreeSet") - } else { - panic!("range start is greater than range end in BTreeMap") + cfg_if! { + if #[cfg(feature = "specialization")] { + if is_set { + panic!("range start is greater than range end in BTreeSet") + } else { + panic!("range start is greater than range end in BTreeMap") + } + } else { + panic!("range start is greater than range end") + } } } _ => {} @@ -125,9 +143,9 @@ impl NodeRef NodeRef( self, + comparator: &impl Comparator, bound: SearchBound<&'r Q>, ) -> (Handle, SearchBound<&'r Q>) where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, { - let (edge_idx, bound) = self.find_lower_bound_index(bound); + let (edge_idx, bound) = self.find_lower_bound_index(comparator, bound); let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -171,13 +190,14 @@ impl NodeRef( self, + comparator: &impl Comparator, bound: SearchBound<&'r Q>, ) -> (Handle, SearchBound<&'r Q>) where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, { - let (edge_idx, bound) = unsafe { self.find_upper_bound_index(bound, 0) }; + let (edge_idx, bound) = unsafe { self.find_upper_bound_index(comparator, bound, 0) }; let edge = unsafe { Handle::new_edge(self, edge_idx) }; (edge, bound) } @@ -191,12 +211,16 @@ impl NodeRef { /// /// The result is meaningful only if the tree is ordered by key, like the tree /// in a `BTreeMap` is. - pub fn search_node(self, key: &Q) -> SearchResult + pub fn search_node( + self, + key: &Q, + comparator: &impl Comparator, + ) -> SearchResult where - Q: Ord, - K: Borrow, + K: Sortable, + Q: Borrow, { - match unsafe { self.find_key_index(key, 0) } { + match unsafe { self.find_key_index(key, comparator, 0) } { IndexResult::KV(idx) => Found(unsafe { Handle::new_kv(self, idx) }), IndexResult::Edge(idx) => GoDown(unsafe { Handle::new_edge(self, idx) }), } @@ -210,10 +234,15 @@ impl NodeRef { /// /// # Safety /// `start_index` must be a valid edge index for the node. - unsafe fn find_key_index(&self, key: &Q, start_index: usize) -> IndexResult + unsafe fn find_key_index( + &self, + key: &Q, + comparator: &impl Comparator, + start_index: usize, + ) -> IndexResult where - Q: Ord, - K: Borrow, + K: Sortable, + Q: Borrow, { let node = self.reborrow(); let keys = node.keys(); @@ -222,7 +251,7 @@ impl NodeRef { .iter() .enumerate() { - match key.cmp(k.borrow()) { + match comparator.cmp(key.borrow(), k.borrow()) { Ordering::Greater => {} Ordering::Equal => return IndexResult::KV(start_index + offset), Ordering::Less => return IndexResult::Edge(start_index + offset), @@ -238,18 +267,19 @@ impl NodeRef { /// The result is meaningful only if the tree is ordered by key. fn find_lower_bound_index<'r, Q>( &self, + comparator: &impl Comparator, bound: SearchBound<&'r Q>, ) -> (usize, SearchBound<&'r Q>) where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, { match bound { - Included(key) => match unsafe { self.find_key_index(key, 0) } { + Included(key) => match unsafe { self.find_key_index(key, comparator, 0) } { IndexResult::KV(idx) => (idx, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match unsafe { self.find_key_index(key, 0) } { + Excluded(key) => match unsafe { self.find_key_index(key, comparator, 0) } { IndexResult::KV(idx) => (idx + 1, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, @@ -265,19 +295,20 @@ impl NodeRef { /// `start_index` must be a valid edge index for the node. unsafe fn find_upper_bound_index<'r, Q>( &self, + comparator: &impl Comparator, bound: SearchBound<&'r Q>, start_index: usize, ) -> (usize, SearchBound<&'r Q>) where - Q: ?Sized + Ord, - K: Borrow, + K: Sortable, + Q: ?Sized + Borrow, { match bound { - Included(key) => match unsafe { self.find_key_index(key, start_index) } { + Included(key) => match unsafe { self.find_key_index(key, comparator, start_index) } { IndexResult::KV(idx) => (idx + 1, AllExcluded), IndexResult::Edge(idx) => (idx, bound), }, - Excluded(key) => match unsafe { self.find_key_index(key, start_index) } { + Excluded(key) => match unsafe { self.find_key_index(key, comparator, start_index) } { IndexResult::KV(idx) => (idx, AllIncluded), IndexResult::Edge(idx) => (idx, bound), }, diff --git a/src/btree/set.rs b/src/btree/set.rs index 174a26a..51a113f 100644 --- a/src/btree/set.rs +++ b/src/btree/set.rs @@ -1,7 +1,7 @@ // This is pretty much entirely stolen from TreeSet, since BTreeMap has an identical interface // to TreeMap -use crate::vec::Vec; +use alloc::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; @@ -11,12 +11,14 @@ use core::iter::{FromIterator, FusedIterator, Peekable}; use core::mem::ManuallyDrop; use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub}; +use crate::{Sortable, MinCmpFn, StdOrd, Comparator}; + use super::map::{BTreeMap, Keys}; use super::merge_iter::MergeIterInner; use super::set_val::SetValZST; use super::Recover; -use crate::alloc::{Allocator, Global}; +use crate::{Allocator, Global}; // FIXME(conventions): implement bounded iterators @@ -42,11 +44,11 @@ use crate::alloc::{Allocator, Global}; /// # Examples /// /// ``` -/// use std::collections::BTreeSet; +/// use copse::BTreeSet; /// /// // Type inference lets us omit an explicit type signature (which /// // would be `BTreeSet<&str>` in this example). -/// let mut books = BTreeSet::new(); +/// let mut books = BTreeSet::default(); /// /// // Add some books. /// books.insert("A Dance With Dragons"); @@ -72,52 +74,54 @@ use crate::alloc::{Allocator, Global}; /// A `BTreeSet` with a known list of items can be initialized from an array: /// /// ``` -/// use std::collections::BTreeSet; +/// use copse::BTreeSet; /// /// let set = BTreeSet::from([1, 2, 3]); /// ``` -#[stable(feature = "rust1", since = "1.0.0")] -#[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")] +// #[stable(feature = "rust1", since = "1.0.0")] +// #[cfg_attr(not(test), rustc_diagnostic_item = "BTreeSet")] pub struct BTreeSet< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C = MinCmpFn, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { - map: BTreeMap, + map: BTreeMap, } -#[stable(feature = "rust1", since = "1.0.0")] -impl Hash for BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Hash for BTreeSet { fn hash(&self, state: &mut H) { self.map.hash(state) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialEq for BTreeSet { - fn eq(&self, other: &BTreeSet) -> bool { +// #[stable(feature = "rust1", since = "1.0.0")] +impl PartialEq for BTreeSet { + fn eq(&self, other: &BTreeSet) -> bool { self.map.eq(&other.map) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Eq for BTreeSet {} +// #[stable(feature = "rust1", since = "1.0.0")] +impl Eq for BTreeSet {} -#[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for BTreeSet { - fn partial_cmp(&self, other: &BTreeSet) -> Option { +// #[stable(feature = "rust1", since = "1.0.0")] +impl PartialOrd for BTreeSet { + fn partial_cmp(&self, other: &BTreeSet) -> Option { self.map.partial_cmp(&other.map) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Ord for BTreeSet { - fn cmp(&self, other: &BTreeSet) -> Ordering { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Ord for BTreeSet { + fn cmp(&self, other: &BTreeSet) -> Ordering { self.map.cmp(&other.map) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for BTreeSet { fn clone(&self) -> Self { BTreeSet { map: self.map.clone(), @@ -136,12 +140,12 @@ impl Clone for BTreeSet { /// /// [`iter`]: BTreeSet::iter #[must_use = "iterators are lazy and do nothing unless consumed"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Iter<'a, T: 'a> { iter: Keys<'a, T, SetValZST>, } -#[stable(feature = "collection_debug", since = "1.17.0")] +// #[stable(feature = "collection_debug", since = "1.17.0")] impl fmt::Debug for Iter<'_, T> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Iter").field(&self.iter.clone()).finish() @@ -155,11 +159,12 @@ impl fmt::Debug for Iter<'_, T> { /// /// [`into_iter`]: BTreeSet#method.into_iter /// [`IntoIterator`]: core::iter::IntoIterator -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] #[derive(Debug)] pub struct IntoIter< T, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { iter: super::map::IntoIter, } @@ -172,7 +177,7 @@ pub struct IntoIter< /// [`range`]: BTreeSet::range #[must_use = "iterators are lazy and do nothing unless consumed"] #[derive(Debug)] -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] pub struct Range<'a, T: 'a> { iter: super::map::Range<'a, T, SetValZST>, } @@ -185,15 +190,18 @@ pub struct Range<'a, T: 'a> { /// [`difference`]: BTreeSet::difference #[must_use = "this returns the difference as an iterator, \ without modifying either input set"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Difference< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { - inner: DifferenceInner<'a, T, A>, + inner: DifferenceInner<'a, T, C, A>, + comparator: &'a C, } -enum DifferenceInner<'a, T: 'a, A: Allocator + Clone> { +enum DifferenceInner<'a, T: 'a, C, A: Allocator + Clone> { Stitch { // iterate all of `self` and some of `other`, spotting matches along the way self_iter: Iter<'a, T>, @@ -202,13 +210,17 @@ enum DifferenceInner<'a, T: 'a, A: Allocator + Clone> { Search { // iterate `self`, look up in `other` self_iter: Iter<'a, T>, - other_set: &'a BTreeSet, + other_set: &'a BTreeSet, }, Iterate(Iter<'a, T>), // simply produce all elements in `self` } // Explicit Debug impl necessary because of issue #26925 -impl Debug for DifferenceInner<'_, T, A> { +impl Debug for DifferenceInner<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { DifferenceInner::Stitch { @@ -232,8 +244,12 @@ impl Debug for DifferenceInner<'_, T, A> { } } -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Difference<'_, T, A> { +// #[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Difference<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Difference").field(&self.inner).finish() } @@ -247,11 +263,11 @@ impl fmt::Debug for Difference<'_, T, A> { /// [`symmetric_difference`]: BTreeSet::symmetric_difference #[must_use = "this returns the difference as an iterator, \ without modifying either input set"] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct SymmetricDifference<'a, T: 'a>(MergeIterInner>); +// #[stable(feature = "rust1", since = "1.0.0")] +pub struct SymmetricDifference<'a, T: 'a, C>(MergeIterInner>, &'a C); -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for SymmetricDifference<'_, T> { +// #[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for SymmetricDifference<'_, T, C> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("SymmetricDifference").field(&self.0).finish() } @@ -265,15 +281,18 @@ impl fmt::Debug for SymmetricDifference<'_, T> { /// [`intersection`]: BTreeSet::intersection #[must_use = "this returns the intersection as an iterator, \ without modifying either input set"] -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] pub struct Intersection< 'a, T: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + C, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > { - inner: IntersectionInner<'a, T, A>, + inner: IntersectionInner<'a, T, C, A>, + comparator: &'a C, } -enum IntersectionInner<'a, T: 'a, A: Allocator + Clone> { +enum IntersectionInner<'a, T: 'a, C, A: Allocator + Clone> { Stitch { // iterate similarly sized sets jointly, spotting matches along the way a: Iter<'a, T>, @@ -282,13 +301,17 @@ enum IntersectionInner<'a, T: 'a, A: Allocator + Clone> { Search { // iterate a small set, look up in the large set small_iter: Iter<'a, T>, - large_set: &'a BTreeSet, + large_set: &'a BTreeSet, }, Answer(Option<&'a T>), // return a specific element or emptiness } // Explicit Debug impl necessary because of issue #26925 -impl Debug for IntersectionInner<'_, T, A> { +impl Debug for IntersectionInner<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { IntersectionInner::Stitch { a, b } => f @@ -309,8 +332,12 @@ impl Debug for IntersectionInner<'_, T, A> { } } -#[stable(feature = "collection_debug", since = "1.17.0")] -impl Debug for Intersection<'_, T, A> { +// #[stable(feature = "collection_debug", since = "1.17.0")] +impl Debug for Intersection<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Intersection").field(&self.inner).finish() } @@ -324,11 +351,11 @@ impl Debug for Intersection<'_, T, A> { /// [`union`]: BTreeSet::union #[must_use = "this returns the union as an iterator, \ without modifying either input set"] -#[stable(feature = "rust1", since = "1.0.0")] -pub struct Union<'a, T: 'a>(MergeIterInner>); +// #[stable(feature = "rust1", since = "1.0.0")] +pub struct Union<'a, T: 'a, C>(MergeIterInner>, &'a C); -#[stable(feature = "collection_debug", since = "1.17.0")] -impl fmt::Debug for Union<'_, T> { +// #[stable(feature = "collection_debug", since = "1.17.0")] +impl fmt::Debug for Union<'_, T, C> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_tuple("Union").field(&self.0).finish() } @@ -342,8 +369,8 @@ impl fmt::Debug for Union<'_, T> { // and it's a power of two to make that division cheap. const ITER_PERFORMANCE_TIPPING_SIZE_DIFF: usize = 16; -impl BTreeSet { - /// Makes a new, empty `BTreeSet`. +impl BTreeSet { + /// Makes a new, empty `BTreeSet` ordered by the given `comparator`. /// /// Does not allocate anything on its own. /// @@ -351,38 +378,42 @@ impl BTreeSet { /// /// ``` /// # #![allow(unused_mut)] - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set: BTreeSet = BTreeSet::new(); + /// let mut set: BTreeSet = BTreeSet::default(); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_stable(feature = "const_btree_new", since = "1.66.0")] #[must_use] - pub const fn new() -> BTreeSet { + pub const fn new(comparator: C) -> BTreeSet { BTreeSet { - map: BTreeMap::new(), + map: BTreeMap::new(comparator), } } } -impl BTreeSet { - /// Makes a new `BTreeSet` with a reasonable choice of B. - /// +impl BTreeSet +where + T: Sortable, + C: Comparator, +{ + /// Makes a new `BTreeSet` with a reasonable choice of B ordered by the given `comparator`. + /// /// # Examples - /// + /// /// ``` - /// # #![allow(unused_mut)] - /// # #![feature(allocator_api)] - /// # #![feature(btreemap_alloc)] - /// use std::collections::BTreeSet; + /// #![feature(allocator_api)] + /// + /// use copse::BTreeSet; /// use std::alloc::Global; - /// - /// let mut set: BTreeSet = BTreeSet::new_in(Global); + /// + /// let mut set: BTreeSet = BTreeSet::new_in(Ord::cmp, Global); /// ``` - #[unstable(feature = "btreemap_alloc", issue = "32838")] - pub fn new_in(alloc: A) -> BTreeSet { + // #[unstable(feature = "btreemap_alloc", issue = "32838")] + #[cfg(feature = "allocator_api")] + pub fn new_in(comparator: C, alloc: A) -> BTreeSet { BTreeSet { - map: BTreeMap::new_in(alloc), + map: BTreeMap::new_in(comparator, alloc), } } @@ -401,23 +432,22 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// use std::ops::Bound::Included; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// set.insert(3); /// set.insert(5); /// set.insert(8); - /// for &elem in set.range((Included(&4), Included(&8))) { + /// for &elem in set.range::((Included(&4), Included(&8))) { /// println!("{elem}"); /// } /// assert_eq!(Some(&5), set.range(4..).next()); /// ``` - #[stable(feature = "btree_range", since = "1.17.0")] + // #[stable(feature = "btree_range", since = "1.17.0")] pub fn range(&self, range: R) -> Range<'_, T> where - K: Ord, - T: Borrow + Ord, + K: Borrow, R: RangeBounds, { Range { @@ -432,30 +462,28 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// a.insert(2); /// - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// b.insert(2); /// b.insert(3); /// /// let diff: Vec<_> = a.difference(&b).cloned().collect(); /// assert_eq!(diff, [1]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T, A> - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn difference<'a>(&'a self, other: &'a BTreeSet) -> Difference<'a, T, C, A> { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { (self_min, self_max) } else { return Difference { inner: DifferenceInner::Iterate(self.iter()), + comparator: &self.map.comparator, }; }; let (other_min, other_max) = @@ -464,10 +492,14 @@ impl BTreeSet { } else { return Difference { inner: DifferenceInner::Iterate(self.iter()), + comparator: &self.map.comparator, }; }; Difference { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + inner: match ( + self.map.comparator.cmp(self_min.borrow(), other_max.borrow()), + self.map.comparator.cmp(self_max.borrow(), other_min.borrow()), + ) { (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), (Equal, _) => { let mut self_iter = self.iter(); @@ -490,6 +522,7 @@ impl BTreeSet { other_iter: other.iter().peekable(), }, }, + comparator: &self.map.comparator, } } @@ -500,28 +533,25 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// a.insert(2); /// - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// b.insert(2); /// b.insert(3); /// /// let sym_diff: Vec<_> = a.symmetric_difference(&b).cloned().collect(); /// assert_eq!(sym_diff, [1, 3]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn symmetric_difference<'a>( &'a self, - other: &'a BTreeSet, - ) -> SymmetricDifference<'a, T> - where - T: Ord, - { - SymmetricDifference(MergeIterInner::new(self.iter(), other.iter())) + other: &'a BTreeSet, + ) -> SymmetricDifference<'a, T, C> { + SymmetricDifference(MergeIterInner::new(self.iter(), other.iter()), &self.map.comparator) } /// Visits the elements representing the intersection, @@ -531,30 +561,28 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// a.insert(2); /// - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// b.insert(2); /// b.insert(3); /// /// let intersection: Vec<_> = a.intersection(&b).cloned().collect(); /// assert_eq!(intersection, [2]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T, A> - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn intersection<'a>(&'a self, other: &'a BTreeSet) -> Intersection<'a, T, C, A> { let (self_min, self_max) = if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { (self_min, self_max) } else { return Intersection { inner: IntersectionInner::Answer(None), + comparator: &self.map.comparator, }; }; let (other_min, other_max) = @@ -563,10 +591,14 @@ impl BTreeSet { } else { return Intersection { inner: IntersectionInner::Answer(None), + comparator: &self.map.comparator, }; }; Intersection { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + inner: match ( + self.map.comparator.cmp(self_min.borrow(), other_max.borrow()), + self.map.comparator.cmp(self_max.borrow(), other_min.borrow()), + ) { (Greater, _) | (_, Less) => IntersectionInner::Answer(None), (Equal, _) => IntersectionInner::Answer(Some(self_min)), (_, Equal) => IntersectionInner::Answer(Some(self_max)), @@ -587,6 +619,7 @@ impl BTreeSet { b: other.iter(), }, }, + comparator: &self.map.comparator, } } @@ -597,43 +630,20 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// b.insert(2); /// /// let union: Vec<_> = a.union(&b).cloned().collect(); /// assert_eq!(union, [1, 2]); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T> - where - T: Ord, - { - Union(MergeIterInner::new(self.iter(), other.iter())) - } - - /// Clears the set, removing all elements. - /// - /// # Examples - /// - /// ``` - /// use std::collections::BTreeSet; - /// - /// let mut v = BTreeSet::new(); - /// v.insert(1); - /// v.clear(); - /// assert!(v.is_empty()); - /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn clear(&mut self) - where - A: Clone, - { - self.map.clear() + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn union<'a>(&'a self, other: &'a BTreeSet) -> Union<'a, T, C> { + Union(MergeIterInner::new(self.iter(), other.iter()), &self.map.comparator) } /// Returns `true` if the set contains an element equal to the value. @@ -645,17 +655,16 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.contains(&1), true); /// assert_eq!(set.contains(&4), false); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn contains(&self, value: &Q) -> bool where - T: Borrow + Ord, - Q: Ord, + Q: Borrow, { self.map.contains_key(value) } @@ -670,17 +679,16 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.get(&2), Some(&2)); /// assert_eq!(set.get(&4), None); /// ``` - #[stable(feature = "set_recovery", since = "1.9.0")] + // #[stable(feature = "set_recovery", since = "1.9.0")] pub fn get(&self, value: &Q) -> Option<&T> where - T: Borrow + Ord, - Q: Ord, + Q: Borrow, { Recover::get(&self.map, value) } @@ -691,10 +699,10 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let a = BTreeSet::from([1, 2, 3]); - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// /// assert_eq!(a.is_disjoint(&b), true); /// b.insert(4); @@ -703,11 +711,8 @@ impl BTreeSet { /// assert_eq!(a.is_disjoint(&b), false); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_disjoint(&self, other: &BTreeSet) -> bool - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_disjoint(&self, other: &BTreeSet) -> bool { self.intersection(other).next().is_none() } @@ -717,10 +722,10 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let sup = BTreeSet::from([1, 2, 3]); - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// assert_eq!(set.is_subset(&sup), true); /// set.insert(2); @@ -729,11 +734,8 @@ impl BTreeSet { /// assert_eq!(set.is_subset(&sup), false); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_subset(&self, other: &BTreeSet) -> bool - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_subset(&self, other: &BTreeSet) -> bool { // Same result as self.difference(other).next().is_none() // but the code below is faster (hugely in some cases). if self.len() > other.len() { @@ -752,14 +754,14 @@ impl BTreeSet { return false; // other is empty }; let mut self_iter = self.iter(); - match self_min.cmp(other_min) { + match self.map.comparator.cmp(self_min.borrow(), other_min.borrow()) { Less => return false, Equal => { self_iter.next(); } Greater => (), } - match self_max.cmp(other_max) { + match self.map.comparator.cmp(self_max.borrow(), other_max.borrow()) { Greater => return false, Equal => { self_iter.next_back(); @@ -778,7 +780,9 @@ impl BTreeSet { other_iter.next_back(); let mut self_next = self_iter.next(); while let Some(self1) = self_next { - match other_iter.next().map_or(Less, |other1| self1.cmp(other1)) { + match other_iter.next().map_or(Less, |other1| { + self.map.comparator.cmp(self1.borrow(), other1.borrow()) + }) { Less => return false, Equal => self_next = self_iter.next(), Greater => (), @@ -794,10 +798,10 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let sub = BTreeSet::from([1, 2]); - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// assert_eq!(set.is_superset(&sub), false); /// @@ -809,11 +813,8 @@ impl BTreeSet { /// assert_eq!(set.is_superset(&sub), true); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - pub fn is_superset(&self, other: &BTreeSet) -> bool - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn is_superset(&self, other: &BTreeSet) -> bool { other.is_subset(self) } @@ -825,9 +826,9 @@ impl BTreeSet { /// Basic usage: /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// assert_eq!(set.first(), None); /// set.insert(1); /// assert_eq!(set.first(), Some(&1)); @@ -835,11 +836,8 @@ impl BTreeSet { /// assert_eq!(set.first(), Some(&1)); /// ``` #[must_use] - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn first(&self) -> Option<&T> - where - T: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn first(&self) -> Option<&T> { self.map.first_key_value().map(|(k, _)| k) } @@ -851,9 +849,9 @@ impl BTreeSet { /// Basic usage: /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// assert_eq!(set.last(), None); /// set.insert(1); /// assert_eq!(set.last(), Some(&1)); @@ -861,11 +859,8 @@ impl BTreeSet { /// assert_eq!(set.last(), Some(&2)); /// ``` #[must_use] - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn last(&self) -> Option<&T> - where - T: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn last(&self) -> Option<&T> { self.map.last_key_value().map(|(k, _)| k) } @@ -875,9 +870,9 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// set.insert(1); /// while let Some(n) = set.pop_first() { @@ -885,11 +880,8 @@ impl BTreeSet { /// } /// assert!(set.is_empty()); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn pop_first(&mut self) -> Option - where - T: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_first(&mut self) -> Option { self.map.pop_first().map(|kv| kv.0) } @@ -899,9 +891,9 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// set.insert(1); /// while let Some(n) = set.pop_last() { @@ -909,11 +901,8 @@ impl BTreeSet { /// } /// assert!(set.is_empty()); /// ``` - #[stable(feature = "map_first_last", since = "1.66.0")] - pub fn pop_last(&mut self) -> Option - where - T: Ord, - { + // #[stable(feature = "map_first_last", since = "1.66.0")] + pub fn pop_last(&mut self) -> Option { self.map.pop_last().map(|kv| kv.0) } @@ -933,19 +922,16 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// assert_eq!(set.insert(2), true); /// assert_eq!(set.insert(2), false); /// assert_eq!(set.len(), 1); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] - pub fn insert(&mut self, value: T) -> bool - where - T: Ord, - { + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn insert(&mut self, value: T) -> bool { self.map.insert(value, SetValZST::default()).is_none() } @@ -955,21 +941,18 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// set.insert(Vec::::new()); /// /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 0); /// set.replace(Vec::with_capacity(10)); /// assert_eq!(set.get(&[][..]).unwrap().capacity(), 10); /// ``` - #[stable(feature = "set_recovery", since = "1.9.0")] - pub fn replace(&mut self, value: T) -> Option - where - T: Ord, - { - Recover::replace(&mut self.map, value) + // #[stable(feature = "set_recovery", since = "1.9.0")] + pub fn replace(&mut self, value: T) -> Option { + Recover::::replace(&mut self.map, value) } /// If the set contains an element equal to the value, removes it from the @@ -982,19 +965,18 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut set = BTreeSet::new(); + /// let mut set = BTreeSet::default(); /// /// set.insert(2); /// assert_eq!(set.remove(&2), true); /// assert_eq!(set.remove(&2), false); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn remove(&mut self, value: &Q) -> bool where - T: Borrow + Ord, - Q: Ord, + Q: Borrow, { self.map.remove(value).is_some() } @@ -1009,17 +991,16 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let mut set = BTreeSet::from([1, 2, 3]); /// assert_eq!(set.take(&2), Some(2)); /// assert_eq!(set.take(&2), None); /// ``` - #[stable(feature = "set_recovery", since = "1.9.0")] + // #[stable(feature = "set_recovery", since = "1.9.0")] pub fn take(&mut self, value: &Q) -> Option where - T: Borrow + Ord, - Q: Ord, + Q: Borrow, { Recover::take(&mut self.map, value) } @@ -1032,17 +1013,16 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let mut set = BTreeSet::from([1, 2, 3, 4, 5, 6]); /// // Keep only the even numbers. /// set.retain(|&k| k % 2 == 0); /// assert!(set.iter().eq([2, 4, 6].iter())); /// ``` - #[stable(feature = "btree_retain", since = "1.53.0")] + // #[stable(feature = "btree_retain", since = "1.53.0")] pub fn retain(&mut self, mut f: F) where - T: Ord, F: FnMut(&T) -> bool, { self.drain_filter(|v| !f(v)); @@ -1053,14 +1033,14 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// a.insert(2); /// a.insert(3); /// - /// let mut b = BTreeSet::new(); + /// let mut b = BTreeSet::default(); /// b.insert(3); /// b.insert(4); /// b.insert(5); @@ -1076,11 +1056,11 @@ impl BTreeSet { /// assert!(a.contains(&4)); /// assert!(a.contains(&5)); /// ``` - #[stable(feature = "btree_append", since = "1.11.0")] + // #[stable(feature = "btree_append", since = "1.11.0")] pub fn append(&mut self, other: &mut Self) where - T: Ord, A: Clone, + C: Clone, { self.map.append(&mut other.map); } @@ -1093,9 +1073,9 @@ impl BTreeSet { /// Basic usage: /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut a = BTreeSet::new(); + /// let mut a = BTreeSet::default(); /// a.insert(1); /// a.insert(2); /// a.insert(3); @@ -1114,11 +1094,12 @@ impl BTreeSet { /// assert!(b.contains(&17)); /// assert!(b.contains(&41)); /// ``` - #[stable(feature = "btree_split_off", since = "1.11.0")] + // #[stable(feature = "btree_split_off", since = "1.11.0")] pub fn split_off(&mut self, value: &Q) -> Self where - T: Borrow + Ord, A: Clone, + C: Clone, + Q: Borrow, { BTreeSet { map: self.map.split_off(value), @@ -1145,8 +1126,7 @@ impl BTreeSet { /// Splitting a set into even and odd values, reusing the original set: /// /// ``` - /// #![feature(btree_drain_filter)] - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let mut set: BTreeSet = (0..8).collect(); /// let evens: BTreeSet<_> = set.drain_filter(|v| v % 2 == 0).collect(); @@ -1154,15 +1134,37 @@ impl BTreeSet { /// assert_eq!(evens.into_iter().collect::>(), vec![0, 2, 4, 6]); /// assert_eq!(odds.into_iter().collect::>(), vec![1, 3, 5, 7]); /// ``` - #[unstable(feature = "btree_drain_filter", issue = "70530")] + // #[unstable(feature = "btree_drain_filter", issue = "70530")] pub fn drain_filter<'a, F>(&'a mut self, pred: F) -> DrainFilter<'a, T, F, A> where - T: Ord, F: 'a + FnMut(&T) -> bool, { let (inner, alloc) = self.map.drain_filter_inner(); DrainFilter { pred, inner, alloc } } +} + +impl BTreeSet { + /// Clears the set, removing all elements. + /// + /// # Examples + /// + /// ``` + /// use copse::BTreeSet; + /// + /// let mut v = BTreeSet::default(); + /// v.insert(1); + /// v.clear(); + /// assert!(v.is_empty()); + /// ``` + // #[stable(feature = "rust1", since = "1.0.0")] + pub fn clear(&mut self) + where + A: Clone, + C: Copy, + { + self.map.clear() + } /// Gets an iterator that visits the elements in the `BTreeSet` in ascending /// order. @@ -1170,7 +1172,7 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set = BTreeSet::from([1, 2, 3]); /// let mut set_iter = set.iter(); @@ -1183,7 +1185,7 @@ impl BTreeSet { /// Values returned by the iterator are returned in ascending order: /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set = BTreeSet::from([3, 1, 2]); /// let mut set_iter = set.iter(); @@ -1192,7 +1194,7 @@ impl BTreeSet { /// assert_eq!(set_iter.next(), Some(&3)); /// assert_eq!(set_iter.next(), None); /// ``` - #[stable(feature = "rust1", since = "1.0.0")] + // #[stable(feature = "rust1", since = "1.0.0")] pub fn iter(&self) -> Iter<'_, T> { Iter { iter: self.map.keys(), @@ -1204,20 +1206,20 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut v = BTreeSet::new(); + /// let mut v = BTreeSet::default(); /// assert_eq!(v.len(), 0); /// v.insert(1); /// assert_eq!(v.len(), 1); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable( - feature = "const_btree_len", - issue = "71835", - implied_by = "const_btree_new" - )] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_unstable( + // feature = "const_btree_len", + // issue = "71835", + // implied_by = "const_btree_new" + // )] pub const fn len(&self) -> usize { self.map.len() } @@ -1227,54 +1229,66 @@ impl BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// - /// let mut v = BTreeSet::new(); + /// let mut v = BTreeSet::default(); /// assert!(v.is_empty()); /// v.insert(1); /// assert!(!v.is_empty()); /// ``` #[must_use] - #[stable(feature = "rust1", since = "1.0.0")] - #[rustc_const_unstable( - feature = "const_btree_len", - issue = "71835", - implied_by = "const_btree_new" - )] + // #[stable(feature = "rust1", since = "1.0.0")] + // #[rustc_const_unstable( + // feature = "const_btree_len", + // issue = "71835", + // implied_by = "const_btree_new" + // )] pub const fn is_empty(&self) -> bool { self.len() == 0 } } -#[stable(feature = "rust1", since = "1.0.0")] -impl FromIterator for BTreeSet { - fn from_iter>(iter: I) -> BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl FromIterator for BTreeSet> +where + T: Sortable, + T::State: Ord, +{ + fn from_iter>(iter: I) -> BTreeSet> { let mut inputs: Vec<_> = iter.into_iter().collect(); if inputs.is_empty() { - return BTreeSet::new(); + return BTreeSet::default(); } // use stable sort to preserve the insertion order. - inputs.sort(); - BTreeSet::from_sorted_iter(inputs.into_iter(), Global) + inputs.sort_by(|a, b| a.borrow().cmp(b.borrow())); + BTreeSet::from_sorted_iter(inputs.into_iter(), T::State::cmp_fn(), Global) } } -impl BTreeSet { - fn from_sorted_iter>(iter: I, alloc: A) -> BTreeSet { +impl BTreeSet +where + T: Sortable, + C: Comparator, +{ + fn from_sorted_iter>(iter: I, comparator: C, alloc: A) -> BTreeSet { let iter = iter.map(|k| (k, SetValZST::default())); - let map = BTreeMap::bulk_build_from_sorted_iter(iter, alloc); + let map = BTreeMap::bulk_build_from_sorted_iter(iter, comparator, alloc); BTreeSet { map } } } -#[stable(feature = "std_collections_from_array", since = "1.56.0")] -impl From<[T; N]> for BTreeSet { +// #[stable(feature = "std_collections_from_array", since = "1.56.0")] +impl From<[T; N]> for BTreeSet> +where + T: Sortable, + T::State: Ord, +{ /// Converts a `[T; N]` into a `BTreeSet`. /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set1 = BTreeSet::from([1, 2, 3, 4]); /// let set2: BTreeSet<_> = [1, 2, 3, 4].into(); @@ -1282,19 +1296,19 @@ impl From<[T; N]> for BTreeSet { /// ``` fn from(mut arr: [T; N]) -> Self { if N == 0 { - return BTreeSet::new(); + return BTreeSet::default(); } // use stable sort to preserve the insertion order. - arr.sort(); + arr.sort_by(|a, b| a.borrow().cmp(b.borrow())); let iter = IntoIterator::into_iter(arr).map(|k| (k, SetValZST::default())); - let map = BTreeMap::bulk_build_from_sorted_iter(iter, Global); + let map = BTreeMap::bulk_build_from_sorted_iter(iter, T::State::cmp_fn(), Global); BTreeSet { map } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl IntoIterator for BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl IntoIterator for BTreeSet { type Item = T; type IntoIter = IntoIter; @@ -1303,7 +1317,7 @@ impl IntoIterator for BTreeSet { /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let set = BTreeSet::from([1, 2, 3, 4]); /// @@ -1317,8 +1331,12 @@ impl IntoIterator for BTreeSet { } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, C, A: Allocator + Clone> IntoIterator for &'a BTreeSet +where + T: Sortable, + C: Comparator, +{ type Item = &'a T; type IntoIter = Iter<'a, T>; @@ -1328,12 +1346,13 @@ impl<'a, T, A: Allocator + Clone> IntoIterator for &'a BTreeSet { } /// An iterator produced by calling `drain_filter` on BTreeSet. -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] pub struct DrainFilter< 'a, T, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator + Clone = Global, + // #[unstable(feature = "allocator_api", issue = "32838")] + A: Allocator + Clone = Global, > where T: 'a, F: 'a + FnMut(&T) -> bool, @@ -1344,7 +1363,7 @@ pub struct DrainFilter< alloc: A, } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl Drop for DrainFilter<'_, T, F, A> where F: FnMut(&T) -> bool, @@ -1354,7 +1373,7 @@ where } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl fmt::Debug for DrainFilter<'_, T, F, A> where T: fmt::Debug, @@ -1367,7 +1386,7 @@ where } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl<'a, T, F, A: Allocator + Clone> Iterator for DrainFilter<'_, T, F, A> where F: 'a + FnMut(&T) -> bool, @@ -1387,14 +1406,18 @@ where } } -#[unstable(feature = "btree_drain_filter", issue = "70530")] +// #[unstable(feature = "btree_drain_filter", issue = "70530")] impl FusedIterator for DrainFilter<'_, T, F, A> where F: FnMut(&T) -> bool { } -#[stable(feature = "rust1", since = "1.0.0")] -impl Extend for BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Extend for BTreeSet +where + T: Sortable, + C: Comparator, +{ #[inline] fn extend>(&mut self, iter: Iter) { iter.into_iter().for_each(move |elem| { @@ -1403,41 +1426,55 @@ impl Extend for BTreeSet { } #[inline] + #[cfg(feature = "extend_one")] fn extend_one(&mut self, elem: T) { self.insert(elem); } } -#[stable(feature = "extend_ref", since = "1.2.0")] -impl<'a, T: 'a + Ord + Copy, A: Allocator + Clone> Extend<&'a T> for BTreeSet { +// #[stable(feature = "extend_ref", since = "1.2.0")] +impl<'a, T: 'a + Ord + Copy, C, A: Allocator + Clone> Extend<&'a T> for BTreeSet +where + T: Sortable, + C: Comparator, +{ fn extend>(&mut self, iter: I) { self.extend(iter.into_iter().cloned()); } #[inline] + #[cfg(feature = "extend_one")] fn extend_one(&mut self, &elem: &'a T) { self.insert(elem); } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Default for BTreeSet { - /// Creates an empty `BTreeSet`. - fn default() -> BTreeSet { - BTreeSet::new() +// #[stable(feature = "rust1", since = "1.0.0")] +impl Default for BTreeSet> +where + T: Sortable, + T::State: Ord, +{ + /// Creates an empty `BTreeSet` ordered by the `Ord` trait. + fn default() -> BTreeSet> { + BTreeSet::new(T::State::cmp_fn()) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Sub<&BTreeSet> for &BTreeSet { - type Output = BTreeSet; +// #[stable(feature = "rust1", since = "1.0.0")] +impl Sub<&BTreeSet> for &BTreeSet +where + T: Sortable, + C: Comparator, +{ + type Output = BTreeSet; /// Returns the difference of `self` and `rhs` as a new `BTreeSet`. /// /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let a = BTreeSet::from([1, 2, 3]); /// let b = BTreeSet::from([3, 4, 5]); @@ -1445,24 +1482,29 @@ impl Sub<&BTreeSet> for &BTreeSet) -> BTreeSet { + fn sub(self, rhs: &BTreeSet) -> BTreeSet { BTreeSet::from_sorted_iter( self.difference(rhs).cloned(), + self.map.comparator.clone(), ManuallyDrop::into_inner(self.map.alloc.clone()), ) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl BitXor<&BTreeSet> for &BTreeSet { - type Output = BTreeSet; +// #[stable(feature = "rust1", since = "1.0.0")] +impl BitXor<&BTreeSet> for &BTreeSet +where + T: Sortable, + C: Comparator, +{ + type Output = BTreeSet; /// Returns the symmetric difference of `self` and `rhs` as a new `BTreeSet`. /// /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let a = BTreeSet::from([1, 2, 3]); /// let b = BTreeSet::from([2, 3, 4]); @@ -1470,24 +1512,29 @@ impl BitXor<&BTreeSet> for &BTreeSet /// let result = &a ^ &b; /// assert_eq!(result, BTreeSet::from([1, 4])); /// ``` - fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { + fn bitxor(self, rhs: &BTreeSet) -> BTreeSet { BTreeSet::from_sorted_iter( self.symmetric_difference(rhs).cloned(), + self.map.comparator.clone(), ManuallyDrop::into_inner(self.map.alloc.clone()), ) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl BitAnd<&BTreeSet> for &BTreeSet { - type Output = BTreeSet; +// #[stable(feature = "rust1", since = "1.0.0")] +impl BitAnd<&BTreeSet> for &BTreeSet +where + T: Sortable, + C: Comparator, +{ + type Output = BTreeSet; /// Returns the intersection of `self` and `rhs` as a new `BTreeSet`. /// /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let a = BTreeSet::from([1, 2, 3]); /// let b = BTreeSet::from([2, 3, 4]); @@ -1495,24 +1542,29 @@ impl BitAnd<&BTreeSet> for &BTreeSet /// let result = &a & &b; /// assert_eq!(result, BTreeSet::from([2, 3])); /// ``` - fn bitand(self, rhs: &BTreeSet) -> BTreeSet { + fn bitand(self, rhs: &BTreeSet) -> BTreeSet { BTreeSet::from_sorted_iter( self.intersection(rhs).cloned(), + self.map.comparator.clone(), ManuallyDrop::into_inner(self.map.alloc.clone()), ) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl BitOr<&BTreeSet> for &BTreeSet { - type Output = BTreeSet; +// #[stable(feature = "rust1", since = "1.0.0")] +impl BitOr<&BTreeSet> for &BTreeSet +where + T: Sortable, + C: Comparator, +{ + type Output = BTreeSet; /// Returns the union of `self` and `rhs` as a new `BTreeSet`. /// /// # Examples /// /// ``` - /// use std::collections::BTreeSet; + /// use copse::BTreeSet; /// /// let a = BTreeSet::from([1, 2, 3]); /// let b = BTreeSet::from([3, 4, 5]); @@ -1520,22 +1572,23 @@ impl BitOr<&BTreeSet> for &BTreeSet< /// let result = &a | &b; /// assert_eq!(result, BTreeSet::from([1, 2, 3, 4, 5])); /// ``` - fn bitor(self, rhs: &BTreeSet) -> BTreeSet { + fn bitor(self, rhs: &BTreeSet) -> BTreeSet { BTreeSet::from_sorted_iter( self.union(rhs).cloned(), + self.map.comparator.clone(), ManuallyDrop::into_inner(self.map.alloc.clone()), ) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl Debug for BTreeSet { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Debug for BTreeSet { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_set().entries(self.iter()).finish() } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Clone for Iter<'_, T> { fn clone(&self) -> Self { Iter { @@ -1543,7 +1596,7 @@ impl Clone for Iter<'_, T> { } } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> Iterator for Iter<'a, T> { type Item = &'a T; @@ -1567,23 +1620,23 @@ impl<'a, T> Iterator for Iter<'a, T> { self.next_back() } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl<'a, T> DoubleEndedIterator for Iter<'a, T> { fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back() } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for Iter<'_, T> { fn len(&self) -> usize { self.iter.len() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Iter<'_, T> {} -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl Iterator for IntoIter { type Item = T; @@ -1595,32 +1648,32 @@ impl Iterator for IntoIter { self.iter.size_hint() } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl DoubleEndedIterator for IntoIter { fn next_back(&mut self) -> Option { self.iter.next_back().map(|(k, _)| k) } } -#[stable(feature = "rust1", since = "1.0.0")] +// #[stable(feature = "rust1", since = "1.0.0")] impl ExactSizeIterator for IntoIter { fn len(&self) -> usize { self.iter.len() } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for IntoIter {} -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl Clone for Range<'_, T> { fn clone(&self) -> Self { - Range { - iter: self.iter.clone(), - } + *self } } -#[stable(feature = "btree_range", since = "1.17.0")] +impl Copy for Range<'_, T> {} + +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, T> Iterator for Range<'a, T> { type Item = &'a T; @@ -1641,18 +1694,18 @@ impl<'a, T> Iterator for Range<'a, T> { } } -#[stable(feature = "btree_range", since = "1.17.0")] +// #[stable(feature = "btree_range", since = "1.17.0")] impl<'a, T> DoubleEndedIterator for Range<'a, T> { fn next_back(&mut self) -> Option<&'a T> { self.iter.next_back().map(|(k, _)| k) } } -#[stable(feature = "fused", since = "1.26.0")] +// #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Range<'_, T> {} -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Difference<'_, T, A> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Difference<'_, T, C, A> { fn clone(&self) -> Self { Difference { inner: match &self.inner { @@ -1672,11 +1725,16 @@ impl Clone for Difference<'_, T, A> { }, DifferenceInner::Iterate(iter) => DifferenceInner::Iterate(iter.clone()), }, + comparator: self.comparator, } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, C, A: Allocator + Clone> Iterator for Difference<'a, T, C, A> +where + T: Sortable, + C: Comparator, +{ type Item = &'a T; fn next(&mut self) -> Option<&'a T> { @@ -1687,10 +1745,9 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { } => { let mut self_next = self_iter.next()?; loop { - match other_iter - .peek() - .map_or(Less, |other_next| self_next.cmp(other_next)) - { + match other_iter.peek().map_or(Less, |&other_next| { + self.comparator.cmp(self_next.borrow(), other_next.borrow()) + }) { Less => return Some(self_next), Equal => { self_next = self_iter.next()?; @@ -1707,7 +1764,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { other_set, } => loop { let self_next = self_iter.next()?; - if !other_set.contains(&self_next) { + if !other_set.contains(self_next) { return Some(self_next); } }, @@ -1735,22 +1792,31 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Difference<'a, T, A> { } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Difference<'_, T, A> {} +// #[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Difference<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ +} -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for SymmetricDifference<'_, T> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for SymmetricDifference<'_, T, C> { fn clone(&self) -> Self { - SymmetricDifference(self.0.clone()) + SymmetricDifference(self.0.clone(), self.1) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, C> Iterator for SymmetricDifference<'a, T, C> +where + T: Sortable, + C: Comparator, +{ type Item = &'a T; fn next(&mut self) -> Option<&'a T> { loop { - let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + let (a_next, b_next) = self.0.nexts(&|a: &&T, b: &&T| self.1.cmp((*a).borrow(), (*b).borrow())); if a_next.and(b_next).is_none() { return a_next.or(b_next); } @@ -1770,11 +1836,16 @@ impl<'a, T: Ord> Iterator for SymmetricDifference<'a, T> { } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for SymmetricDifference<'_, T> {} +// #[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for SymmetricDifference<'_, T, C> +where + T: Sortable, + C: Comparator, +{ +} -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Intersection<'_, T, A> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Intersection<'_, T, C, A> { fn clone(&self) -> Self { Intersection { inner: match &self.inner { @@ -1791,11 +1862,16 @@ impl Clone for Intersection<'_, T, A> { }, IntersectionInner::Answer(answer) => IntersectionInner::Answer(*answer), }, + comparator: self.comparator, } } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, C, A: Allocator + Clone> Iterator for Intersection<'a, T, C, A> +where + T: Sortable, + C: Comparator, +{ type Item = &'a T; fn next(&mut self) -> Option<&'a T> { @@ -1804,7 +1880,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { let mut a_next = a.next()?; let mut b_next = b.next()?; loop { - match a_next.cmp(b_next) { + match self.comparator.cmp(a_next.borrow(), b_next.borrow()) { Less => a_next = a.next()?, Greater => b_next = b.next()?, Equal => return Some(a_next), @@ -1816,7 +1892,7 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { large_set, } => loop { let small_next = small_iter.next()?; - if large_set.contains(&small_next) { + if large_set.contains(small_next) { return Some(small_next); } }, @@ -1838,21 +1914,30 @@ impl<'a, T: Ord, A: Allocator + Clone> Iterator for Intersection<'a, T, A> { } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Intersection<'_, T, A> {} +// #[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Intersection<'_, T, C, A> +where + T: Sortable, + C: Comparator, +{ +} -#[stable(feature = "rust1", since = "1.0.0")] -impl Clone for Union<'_, T> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl Clone for Union<'_, T, &C> { fn clone(&self) -> Self { - Union(self.0.clone()) + Union(self.0.clone(), self.1) } } -#[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T: Ord> Iterator for Union<'a, T> { +// #[stable(feature = "rust1", since = "1.0.0")] +impl<'a, T, C> Iterator for Union<'a, T, C> +where + T: Sortable, + C: Comparator, +{ type Item = &'a T; fn next(&mut self) -> Option<&'a T> { - let (a_next, b_next) = self.0.nexts(Self::Item::cmp); + let (a_next, b_next) = self.0.nexts(&|a: &&T, b: &&T| self.1.cmp((*a).borrow(), (*b).borrow())); a_next.or(b_next) } @@ -1867,8 +1952,13 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { } } -#[stable(feature = "fused", since = "1.26.0")] -impl FusedIterator for Union<'_, T> {} +// #[stable(feature = "fused", since = "1.26.0")] +impl FusedIterator for Union<'_, T, C> +where + T: Sortable, + C: Comparator, +{ +} #[cfg(test)] mod tests; diff --git a/src/btree/set/tests.rs b/src/btree/set/tests.rs index d99c9cf..f9f8966 100644 --- a/src/btree/set/tests.rs +++ b/src/btree/set/tests.rs @@ -1,7 +1,7 @@ use super::super::testing::crash_test::{CrashTestDummy, Panic}; use super::super::testing::rng::DeterministicRng; use super::*; -use crate::vec::Vec; +use alloc::vec::Vec; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::iter::FromIterator; @@ -10,7 +10,7 @@ use std::panic::{catch_unwind, AssertUnwindSafe}; #[test] fn test_clone_eq() { - let mut m = BTreeSet::new(); + let mut m = BTreeSet::default(); m.insert(1); m.insert(2); @@ -20,41 +20,45 @@ fn test_clone_eq() { #[test] fn test_iter_min_max() { - let mut a = BTreeSet::new(); + let mut a = BTreeSet::default(); assert_eq!(a.iter().min(), None); assert_eq!(a.iter().max(), None); - assert_eq!(a.range(..).min(), None); - assert_eq!(a.range(..).max(), None); - assert_eq!(a.difference(&BTreeSet::new()).min(), None); - assert_eq!(a.difference(&BTreeSet::new()).max(), None); + assert_eq!(a.range::(..).min(), None); + assert_eq!(a.range::(..).max(), None); + assert_eq!(a.difference(&BTreeSet::default()).min(), None); + assert_eq!(a.difference(&BTreeSet::default()).max(), None); assert_eq!(a.intersection(&a).min(), None); assert_eq!(a.intersection(&a).max(), None); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), None); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::default()).min(), None); + assert_eq!(a.symmetric_difference(&BTreeSet::default()).max(), None); assert_eq!(a.union(&a).min(), None); assert_eq!(a.union(&a).max(), None); a.insert(1); a.insert(2); assert_eq!(a.iter().min(), Some(&1)); assert_eq!(a.iter().max(), Some(&2)); - assert_eq!(a.range(..).min(), Some(&1)); - assert_eq!(a.range(..).max(), Some(&2)); - assert_eq!(a.difference(&BTreeSet::new()).min(), Some(&1)); - assert_eq!(a.difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.range::(..).min(), Some(&1)); + assert_eq!(a.range::(..).max(), Some(&2)); + assert_eq!(a.difference(&BTreeSet::default()).min(), Some(&1)); + assert_eq!(a.difference(&BTreeSet::default()).max(), Some(&2)); assert_eq!(a.intersection(&a).min(), Some(&1)); assert_eq!(a.intersection(&a).max(), Some(&2)); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).min(), Some(&1)); - assert_eq!(a.symmetric_difference(&BTreeSet::new()).max(), Some(&2)); + assert_eq!(a.symmetric_difference(&BTreeSet::default()).min(), Some(&1)); + assert_eq!(a.symmetric_difference(&BTreeSet::default()).max(), Some(&2)); assert_eq!(a.union(&a).min(), Some(&1)); assert_eq!(a.union(&a).max(), Some(&2)); } fn check(a: &[i32], b: &[i32], expected: &[i32], f: F) where - F: FnOnce(&BTreeSet, &BTreeSet, &mut dyn FnMut(&i32) -> bool) -> bool, + F: FnOnce( + &BTreeSet>, + &BTreeSet>, + &mut dyn FnMut(&i32) -> bool, + ) -> bool, { - let mut set_a = BTreeSet::new(); - let mut set_b = BTreeSet::new(); + let mut set_a = BTreeSet::default(); + let mut set_b = BTreeSet::default(); for x in a { assert!(set_a.insert(*x)) @@ -299,29 +303,23 @@ fn test_is_subset() { set_a.is_subset(&set_b) } - assert_eq!(is_subset(&[], &[]), true); - assert_eq!(is_subset(&[], &[1, 2]), true); - assert_eq!(is_subset(&[0], &[1, 2]), false); - assert_eq!(is_subset(&[1], &[1, 2]), true); - assert_eq!(is_subset(&[2], &[1, 2]), true); - assert_eq!(is_subset(&[3], &[1, 2]), false); - assert_eq!(is_subset(&[1, 2], &[1]), false); - assert_eq!(is_subset(&[1, 2], &[1, 2]), true); - assert_eq!(is_subset(&[1, 2], &[2, 3]), false); - assert_eq!( - is_subset( - &[-5, 11, 22, 33, 40, 42], - &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42] - ), - true - ); - assert_eq!( - is_subset( - &[-5, 11, 22, 33, 40, 42], - &[-12, -5, 11, 14, 22, 23, 34, 38] - ), - false - ); + assert!(is_subset(&[], &[])); + assert!(is_subset(&[], &[1, 2])); + assert!(!is_subset(&[0], &[1, 2])); + assert!(is_subset(&[1], &[1, 2])); + assert!(is_subset(&[2], &[1, 2])); + assert!(!is_subset(&[3], &[1, 2])); + assert!(!is_subset(&[1, 2], &[1])); + assert!(is_subset(&[1, 2], &[1, 2])); + assert!(!is_subset(&[1, 2], &[2, 3])); + assert!(is_subset( + &[-5, 11, 22, 33, 40, 42], + &[-12, -5, 11, 14, 22, 23, 33, 34, 38, 39, 40, 42] + )); + assert!(!is_subset( + &[-5, 11, 22, 33, 40, 42], + &[-12, -5, 11, 14, 22, 23, 34, 38] + )); if cfg!(miri) { // Miri is too slow @@ -329,12 +327,12 @@ fn test_is_subset() { } let large = Vec::from_iter(0..100); - assert_eq!(is_subset(&[], &large), true); - assert_eq!(is_subset(&large, &[]), false); - assert_eq!(is_subset(&[-1], &large), false); - assert_eq!(is_subset(&[0], &large), true); - assert_eq!(is_subset(&[1, 2], &large), true); - assert_eq!(is_subset(&[99, 100], &large), false); + assert!(is_subset(&[], &large)); + assert!(!is_subset(&large, &[])); + assert!(!is_subset(&[-1], &large)); + assert!(is_subset(&[0], &large)); + assert!(is_subset(&[1, 2], &large)); + assert!(!is_subset(&[99, 100], &large)); } #[test] @@ -345,16 +343,16 @@ fn test_is_superset() { set_a.is_superset(&set_b) } - assert_eq!(is_superset(&[], &[]), true); - assert_eq!(is_superset(&[], &[1, 2]), false); - assert_eq!(is_superset(&[0], &[1, 2]), false); - assert_eq!(is_superset(&[1], &[1, 2]), false); - assert_eq!(is_superset(&[4], &[1, 2]), false); - assert_eq!(is_superset(&[1, 4], &[1, 2]), false); - assert_eq!(is_superset(&[1, 2], &[1, 2]), true); - assert_eq!(is_superset(&[1, 2, 3], &[1, 3]), true); - assert_eq!(is_superset(&[1, 2, 3], &[]), true); - assert_eq!(is_superset(&[-1, 1, 2, 3], &[-1, 3]), true); + assert!(is_superset(&[], &[])); + assert!(!is_superset(&[], &[1, 2])); + assert!(!is_superset(&[0], &[1, 2])); + assert!(!is_superset(&[1], &[1, 2])); + assert!(!is_superset(&[4], &[1, 2])); + assert!(!is_superset(&[1, 4], &[1, 2])); + assert!(is_superset(&[1, 2], &[1, 2])); + assert!(is_superset(&[1, 2, 3], &[1, 3])); + assert!(is_superset(&[1, 2, 3], &[])); + assert!(is_superset(&[-1, 1, 2, 3], &[-1, 3])); if cfg!(miri) { // Miri is too slow @@ -362,15 +360,15 @@ fn test_is_superset() { } let large = Vec::from_iter(0..100); - assert_eq!(is_superset(&[], &large), false); - assert_eq!(is_superset(&large, &[]), true); - assert_eq!(is_superset(&large, &[1]), true); - assert_eq!(is_superset(&large, &[50, 99]), true); - assert_eq!(is_superset(&large, &[100]), false); - assert_eq!(is_superset(&large, &[0, 99]), true); - assert_eq!(is_superset(&[-1], &large), false); - assert_eq!(is_superset(&[0], &large), false); - assert_eq!(is_superset(&[99, 100], &large), false); + assert!(!is_superset(&[], &large)); + assert!(is_superset(&large, &[])); + assert!(is_superset(&large, &[1])); + assert!(is_superset(&large, &[50, 99])); + assert!(!is_superset(&large, &[100])); + assert!(is_superset(&large, &[0, 99])); + assert!(!is_superset(&[-1], &large)); + assert!(!is_superset(&[0], &large)); + assert!(!is_superset(&[99, 100], &large)); } #[test] @@ -399,7 +397,7 @@ fn test_drain_filter_drop_panic_leak() { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut set = BTreeSet::new(); + let mut set = BTreeSet::default(); set.insert(a.spawn(Panic::Never)); set.insert(b.spawn(Panic::InDrop)); set.insert(c.spawn(Panic::Never)); @@ -419,7 +417,7 @@ fn test_drain_filter_pred_panic_leak() { let a = CrashTestDummy::new(0); let b = CrashTestDummy::new(1); let c = CrashTestDummy::new(2); - let mut set = BTreeSet::new(); + let mut set = BTreeSet::default(); set.insert(a.spawn(Panic::Never)); set.insert(b.spawn(Panic::InQuery)); set.insert(c.spawn(Panic::InQuery)); @@ -442,7 +440,7 @@ fn test_drain_filter_pred_panic_leak() { #[test] fn test_clear() { - let mut x = BTreeSet::new(); + let mut x = BTreeSet::default(); x.insert(1); x.clear(); @@ -450,7 +448,7 @@ fn test_clear() { } #[test] fn test_remove() { - let mut x = BTreeSet::new(); + let mut x = BTreeSet::default(); assert!(x.is_empty()); x.insert(1); @@ -458,25 +456,25 @@ fn test_remove() { x.insert(3); x.insert(4); - assert_eq!(x.remove(&2), true); - assert_eq!(x.remove(&0), false); - assert_eq!(x.remove(&5), false); - assert_eq!(x.remove(&1), true); - assert_eq!(x.remove(&2), false); - assert_eq!(x.remove(&3), true); - assert_eq!(x.remove(&4), true); - assert_eq!(x.remove(&4), false); + assert!(x.remove(&2)); + assert!(!x.remove(&0)); + assert!(!x.remove(&5)); + assert!(x.remove(&1)); + assert!(!x.remove(&2)); + assert!(x.remove(&3)); + assert!(x.remove(&4)); + assert!(!x.remove(&4)); assert!(x.is_empty()); } #[test] fn test_zip() { - let mut x = BTreeSet::new(); + let mut x = BTreeSet::default(); x.insert(5); x.insert(12); x.insert(11); - let mut y = BTreeSet::new(); + let mut y = BTreeSet::default(); y.insert("foo"); y.insert("bar"); @@ -502,8 +500,8 @@ fn test_from_iter() { #[test] fn test_show() { - let mut set = BTreeSet::new(); - let empty = BTreeSet::::new(); + let mut set = BTreeSet::default(); + let empty = BTreeSet::::default(); set.insert(1); set.insert(2); @@ -516,7 +514,7 @@ fn test_show() { #[test] fn test_extend_ref() { - let mut a = BTreeSet::new(); + let mut a = BTreeSet::default(); a.insert(1); a.extend(&[2, 3, 4]); @@ -527,7 +525,7 @@ fn test_extend_ref() { assert!(a.contains(&3)); assert!(a.contains(&4)); - let mut b = BTreeSet::new(); + let mut b = BTreeSet::default(); b.insert(5); b.insert(6); @@ -547,6 +545,10 @@ fn test_recovery() { #[derive(Debug)] struct Foo(&'static str, i32); + impl Sortable for Foo { + type State = Self; + } + impl PartialEq for Foo { fn eq(&self, other: &Self) -> bool { self.0 == other.0 @@ -557,17 +559,17 @@ fn test_recovery() { impl PartialOrd for Foo { fn partial_cmp(&self, other: &Self) -> Option { - self.0.partial_cmp(&other.0) + self.0.partial_cmp(other.0) } } impl Ord for Foo { fn cmp(&self, other: &Self) -> Ordering { - self.0.cmp(&other.0) + self.0.cmp(other.0) } } - let mut s = BTreeSet::new(); + let mut s = BTreeSet::default(); assert_eq!(s.replace(Foo("a", 1)), None); assert_eq!(s.len(), 1); assert_eq!(s.replace(Foo("a", 2)), Some(Foo("a", 1))); @@ -608,79 +610,133 @@ fn assert_covariance() { #[allow(dead_code)] fn assert_sync() { - fn set(v: &BTreeSet) -> impl Sync + '_ { + fn set(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { v } - fn iter(v: &BTreeSet) -> impl Sync + '_ { + fn iter(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { v.iter() } - fn into_iter(v: BTreeSet) -> impl Sync { + fn into_iter(v: BTreeSet) -> impl Sync + where + T::State: Ord, + { v.into_iter() } - fn range(v: &BTreeSet) -> impl Sync + '_ { - v.range(..) + fn range(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { + v.range::(..) } - fn drain_filter(v: &mut BTreeSet) -> impl Sync + '_ { + fn drain_filter(v: &mut BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { v.drain_filter(|_| false) } - fn difference(v: &BTreeSet) -> impl Sync + '_ { - v.difference(&v) + fn difference(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { + v.difference(v) } - fn intersection(v: &BTreeSet) -> impl Sync + '_ { - v.intersection(&v) + fn intersection(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { + v.intersection(v) } - fn symmetric_difference(v: &BTreeSet) -> impl Sync + '_ { - v.symmetric_difference(&v) + fn symmetric_difference(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { + v.symmetric_difference(v) } - fn union(v: &BTreeSet) -> impl Sync + '_ { - v.union(&v) + fn union(v: &BTreeSet) -> impl Sync + '_ + where + T::State: Ord, + { + v.union(v) } } #[allow(dead_code)] fn assert_send() { - fn set(v: BTreeSet) -> impl Send { + fn set(v: BTreeSet) -> impl Send + where + T::State: Ord, + { v } - fn iter(v: &BTreeSet) -> impl Send + '_ { + fn iter(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { v.iter() } - fn into_iter(v: BTreeSet) -> impl Send { + fn into_iter(v: BTreeSet) -> impl Send + where + T::State: Ord, + { v.into_iter() } - fn range(v: &BTreeSet) -> impl Send + '_ { - v.range(..) + fn range(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { + v.range::(..) } - fn drain_filter(v: &mut BTreeSet) -> impl Send + '_ { + fn drain_filter(v: &mut BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { v.drain_filter(|_| false) } - fn difference(v: &BTreeSet) -> impl Send + '_ { - v.difference(&v) + fn difference(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { + v.difference(v) } - fn intersection(v: &BTreeSet) -> impl Send + '_ { - v.intersection(&v) + fn intersection(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { + v.intersection(v) } - fn symmetric_difference(v: &BTreeSet) -> impl Send + '_ { - v.symmetric_difference(&v) + fn symmetric_difference(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { + v.symmetric_difference(v) } - fn union(v: &BTreeSet) -> impl Send + '_ { - v.union(&v) + fn union(v: &BTreeSet) -> impl Send + '_ + where + T::State: Ord, + { + v.union(v) } } @@ -688,36 +744,60 @@ fn assert_send() { // Check that the member-like functions conditionally provided by #[derive()] // are not overridden by genuine member functions with a different signature. fn assert_derives() { - fn hash(v: BTreeSet, state: &mut H) { + fn hash(v: BTreeSet, state: &mut H) + where + T::State: Ord, + { v.hash(state); // Tested much more thoroughly outside the crate in btree_set_hash.rs } - fn eq(v: BTreeSet) { + fn eq(v: BTreeSet) + where + T::State: Ord, + { let _ = v.eq(&v); } - fn ne(v: BTreeSet) { + fn ne(v: BTreeSet) + where + T::State: Ord, + { let _ = v.ne(&v); } - fn cmp(v: BTreeSet) { + fn cmp(v: BTreeSet) + where + T::State: Ord, + { let _ = v.cmp(&v); } - fn min(v: BTreeSet, w: BTreeSet) { + fn min(v: BTreeSet, w: BTreeSet) + where + T::State: Ord, + { let _ = v.min(w); } - fn max(v: BTreeSet, w: BTreeSet) { + fn max(v: BTreeSet, w: BTreeSet) + where + T::State: Ord, + { let _ = v.max(w); } - fn clamp(v: BTreeSet, w: BTreeSet, x: BTreeSet) { + fn clamp(v: BTreeSet, w: BTreeSet, x: BTreeSet) + where + T::State: Ord, + { let _ = v.clamp(w, x); } - fn partial_cmp(v: &BTreeSet) { - let _ = v.partial_cmp(&v); + fn partial_cmp(v: &BTreeSet) + where + T::State: Ord, + { + let _ = v.partial_cmp(v); } } #[test] fn test_ord_absence() { - fn set(mut set: BTreeSet) { + fn set(mut set: BTreeSet) { let _ = set.is_empty(); let _ = set.len(); set.clear(); @@ -725,31 +805,31 @@ fn test_ord_absence() { let _ = set.into_iter(); } - fn set_debug(set: BTreeSet) { + fn set_debug(set: BTreeSet) { format!("{set:?}"); format!("{:?}", set.iter()); format!("{:?}", set.into_iter()); } - fn set_clone(mut set: BTreeSet) { + fn set_clone(mut set: BTreeSet) { set.clone_from(&set.clone()); } #[derive(Debug, Clone)] struct NonOrd; - set(BTreeSet::::new()); - set_debug(BTreeSet::::new()); - set_clone(BTreeSet::::default()); + set(BTreeSet::::new(())); + set_debug(BTreeSet::::new(())); + set_clone(BTreeSet::::new(())); } #[test] fn test_append() { - let mut a = BTreeSet::new(); + let mut a = BTreeSet::default(); a.insert(1); a.insert(2); a.insert(3); - let mut b = BTreeSet::new(); + let mut b = BTreeSet::default(); b.insert(3); b.insert(4); b.insert(5); @@ -759,16 +839,16 @@ fn test_append() { assert_eq!(a.len(), 5); assert_eq!(b.len(), 0); - assert_eq!(a.contains(&1), true); - assert_eq!(a.contains(&2), true); - assert_eq!(a.contains(&3), true); - assert_eq!(a.contains(&4), true); - assert_eq!(a.contains(&5), true); + assert!(a.contains(&1)); + assert!(a.contains(&2)); + assert!(a.contains(&3)); + assert!(a.contains(&4)); + assert!(a.contains(&5)); } #[test] fn test_first_last() { - let mut a = BTreeSet::new(); + let mut a = BTreeSet::default(); assert_eq!(a.first(), None); assert_eq!(a.last(), None); a.insert(1); @@ -859,24 +939,38 @@ fn from_array() { assert_eq!(set, unordered_duplicates); } -#[should_panic(expected = "range start is greater than range end in BTreeSet")] +#[cfg_attr( + feature = "specialization", + should_panic(expected = "range start is greater than range end in BTreeSet") +)] +#[cfg_attr( + not(feature = "specialization"), + should_panic(expected = "range start is greater than range end") +)] #[test] fn test_range_panic_1() { - let mut set = BTreeSet::new(); + let mut set = BTreeSet::default(); set.insert(3); set.insert(5); set.insert(8); - let _invalid_range = set.range((Included(&8), Included(&3))); + let _invalid_range = set.range::((Included(&8), Included(&3))); } -#[should_panic(expected = "range start and end are equal and excluded in BTreeSet")] +#[cfg_attr( + feature = "specialization", + should_panic(expected = "range start and end are equal and excluded in BTreeSet") +)] +#[cfg_attr( + not(feature = "specialization"), + should_panic(expected = "range start and end are equal and excluded") +)] #[test] fn test_range_panic_2() { - let mut set = BTreeSet::new(); + let mut set = BTreeSet::default(); set.insert(3); set.insert(5); set.insert(8); - let _invalid_range = set.range((Excluded(&5), Excluded(&5))); + let _invalid_range = set.range::((Excluded(&5), Excluded(&5))); } diff --git a/src/btree/set_val.rs b/src/btree/set_val.rs index 80c459b..4002e53 100644 --- a/src/btree/set_val.rs +++ b/src/btree/set_val.rs @@ -15,6 +15,7 @@ pub trait IsSetVal { } // Blanket implementation +#[cfg(feature = "specialization")] impl IsSetVal for V { default fn is_set_val() -> bool { false diff --git a/src/btree/split.rs b/src/btree/split.rs index 638dc98..de227c6 100644 --- a/src/btree/split.rs +++ b/src/btree/split.rs @@ -1,6 +1,8 @@ +use crate::{Sortable, Comparator}; + use super::node::{ForceResult::*, Root}; use super::search::SearchResult::*; -use core::alloc::Allocator; +use crate::Allocator; use core::borrow::Borrow; impl Root { @@ -29,9 +31,15 @@ impl Root { /// and if the ordering of `Q` corresponds to that of `K`. /// If `self` respects all `BTreeMap` tree invariants, then both /// `self` and the returned tree will respect those invariants. - pub fn split_off(&mut self, key: &Q, alloc: A) -> Self + pub fn split_off( + &mut self, + key: &Q, + comparator: &impl Comparator, + alloc: A, + ) -> Self where - K: Borrow, + K: Sortable, + Q: Borrow, { let left_root = self; let mut right_root = Root::new_pillar(left_root.height(), alloc.clone()); @@ -39,7 +47,7 @@ impl Root { let mut right_node = right_root.borrow_mut(); loop { - let mut split_edge = match left_node.search_node(key) { + let mut split_edge = match left_node.search_node(key.borrow(), comparator) { // key is going to the right tree Found(kv) => kv.left_edge(), GoDown(edge) => edge, diff --git a/src/btree/testing/crash_test.rs b/src/btree/testing/crash_test.rs index 6971471..9915086 100644 --- a/src/btree/testing/crash_test.rs +++ b/src/btree/testing/crash_test.rs @@ -1,8 +1,10 @@ // We avoid relying on anything else in the crate, apart from the `Debug` trait. -use crate::fmt::Debug; +use alloc::fmt::Debug; use std::cmp::Ordering; use std::sync::atomic::{AtomicUsize, Ordering::SeqCst}; +use crate::Sortable; + /// A blueprint for crash test dummy instances that monitor particular events. /// Some instances may be configured to panic at some point. /// Events are `clone`, `drop` or some anonymous `query`. @@ -59,6 +61,10 @@ pub struct Instance<'a> { panic: Panic, } +impl Sortable for Instance<'_> { + type State = Self; +} + #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Panic { Never, diff --git a/src/btree/testing/ord_chaos.rs b/src/btree/testing/ord_chaos.rs index a67b1ca..4d2ca18 100644 --- a/src/btree/testing/ord_chaos.rs +++ b/src/btree/testing/ord_chaos.rs @@ -11,6 +11,12 @@ pub enum Cyclic3 { } use Cyclic3::*; +use crate::Sortable; + +impl Sortable for Cyclic3 { + type State = Self; +} + impl PartialOrd for Cyclic3 { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) @@ -29,7 +35,7 @@ impl Ord for Cyclic3 { impl PartialEq for Cyclic3 { fn eq(&self, other: &Self) -> bool { - self.cmp(&other) == Equal + self.cmp(other) == Equal } } @@ -59,6 +65,10 @@ impl Governor { #[derive(Debug)] pub struct Governed<'a, T>(pub T, pub &'a Governor); +impl Sortable for Governed<'_, T> { + type State = Self; +} + impl PartialOrd for Governed<'_, T> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) diff --git a/src/lib.rs b/src/lib.rs index c9ca01e..e59ef6f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1 +1,307 @@ +//! Direct ports of the standard library's [`BTreeMap`][std::collections::BTreeMap] and +//! [`BTreeSet`][std::collections::BTreeSet] collections, but which sort according to a specified +//! [`Comparator`] rather than relying upon the [`Ord`] trait. +//! +//! This is primarily useful when the [`Comparator`] is not defined until runtime, and therefore +//! cannot be provided as an [`Ord`] implementation for any type. +//! +//! # Lookup keys +//! In the standard library's collections, certain lookups can be performed using a key of type +//! `&Q` where the collection's storage key type `K` implements [`Borrow`]; for example, one +//! can use `&str` keys to perform lookups into collections that store `String` keys. This is +//! possible because the [`Borrow`] trait stipulates that borrowed values must preserve [`Ord`] +//! order. +//! +//! However, copse's collections do not use the [`Ord`] trait; instead, lookups can only ever +//! be performed using the [`Comparator`] supplied upon collection creation. This comparator +//! can only compare values of type `&T` for which it was defined, and hence such type must be +//! reachable from any key type `&Q` used to perform lookups in the collection. copse ensures +//! this via its [`Sortable`] trait, which will typically be implemented by the stored key type +//! `K`; its [`State`][Sortable::State] associated type then specifies the `T` in which +//! comparisons will be performed, and values of type `&Q` can be used as lookup keys provided +//! that `Q: Borrow`. +//! +//! For example, a collection using a `Comparator` comparator can store keys of type +//! `String` because `String` implements `Sortable`; moreover, lookups can be +//! performed using keys of type `&str` because `str` implements `Borrow` (due to the +//! reflexive blanket implementation). +//! +//! Implementations of [`Sortable`] are provided for primitive and some common standard library +//! types, but storing keys of other foreign types may require newtyping. +//! +//! # Function item types +//! In addition to the type parameters familiar from the standard library collections, copse's +//! collections are additionally parameterised by the type of the [`Comparator`]. If the +//! comparator type is not explicitly named, it defaults to the type of the [`Ord::cmp`] +//! function for `K::State`. As noted in the documentation of the [`CmpFn`] type alias, this +//! is only a zero-sized function item type if the unstable `type_alias_impl_trait` feature is +//! enabled; otherwise it is a function pointer type, with ensuing size and indirect call +//! implications. Collections built using the zero-sized function item type can still be +//! used in stable code, however; just not using the default type parameter. For example: +//! +//! ```rust +//! # use std::cmp::Ord; +//! # use copse::BTreeMap; +//! let mut ord_map = BTreeMap::new(Ord::cmp); +//! # ord_map.insert(123, "hello"); +//! ``` +//! +//! However, naming this type carries the usual problems associated with anonymous types like +//! closures; in certain situations you may be able to use `impl Comparator` for the type +//! parameter, but in other situations (in stable code) the function pointer may be +//! unavoidable. +//! +//! # Crate feature flags +//! This crate defines a number of feature flags, none of which are enabled by default: +//! +//! * the `std` feature provides [`Sortable`] implementations for some libstd types +//! that are not available in libcore + liballoc, namely [`OsString`] and [`PathBuf`]; +//! +//! * the `unstable` feature enables all other crate features, each of which enables the +//! like-named unstable compiler feature that is used by the standard library's collection +//! implementations (and which therefore require a nightly compiler)—most such behaviour +//! is polyfilled when the features are disabled, so they should rarely be required, but +//! they are nevertheless included to ease tracking of the stdlib implementations. +//! +//! The most visible differences to library users will be: +//! * `allocator_api` enables the `new_in` methods for use of custom allocators; +//! * `specialization` adds the collection type name to some panic messages; +//! * `type_alias_impl_trait`, as mentioned above, ensures that the *default* +//! [`Comparator`] type parameter for the collections is the zero-sized function +//! item type of the `K::State::cmp` function. +//! +//! [`Ord`]: std::cmp::Ord +//! [`Ord::cmp`]: std::cmp::Ord::cmp +//! [`OsString`]: std::ffi::OsString +//! [`PathBuf`]: std::path::PathBuf + + +#![allow(clippy::type_complexity)] +#![cfg_attr(docsrs, feature(doc_auto_cfg, doc_cfg))] +#![cfg_attr(not(any(feature = "std", test)), no_std)] +#![cfg_attr(feature = "specialization", allow(incomplete_features))] +#![cfg_attr(feature = "allocator_api", feature(allocator_api))] +#![cfg_attr(feature = "bound_map", feature(bound_map))] +#![cfg_attr(feature = "core_intrinsics", feature(core_intrinsics))] +#![cfg_attr(feature = "dropck_eyepatch", feature(dropck_eyepatch))] +#![cfg_attr(feature = "error_in_core", feature(error_in_core))] +#![cfg_attr(feature = "exact_size_is_empty", feature(exact_size_is_empty))] +#![cfg_attr(feature = "exclusive_range_pattern", feature(exclusive_range_pattern))] +#![cfg_attr(feature = "extend_one", feature(extend_one))] +#![cfg_attr( + feature = "hasher_prefixfree_extras", + feature(hasher_prefixfree_extras) +)] +#![cfg_attr(feature = "map_try_insert", feature(map_try_insert))] +#![cfg_attr(feature = "maybe_uninit_slice", feature(maybe_uninit_slice))] +#![cfg_attr(feature = "new_uninit", feature(new_uninit))] +#![cfg_attr(feature = "rustc_attrs", feature(rustc_attrs))] +#![cfg_attr(feature = "slice_ptr_get", feature(slice_ptr_get))] +#![cfg_attr(feature = "specialization", feature(specialization))] +#![cfg_attr(feature = "type_alias_impl_trait", feature(type_alias_impl_trait))] + +extern crate alloc; + +use alloc::{borrow::Cow, boxed::Box, ffi::CString, rc::Rc, string::String, sync::Arc, vec::Vec}; +use cfg_if::cfg_if; +use core::{borrow::Borrow, ffi::CStr, cmp::Ordering}; + mod btree; +pub use btree::{*, map::BTreeMap, set::BTreeSet}; + +cfg_if! { + if #[cfg(feature = "allocator_api")] { + use alloc::alloc::{Allocator, Global}; + } else { + mod mock_alloc { + use alloc::alloc::Layout; + use core::ptr::NonNull; + + pub trait Allocator { + #[inline] + fn allocate(&self, layout: Layout) -> Result, ()> { + unsafe { + let len = layout.size(); + let data = if len == 0 { + // SAFETY: align is guaranteed to be non-zero + layout.align() as _ + } else { + // SAFETY: `layout` is non-zero in size, + NonNull::new(alloc::alloc::alloc(layout)).ok_or(())?.as_ptr() + }; + Ok(NonNull::new_unchecked(core::ptr::slice_from_raw_parts_mut( + data, len, + ))) + } + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + if layout.size() != 0 { + // SAFETY: `layout` is non-zero in size, + // other conditions must be upheld by the caller + unsafe { alloc::alloc::dealloc(ptr.as_ptr(), layout) } + } + } + } + + #[derive(Copy, Clone, Debug)] + pub struct Global; + + impl Allocator for Global {} + } + + use mock_alloc::{Allocator, Global}; + } +} + +/// A sortable type. See the [crate's documentation][crate] for details. +pub trait Sortable: Borrow { + /// A type that can be borrowed from `Self` and which contains all state necessary + /// for sorting. + type State: ?Sized; +} + +mod std_ord { + use cfg_if::cfg_if; + use core::cmp::Ordering; + + pub trait StdOrd: Ord { + #[allow(non_camel_case_types)] + type cmp: Copy + Fn(&Self, &Self) -> Ordering; + fn cmp_fn() -> Self::cmp; + } + + impl StdOrd for O { + cfg_if! { + if #[cfg(feature = "type_alias_impl_trait")] { + type cmp = impl Copy + Fn(&Self, &Self) -> Ordering; + } else { + type cmp = fn(&Self, &Self) -> Ordering; + } + } + + fn cmp_fn() -> Self::cmp { + Self::cmp + } + } +} + +use std_ord::StdOrd; +use StdOrd as Ord; + +/// Alias for the type of the `::cmp` function. +/// +/// Note that, unless the `type_alias_impl_trait` feature is enabled, this is +/// just the relevant function pointer type (and therefore is not zero-sized). +/// However, with that (unstable) feature enabled, this is an alias for the +/// actual zero-sized function item type. +pub type CmpFn = ::cmp; + +/// Alias for the `Ord::cmp` function of `K::State`. +pub type MinCmpFn = CmpFn<::State>; + +macro_rules! minimals { + () => {}; + + ($t:ty => $m:ty $(, $($rest:tt)*)?) => { + impl Sortable for $t { + type State = $m; + } + + $(minimals!($($rest)*);)? + }; + + ($t:ty $(, $($rest:tt)*)?) => { + minimals!($t => Self $(, $($rest)*)?); + }; +} + +minimals! { + (), + bool, char, + f32, f64, + i8, u8, + i16, u16, + i32, u32, + i64, u64, + i128, u128, + isize, usize, + String => str, + CString => CStr, +} + +cfg_if! { + if #[cfg(any(feature = "std"))] { + use std::{ + ffi::{OsString, OsStr}, + path::{PathBuf, Path}, + }; + + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + impl Sortable for OsString { + type State = OsStr; + } + + #[cfg_attr(docsrs, doc(cfg(feature = "std")))] + impl Sortable for PathBuf { + type State = Path; + } + } +} + +impl Sortable for Cow<'_, B> { + type State = B; +} + +impl Sortable for &T { + type State = T; +} + +impl Sortable for &mut T { + type State = T; +} + +impl Sortable for Rc { + type State = T; +} + +impl Sortable for Arc { + type State = T; +} + +cfg_if! { + if #[cfg(feature = "allocator_api")] { + impl Sortable for Vec { + type State = [T]; + } + + impl Sortable for Box { + type State = T; + } + } else { + impl Sortable for Vec { + type State = [T]; + } + + impl Sortable for Box { + type State = T; + } + } +} + +impl Sortable for [T; N] { + type State = [T]; +} + +/// A comparator compares two values to determine their relative positions +/// according to the total order that it defines over their type `T`. +pub trait Comparator { + fn cmp(&self, this: &T, that: &T) -> Ordering; +} + +impl Ordering> Comparator for F { + fn cmp(&self, this: &T, that: &T) -> Ordering { + self(this, that) + } +}