From acd029484577c064949d537894d9b2265a28cba0 Mon Sep 17 00:00:00 2001 From: Marijn Schouten Date: Fri, 17 Oct 2025 12:10:51 +0000 Subject: [PATCH] btree: cleanup difference, intersection, is_subset --- library/alloc/src/collections/btree/set.rs | 179 +++++++++--------- library/alloctests/Cargo.toml | 2 +- tests/run-make/alloc-no-oom-handling/rmake.rs | 2 +- tests/run-make/alloc-no-rc/rmake.rs | 2 +- tests/run-make/alloc-no-sync/rmake.rs | 2 +- 5 files changed, 90 insertions(+), 97 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 6e6996bcbd69b..cb3e14252f8a3 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -427,39 +427,35 @@ impl BTreeSet { where T: Ord, { - 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()) }; - }; - let (other_min, other_max) = - if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { - (other_min, other_max) - } else { - return Difference { inner: DifferenceInner::Iterate(self.iter()) }; - }; - Difference { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { - (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), - (Equal, _) => { - let mut self_iter = self.iter(); - self_iter.next(); - DifferenceInner::Iterate(self_iter) - } - (_, Equal) => { - let mut self_iter = self.iter(); - self_iter.next_back(); - DifferenceInner::Iterate(self_iter) - } - _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - DifferenceInner::Search { self_iter: self.iter(), other_set: other } - } - _ => DifferenceInner::Stitch { - self_iter: self.iter(), - other_iter: other.iter().peekable(), + if let Some(self_min) = self.first() + && let Some(self_max) = self.last() + && let Some(other_min) = other.first() + && let Some(other_max) = other.last() + { + Difference { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => DifferenceInner::Iterate(self.iter()), + (Equal, _) => { + let mut self_iter = self.iter(); + self_iter.next(); + DifferenceInner::Iterate(self_iter) + } + (_, Equal) => { + let mut self_iter = self.iter(); + self_iter.next_back(); + DifferenceInner::Iterate(self_iter) + } + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + DifferenceInner::Search { self_iter: self.iter(), other_set: other } + } + _ => DifferenceInner::Stitch { + self_iter: self.iter(), + other_iter: other.iter().peekable(), + }, }, - }, + } + } else { + Difference { inner: DifferenceInner::Iterate(self.iter()) } } } @@ -519,31 +515,27 @@ impl BTreeSet { where T: Ord, { - 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) }; - }; - let (other_min, other_max) = - if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { - (other_min, other_max) - } else { - return Intersection { inner: IntersectionInner::Answer(None) }; - }; - Intersection { - inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { - (Greater, _) | (_, Less) => IntersectionInner::Answer(None), - (Equal, _) => IntersectionInner::Answer(Some(self_min)), - (_, Equal) => IntersectionInner::Answer(Some(self_max)), - _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - IntersectionInner::Search { small_iter: self.iter(), large_set: other } - } - _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { - IntersectionInner::Search { small_iter: other.iter(), large_set: self } - } - _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() }, - }, + if let Some(self_min) = self.first() + && let Some(self_max) = self.last() + && let Some(other_min) = other.first() + && let Some(other_max) = other.last() + { + Intersection { + inner: match (self_min.cmp(other_max), self_max.cmp(other_min)) { + (Greater, _) | (_, Less) => IntersectionInner::Answer(None), + (Equal, _) => IntersectionInner::Answer(Some(self_min)), + (_, Equal) => IntersectionInner::Answer(Some(self_max)), + _ if self.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: self.iter(), large_set: other } + } + _ if other.len() <= self.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF => { + IntersectionInner::Search { small_iter: other.iter(), large_set: self } + } + _ => IntersectionInner::Stitch { a: self.iter(), b: other.iter() }, + }, + } + } else { + Intersection { inner: IntersectionInner::Answer(None) } } } @@ -694,55 +686,56 @@ impl BTreeSet { // Same result as self.difference(other).next().is_none() // but the code below is faster (hugely in some cases). if self.len() > other.len() { - return false; + return false; // self has more elements than other } - let (self_min, self_max) = - if let (Some(self_min), Some(self_max)) = (self.first(), self.last()) { - (self_min, self_max) - } else { - return true; // self is empty - }; - let (other_min, other_max) = - if let (Some(other_min), Some(other_max)) = (other.first(), other.last()) { - (other_min, other_max) - } else { - return false; // other is empty - }; + let (Some(self_min), Some(self_max)) = (self.first(), self.last()) else { + return true; // self is empty + }; + let (Some(other_min), Some(other_max)) = (other.first(), other.last()) else { + return false; // other is empty + }; let mut self_iter = self.iter(); match self_min.cmp(other_min) { - Less => return false, + Less => return false, // other does not contain self_min Equal => { - self_iter.next(); + self_iter.next(); // self_min is contained in other, so remove it from consideration + // other_min is now not in self_iter (used below) } - Greater => (), - } + Greater => {} // other_min is not in self_iter (used below) + }; + match self_max.cmp(other_max) { - Greater => return false, + Greater => return false, // other does not contain self_max Equal => { - self_iter.next_back(); + self_iter.next_back(); // self_max is contained in other, so remove it from consideration + // other_max is now not in self_iter (used below) } - Less => (), - } + Less => {} // other_max is not in self_iter (used below) + }; if self_iter.len() <= other.len() / ITER_PERFORMANCE_TIPPING_SIZE_DIFF { - for next in self_iter { - if !other.contains(next) { - return false; - } - } + self_iter.all(|e| other.contains(e)) } else { let mut other_iter = other.iter(); - other_iter.next(); - 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)) { - Less => return false, - Equal => self_next = self_iter.next(), - Greater => (), - } + { + // remove other_min and other_max as they are not in self_iter (see above) + other_iter.next(); + other_iter.next_back(); } + // custom `self_iter.all(|e| other.contains(e))` + self_iter.all(|self1| { + while let Some(other1) = other_iter.next() { + match other1.cmp(self1) { + // happens up to `ITER_PERFORMANCE_TIPPING_SIZE_DIFF * self.len() - 1` times + Less => continue, // skip over elements that are smaller + // happens `self.len()` times + Equal => return true, // self1 is in other + // happens only once + Greater => return false, // self1 is not in other + } + } + false + }) } - true } /// Returns `true` if the set is a superset of another, diff --git a/library/alloctests/Cargo.toml b/library/alloctests/Cargo.toml index 07c45d1b82484..3b522bf80a217 100644 --- a/library/alloctests/Cargo.toml +++ b/library/alloctests/Cargo.toml @@ -6,7 +6,7 @@ repository = "https://github.com/rust-lang/rust.git" description = "Tests for the Rust Allocation Library" autotests = false autobenches = false -edition = "2021" +edition = "2024" [lib] path = "lib.rs" diff --git a/tests/run-make/alloc-no-oom-handling/rmake.rs b/tests/run-make/alloc-no-oom-handling/rmake.rs index 89a6636d9a0cc..94002eca5736f 100644 --- a/tests/run-make/alloc-no-oom-handling/rmake.rs +++ b/tests/run-make/alloc-no-oom-handling/rmake.rs @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; fn main() { rustc() - .edition("2021") + .edition("2024") .arg("-Dwarnings") .crate_type("rlib") .input(source_root().join("library/alloc/src/lib.rs")) diff --git a/tests/run-make/alloc-no-rc/rmake.rs b/tests/run-make/alloc-no-rc/rmake.rs index 12171c2148f1d..8d8cd4990bc65 100644 --- a/tests/run-make/alloc-no-rc/rmake.rs +++ b/tests/run-make/alloc-no-rc/rmake.rs @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; fn main() { rustc() - .edition("2021") + .edition("2024") .arg("-Dwarnings") .crate_type("rlib") .input(source_root().join("library/alloc/src/lib.rs")) diff --git a/tests/run-make/alloc-no-sync/rmake.rs b/tests/run-make/alloc-no-sync/rmake.rs index 29f204f30673e..a096d3941d466 100644 --- a/tests/run-make/alloc-no-sync/rmake.rs +++ b/tests/run-make/alloc-no-sync/rmake.rs @@ -6,7 +6,7 @@ use run_make_support::{rustc, source_root}; fn main() { rustc() - .edition("2021") + .edition("2024") .arg("-Dwarnings") .crate_type("rlib") .input(source_root().join("library/alloc/src/lib.rs"))