From 9d9b55cd2b14bce066cef83d9d85ba798a2ba95c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 15 Jul 2024 21:25:03 +0200 Subject: [PATCH 01/12] make invalid_type_param_default lint show up in cargo future-compat reports and remove the feature gate that silenced the lint --- compiler/rustc_feature/src/removed.rs | 3 ++ compiler/rustc_feature/src/unstable.rs | 2 - .../src/collect/generics_of.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 2 +- ...ate-default_type_parameter_fallback.stderr | 21 --------- tests/ui/impl-trait/where-allowed.stderr | 22 ++++++++++ tests/ui/issues/issue-26812.rs | 4 +- tests/ui/issues/issue-26812.stderr | 25 ++++++++++- .../lifetimes/unusual-rib-combinations.stderr | 11 +++++ ...ed-type-param-in-fn-with-assoc-type.stderr | 10 +++++ .../default_type_parameter_in_fn_or_impl.rs} | 0 ...efault_type_parameter_in_fn_or_impl.stderr | 43 +++++++++++++++++++ 12 files changed, 115 insertions(+), 30 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr rename tests/ui/{feature-gates/feature-gate-default_type_parameter_fallback.rs => type/default_type_parameter_in_fn_or_impl.rs} (100%) create mode 100644 tests/ui/type/default_type_parameter_in_fn_or_impl.stderr diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index f13aa506c1ec0..a78ae0d6993e2 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -75,6 +75,9 @@ declare_features! ( /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`. (removed, custom_derive, "1.32.0", Some(29644), Some("subsumed by `#[proc_macro_derive]`")), + /// Allows default type parameters to influence type inference. + (removed, default_type_parameter_fallback, "CURRENT_RUSTC_VERSION", Some(27336), + Some("never properly implemented; requires significant design work")), /// Allows using `#[doc(keyword = "...")]`. (removed, doc_keyword, "1.28.0", Some(51315), Some("merged into `#![feature(rustdoc_internals)]`")), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 948499fb38fbf..407800ce60d5d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -428,8 +428,6 @@ declare_features! ( (unstable, custom_test_frameworks, "1.30.0", Some(50297)), /// Allows declarative macros 2.0 (`macro`). (unstable, decl_macro, "1.17.0", Some(39412)), - /// Allows default type parameters to influence type inference. - (unstable, default_type_parameter_fallback, "1.3.0", Some(27336)), /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait (unstable, deprecated_safe, "1.61.0", Some(94978)), /// Allows having using `suggestion` in the `#[deprecated]` attribute. diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 22d465c8e62be..398a496a3737f 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -323,8 +323,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if default.is_some() { match allow_defaults { Defaults::Allowed => {} - Defaults::FutureCompatDisallowed - if tcx.features().default_type_parameter_fallback => {} Defaults::FutureCompatDisallowed => { tcx.node_span_lint( lint::builtin::INVALID_TYPE_PARAM_DEFAULT, diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index aa7844f40121b..276a507d3e89b 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -1241,7 +1241,7 @@ declare_lint! { Deny, "type parameter default erroneously allowed in invalid location", @future_incompatible = FutureIncompatibleInfo { - reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps, reference: "issue #36887 ", }; } diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr deleted file mode 100644 index 308de2692930d..0000000000000 --- a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ /dev/null @@ -1,21 +0,0 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 - | -LL | fn avg(_: T) {} - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - = note: `#[deny(invalid_type_param_default)]` on by default - -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions - --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 - | -LL | impl S {} - | ^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #36887 - -error: aborting due to 2 previous errors - diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr index f0d259d01de94..1fb69db98c162 100644 --- a/tests/ui/impl-trait/where-allowed.stderr +++ b/tests/ui/impl-trait/where-allowed.stderr @@ -433,3 +433,25 @@ error: aborting due to 50 previous errors Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0599, E0658, E0666. For more information about an error, try `rustc --explain E0053`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:239:7 + | +LL | impl T {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/where-allowed.rs:246:36 + | +LL | fn in_method_generic_param_default(_: T) {} + | ^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/issues/issue-26812.rs b/tests/ui/issues/issue-26812.rs index 3391ea4b350af..e0723e016b381 100644 --- a/tests/ui/issues/issue-26812.rs +++ b/tests/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ -#![feature(default_type_parameter_fallback)] - fn avg(_: T) {} //~^ ERROR generic parameters with a default cannot use forward declared identifiers +//~| ERROR defaults for type parameters +//~| WARN previously accepted fn main() {} diff --git a/tests/ui/issues/issue-26812.stderr b/tests/ui/issues/issue-26812.stderr index c2a3d4b83d536..4a18b23fd8b13 100644 --- a/tests/ui/issues/issue-26812.stderr +++ b/tests/ui/issues/issue-26812.stderr @@ -1,9 +1,30 @@ error[E0128]: generic parameters with a default cannot use forward declared identifiers - --> $DIR/issue-26812.rs:3:10 + --> $DIR/issue-26812.rs:1:10 | LL | fn avg(_: T) {} | ^^^^^^^ defaulted generic parameters cannot be forward declared -error: aborting due to 1 previous error +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0128`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/issue-26812.rs:1:8 + | +LL | fn avg(_: T) {} + | ^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/lifetimes/unusual-rib-combinations.stderr b/tests/ui/lifetimes/unusual-rib-combinations.stderr index 70f06b4be603c..3f97ae6c5bd54 100644 --- a/tests/ui/lifetimes/unusual-rib-combinations.stderr +++ b/tests/ui/lifetimes/unusual-rib-combinations.stderr @@ -68,3 +68,14 @@ error: aborting due to 8 previous errors Some errors have detailed explanations: E0106, E0214, E0308, E0770. For more information about an error, try `rustc --explain E0106`. +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unusual-rib-combinations.rs:15:6 + | +LL | fn c() {} + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + diff --git a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr index dc0bea58a70e8..bf8829c09257f 100644 --- a/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr +++ b/tests/ui/type-inference/unbounded-type-param-in-fn-with-assoc-type.stderr @@ -12,3 +12,13 @@ LL | foo::(); error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0282`. +Future incompatibility report: Future breakage diagnostic: +warning: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/unbounded-type-param-in-fn-with-assoc-type.rs:3:11 + | +LL | fn foo() -> (T, U) { + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + diff --git a/tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs b/tests/ui/type/default_type_parameter_in_fn_or_impl.rs similarity index 100% rename from tests/ui/feature-gates/feature-gate-default_type_parameter_fallback.rs rename to tests/ui/type/default_type_parameter_in_fn_or_impl.rs diff --git a/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr new file mode 100644 index 0000000000000..a3205cd3c29ca --- /dev/null +++ b/tests/ui/type/default_type_parameter_in_fn_or_impl.stderr @@ -0,0 +1,43 @@ +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:3:8 + | +LL | fn avg(_: T) {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + +Future breakage diagnostic: +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_type_parameter_in_fn_or_impl.rs:8:6 + | +LL | impl S {} + | ^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #36887 + = note: `#[deny(invalid_type_param_default)]` on by default + From 468f9358f3f73db9a0ea6dc1a94320177718061a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 21 Jul 2024 09:43:06 +0100 Subject: [PATCH 02/12] std::thread: available_parallelism implementation for vxWorks proposal. --- library/std/src/sys/pal/unix/thread.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs index 619f4e4121e73..0f496a39173a0 100644 --- a/library/std/src/sys/pal/unix/thread.rs +++ b/library/std/src/sys/pal/unix/thread.rs @@ -462,8 +462,18 @@ pub fn available_parallelism() -> io::Result> { Ok(NonZero::new_unchecked(sinfo.cpu_count as usize)) } + } else if #[cfg(target_os = "vxworks")] { + // Note: there is also `vxCpuConfiguredGet`, closer to _SC_NPROCESSORS_CONF + // expectations than the actual cores availability. + extern "C" { + fn vxCpuEnabledGet() -> libc::cpuset_t; + } + + // always fetches a valid bitmask + let set = unsafe { vxCpuEnabledGet() }; + Ok(NonZero::new_unchecked(set.count_ones() as usize)) } else { - // FIXME: implement on vxWorks, Redox, l4re + // FIXME: implement on Redox, l4re Err(io::const_io_error!(io::ErrorKind::Unsupported, "Getting the number of hardware threads is not supported on the target platform")) } } From 9b165a16009980545a864eb5899c3b3279f58f37 Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Sun, 28 Jul 2024 15:03:07 +0100 Subject: [PATCH 03/12] Implement cursors for `BTreeSet` --- library/alloc/src/collections/btree/set.rs | 427 ++++++++++++++++++++- 1 file changed, 426 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index b0bd6ef2d3c63..6f23d686bcf8e 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -2,11 +2,12 @@ use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; +use core::error::Error; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use core::iter::{FusedIterator, Peekable}; use core::mem::ManuallyDrop; -use core::ops::{BitAnd, BitOr, BitXor, RangeBounds, Sub}; +use core::ops::{BitAnd, BitOr, BitXor, Bound, RangeBounds, Sub}; use super::map::{BTreeMap, Keys}; use super::merge_iter::MergeIterInner; @@ -1183,6 +1184,178 @@ impl BTreeSet { pub const fn is_empty(&self) -> bool { self.len() == 0 } + + /// Returns a [`Cursor`] pointing at the gap before the smallest element + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest element greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest element greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest element in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let cursor = set.lower_bound(Bound::Included(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&1)); + /// assert_eq!(cursor.peek_next(), Some(&2)); + /// + /// let cursor = set.lower_bound(Bound::Excluded(&2)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let cursor = set.lower_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some(&1)); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn lower_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T> + where + T: Borrow + Ord, + Q: Ord, + { + Cursor { inner: self.map.lower_bound(bound) } + } + + /// Returns a [`CursorMut`] pointing at the gap before the smallest element + /// greater than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap before the smallest element greater than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap before the smallest element greater than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap before the smallest element in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let mut set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Included(&2)) }; + /// assert_eq!(cursor.peek_prev(), Some(&mut 1)); + /// assert_eq!(cursor.peek_next(), Some(&mut 2)); + /// + /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Excluded(&2)) }; + /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); + /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// + /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Unbounded) }; + /// assert_eq!(cursor.peek_prev(), None); + /// assert_eq!(cursor.peek_next(), Some(&mut 1)); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + where + T: Borrow + Ord, + Q: Ord, + { + CursorMut { inner: unsafe { self.map.lower_bound_mut(bound).with_mutable_key() } } + } + + /// Returns a [`Cursor`] pointing at the gap after the greatest element + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest element in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let cursor = set.upper_bound(Bound::Included(&3)); + /// assert_eq!(cursor.peek_prev(), Some(&3)); + /// assert_eq!(cursor.peek_next(), Some(&4)); + /// + /// let cursor = set.upper_bound(Bound::Excluded(&3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); + /// + /// let cursor = set.upper_bound(Bound::Unbounded); + /// assert_eq!(cursor.peek_prev(), Some(&4)); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn upper_bound(&self, bound: Bound<&Q>) -> Cursor<'_, T> + where + T: Borrow + Ord, + Q: Ord, + { + Cursor { inner: self.map.upper_bound(bound) } + } + + /// Returns a [`CursorMut`] pointing at the gap after the greatest element + /// smaller than the given bound. + /// + /// Passing `Bound::Included(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than or equal to `x`. + /// + /// Passing `Bound::Excluded(x)` will return a cursor pointing to the + /// gap after the greatest element smaller than `x`. + /// + /// Passing `Bound::Unbounded` will return a cursor pointing to the + /// gap after the greatest element in the map. + /// + /// # Examples + /// + /// ``` + /// #![feature(btree_cursors)] + /// + /// use std::collections::BTreeSet; + /// use std::ops::Bound; + /// + /// let mut set = BTreeSet::from([1, 2, 3, 4]); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) }; + /// assert_eq!(cursor.peek_prev(), Some(&mut 3)); + /// assert_eq!(cursor.peek_next(), Some(&mut 4)); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) }; + /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); + /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// + /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) }; + /// assert_eq!(cursor.peek_prev(), Some(&mut 4)); + /// assert_eq!(cursor.peek_next(), None); + /// ``` + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn upper_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + where + T: Borrow + Ord, + Q: Ord, + { + CursorMut { inner: unsafe { self.map.upper_bound_mut(bound).with_mutable_key() } } + } } #[stable(feature = "rust1", since = "1.0.0")] @@ -1817,5 +1990,257 @@ impl<'a, T: Ord> Iterator for Union<'a, T> { #[stable(feature = "fused", since = "1.26.0")] impl FusedIterator for Union<'_, T> {} +/// A cursor over a `BTreeSet`. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `Cursor` is created with the [`BTreeSet::lower_bound`] and [`BTreeSet::upper_bound`] methods. +#[derive(Clone)] +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct Cursor<'a, K: 'a> { + inner: super::map::Cursor<'a, K, SetValZST>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for Cursor<'_, K> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("Cursor") + } +} + +/// A cursor over a `BTreeSet` with editing operations, and which allows +/// mutating elements. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the set during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying set. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and +/// [`BTreeSet::upper_bound_mut`] methods. +/// +/// # Safety +/// +/// Since this cursor allows mutating elements, you must ensure that the +/// `BTreeSet` invariants are maintained. Specifically: +/// +/// * The newly inserted element must be unique in the tree. +/// * All elements in the tree must remain in sorted order. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> +{ + inner: super::map::CursorMutKey<'a, K, SetValZST, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMut<'_, K, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMut") + } +} + +impl<'a, K> Cursor<'a, K> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&'a K> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&'a K> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&self) -> Option<&'a K> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&self) -> Option<&'a K> { + self.inner.peek_prev().map(|(k, _)| k) + } +} + +impl<'a, T, A> CursorMut<'a, T, A> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&mut T> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&mut T> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to the next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<&mut T> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + self.inner.peek_prev().map(|(k, _)| k) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMut`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMut`, which means it cannot outlive the `CursorMut` and that the + /// `CursorMut` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { inner: self.inner.as_cursor() } + } +} + +impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_after_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_before_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedError> { + self.inner.insert_after(value, SetValZST).map_err(UnorderedError::from_map_error) + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedError> { + self.inner.insert_before(value, SetValZST).map_err(UnorderedError::from_map_error) + } + + /// Removes the next element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option { + self.inner.remove_next().map(|(k, _)| k) + } + + /// Removes the precending element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option { + self.inner.remove_prev().map(|(k, _)| k) + } +} + +/// Error type returned by [`CursorMut::insert_before`] and +/// [`CursorMut::insert_after`] if the element being inserted is not properly +/// ordered with regards to adjacent elements. +#[derive(Clone, PartialEq, Eq, Debug)] +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct UnorderedError {} + +impl UnorderedError { + fn from_map_error(error: super::map::UnorderedKeyError) -> Self { + let super::map::UnorderedKeyError {} = error; + Self {} + } +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl fmt::Display for UnorderedError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "value is not properly ordered relative to neighbors") + } +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Error for UnorderedError {} + #[cfg(test)] mod tests; From bbeff8c7862ad70fada412502324ecd41d1dea14 Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 30 Jul 2024 16:55:45 +0300 Subject: [PATCH 04/12] set `force_recompile: true` if library is modified This allows the standard library to be compiled even with `download-rustc` enabled. Which means it's no longer a requirement to compile `rustc` in order to compile `std`. Signed-off-by: onur-ozkan --- src/bootstrap/src/core/build_steps/compile.rs | 39 +++++++++++++++---- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 268e89c7f6011..c09180e542ff6 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -26,7 +26,8 @@ use crate::core::builder::{ use crate::core::config::{DebuginfoLevel, LlvmLibunwind, RustcLto, TargetSelection}; use crate::utils::exec::command; use crate::utils::helpers::{ - exe, get_clang_cl_resource_dir, is_debug_info, is_dylib, symlink_dir, t, up_to_date, + self, exe, get_clang_cl_resource_dir, get_closest_merge_base_commit, is_debug_info, is_dylib, + symlink_dir, t, up_to_date, }; use crate::{CLang, Compiler, DependencyType, GitRepo, Mode, LLVM_TOOLS}; @@ -114,21 +115,43 @@ impl Step for Std { const DEFAULT: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - // When downloading stage1, the standard library has already been copied to the sysroot, so - // there's no need to rebuild it. - let builder = run.builder; - run.crate_or_deps("sysroot") - .path("library") - .lazy_default_condition(Box::new(|| !builder.download_rustc())) + run.crate_or_deps("sysroot").path("library") } fn make_run(run: RunConfig<'_>) { let crates = std_crates_for_run_make(&run); + let builder = run.builder; + + // Force compilation of the standard library from source if the `library` is modified. This allows + // library team to compile the standard library without needing to compile the compiler with + // the `rust.download-rustc=true` option. + let force_recompile = + if builder.rust_info().is_managed_git_subrepository() && builder.download_rustc() { + let closest_merge_commit = get_closest_merge_base_commit( + Some(&builder.src), + &builder.config.git_config(), + &builder.config.stage0_metadata.config.git_merge_commit_email, + &[], + ) + .unwrap(); + + // Check if `library` has changes (returns false otherwise) + !t!(helpers::git(Some(&builder.src)) + .args(["diff-index", "--quiet", &closest_merge_commit]) + .arg("--") + .arg(builder.src.join("library")) + .as_command_mut() + .status()) + .success() + } else { + false + }; + run.builder.ensure(Std { compiler: run.builder.compiler(run.builder.top_stage, run.build_triple()), target: run.target, crates, - force_recompile: false, + force_recompile, extra_rust_args: &[], is_for_mir_opt_tests: false, }); From 6fcc630e56263d7d17a37a77202717f1c83c5b2a Mon Sep 17 00:00:00 2001 From: onur-ozkan Date: Tue, 30 Jul 2024 16:56:47 +0300 Subject: [PATCH 05/12] update download-rustc documentation Signed-off-by: onur-ozkan --- config.example.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config.example.toml b/config.example.toml index 45faa66ec114f..1a7bdc4737fbf 100644 --- a/config.example.toml +++ b/config.example.toml @@ -472,7 +472,8 @@ # This is mostly useful for tools; if you have changes to `compiler/` or `library/` they will be ignored. # # Set this to "if-unchanged" to only download if the compiler and standard library have not been modified. -# Set this to `true` to download unconditionally (useful if e.g. you are only changing doc-comments). +# Set this to `true` to download unconditionally. This is useful if you are working on tools, doc-comments, +# or library (you will be able to build the standard library without needing to build the compiler). #download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 From 020476296b1aa60f79c2f671c48542afe99cc428 Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:23:18 +0100 Subject: [PATCH 06/12] Share `UnorderedKeyError` with `BTReeMap` for set API --- library/alloc/src/collections/btree/set.rs | 36 +++++----------------- 1 file changed, 7 insertions(+), 29 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 6f23d686bcf8e..0fc892eec6504 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -2,7 +2,6 @@ use crate::vec::Vec; use core::borrow::Borrow; use core::cmp::Ordering::{self, Equal, Greater, Less}; use core::cmp::{max, min}; -use core::error::Error; use core::fmt::{self, Debug}; use core::hash::{Hash, Hasher}; use core::iter::{FusedIterator, Peekable}; @@ -2177,11 +2176,11 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// /// If the inserted element is not greater than the element before the /// cursor (if any), or if it not less than the element after the cursor (if - /// any), then an [`UnorderedError`] is returned since this would + /// any), then an [`UnorderedKeyError`] is returned since this would /// invalidate the [`Ord`] invariant between the elements of the set. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedError> { - self.inner.insert_after(value, SetValZST).map_err(UnorderedError::from_map_error) + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) } /// Inserts a new element into the set in the gap that the @@ -2192,11 +2191,11 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { /// /// If the inserted element is not greater than the element before the /// cursor (if any), or if it not less than the element after the cursor (if - /// any), then an [`UnorderedError`] is returned since this would + /// any), then an [`UnorderedKeyError`] is returned since this would /// invalidate the [`Ord`] invariant between the elements of the set. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedError> { - self.inner.insert_before(value, SetValZST).map_err(UnorderedError::from_map_error) + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) } /// Removes the next element from the `BTreeSet`. @@ -2218,29 +2217,8 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { } } -/// Error type returned by [`CursorMut::insert_before`] and -/// [`CursorMut::insert_after`] if the element being inserted is not properly -/// ordered with regards to adjacent elements. -#[derive(Clone, PartialEq, Eq, Debug)] #[unstable(feature = "btree_cursors", issue = "107540")] -pub struct UnorderedError {} - -impl UnorderedError { - fn from_map_error(error: super::map::UnorderedKeyError) -> Self { - let super::map::UnorderedKeyError {} = error; - Self {} - } -} - -#[unstable(feature = "btree_cursors", issue = "107540")] -impl fmt::Display for UnorderedError { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!(f, "value is not properly ordered relative to neighbors") - } -} - -#[unstable(feature = "btree_cursors", issue = "107540")] -impl Error for UnorderedError {} +pub use super::map::UnorderedKeyError; #[cfg(test)] mod tests; From 4560770451a21c3beca5808e362b6fe34c7371ae Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:47:06 +0100 Subject: [PATCH 07/12] Fix some uses of "map" instead of "set" in `BTreeSet` cursor API docs --- library/alloc/src/collections/btree/set.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 0fc892eec6504..47b7e56ddf050 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1194,7 +1194,7 @@ impl BTreeSet { /// gap before the smallest element greater than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap before the smallest element in the map. + /// gap before the smallest element in the set. /// /// # Examples /// @@ -1237,7 +1237,7 @@ impl BTreeSet { /// gap before the smallest element greater than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap before the smallest element in the map. + /// gap before the smallest element in the set. /// /// # Examples /// @@ -1280,7 +1280,7 @@ impl BTreeSet { /// gap after the greatest element smaller than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap after the greatest element in the map. + /// gap after the greatest element in the set. /// /// # Examples /// @@ -1323,7 +1323,7 @@ impl BTreeSet { /// gap after the greatest element smaller than `x`. /// /// Passing `Bound::Unbounded` will return a cursor pointing to the - /// gap after the greatest element in the map. + /// gap after the greatest element in the set. /// /// # Examples /// From cbdc3778667c5bad3f9eee4124000a0ca96e4590 Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 19:47:28 +0100 Subject: [PATCH 08/12] Introduce `Cursor`/`CursorMut`/`CursorMutKey` thrichotomy for `BTreeSet` like map API --- library/alloc/src/collections/btree/set.rs | 210 +++++++++++++++++++-- 1 file changed, 194 insertions(+), 16 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 47b7e56ddf050..86401714639c0 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1249,25 +1249,25 @@ impl BTreeSet { /// /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Included(&2)) }; + /// let mut cursor = set.lower_bound_mut(Bound::Included(&2)); /// assert_eq!(cursor.peek_prev(), Some(&mut 1)); /// assert_eq!(cursor.peek_next(), Some(&mut 2)); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Excluded(&2)) }; + /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2)); /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); /// assert_eq!(cursor.peek_next(), Some(&mut 3)); /// - /// let mut cursor = unsafe { set.lower_bound_mut(Bound::Unbounded) }; + /// let mut cursor = set.lower_bound_mut(Bound::Unbounded); /// assert_eq!(cursor.peek_prev(), None); /// assert_eq!(cursor.peek_next(), Some(&mut 1)); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] - pub unsafe fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> + pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> where T: Borrow + Ord, Q: Ord, { - CursorMut { inner: unsafe { self.map.lower_bound_mut(bound).with_mutable_key() } } + CursorMut { inner: self.map.lower_bound_mut(bound) } } /// Returns a [`Cursor`] pointing at the gap after the greatest element @@ -1353,7 +1353,7 @@ impl BTreeSet { T: Borrow + Ord, Q: Ord, { - CursorMut { inner: unsafe { self.map.upper_bound_mut(bound).with_mutable_key() } } + CursorMut { inner: self.map.upper_bound_mut(bound) } } } @@ -2010,6 +2010,31 @@ impl Debug for Cursor<'_, K> { } } +/// A cursor over a `BTreeSet` with editing operations. +/// +/// A `Cursor` is like an iterator, except that it can freely seek back-and-forth, and can +/// safely mutate the set during iteration. This is because the lifetime of its yielded +/// references is tied to its own lifetime, instead of just the underlying map. This means +/// cursors cannot yield multiple elements at once. +/// +/// Cursors always point to a gap between two elements in the set, and can +/// operate on the two immediately adjacent elements. +/// +/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and [`BTreeSet::upper_bound_mut`] +/// methods. +#[unstable(feature = "btree_cursors", issue = "107540")] +pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> +{ + inner: super::map::CursorMut<'a, K, SetValZST, A>, +} + +#[unstable(feature = "btree_cursors", issue = "107540")] +impl Debug for CursorMut<'_, K, A> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str("CursorMut") + } +} + /// A cursor over a `BTreeSet` with editing operations, and which allows /// mutating elements. /// @@ -2021,8 +2046,8 @@ impl Debug for Cursor<'_, K> { /// Cursors always point to a gap between two elements in the set, and can /// operate on the two immediately adjacent elements. /// -/// A `CursorMut` is created with the [`BTreeSet::lower_bound_mut`] and -/// [`BTreeSet::upper_bound_mut`] methods. +/// A `CursorMutKey` is created from a [`CursorMut`] with the +/// [`CursorMut::with_mutable_key`] method. /// /// # Safety /// @@ -2032,15 +2057,18 @@ impl Debug for Cursor<'_, K> { /// * The newly inserted element must be unique in the tree. /// * All elements in the tree must remain in sorted order. #[unstable(feature = "btree_cursors", issue = "107540")] -pub struct CursorMut<'a, K: 'a, #[unstable(feature = "allocator_api", issue = "32838")] A = Global> -{ +pub struct CursorMutKey< + 'a, + K: 'a, + #[unstable(feature = "allocator_api", issue = "32838")] A = Global, +> { inner: super::map::CursorMutKey<'a, K, SetValZST, A>, } #[unstable(feature = "btree_cursors", issue = "107540")] -impl Debug for CursorMut<'_, K, A> { +impl Debug for CursorMutKey<'_, K, A> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str("CursorMut") + f.write_str("CursorMutKey") } } @@ -2089,7 +2117,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// If the cursor is already at the end of the set then `None` is returned /// and the cursor is not moved. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn next(&mut self) -> Option<&mut T> { + pub fn next(&mut self) -> Option<&T> { self.inner.next().map(|(k, _)| k) } @@ -2099,7 +2127,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// If the cursor is already at the start of the set then `None` is returned /// and the cursor is not moved. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn prev(&mut self) -> Option<&mut T> { + pub fn prev(&mut self) -> Option<&T> { self.inner.prev().map(|(k, _)| k) } @@ -2107,7 +2135,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// /// If the cursor is at the end of the set then `None` is returned. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn peek_next(&mut self) -> Option<&mut T> { + pub fn peek_next(&mut self) -> Option<&T> { self.inner.peek_next().map(|(k, _)| k) } @@ -2115,7 +2143,7 @@ impl<'a, T, A> CursorMut<'a, T, A> { /// /// If the cursor is at the start of the set then `None` is returned. #[unstable(feature = "btree_cursors", issue = "107540")] - pub fn peek_prev(&mut self) -> Option<&mut T> { + pub fn peek_prev(&mut self) -> Option<&T> { self.inner.peek_prev().map(|(k, _)| k) } @@ -2129,6 +2157,70 @@ impl<'a, T, A> CursorMut<'a, T, A> { pub fn as_cursor(&self) -> Cursor<'_, T> { Cursor { inner: self.inner.as_cursor() } } + + /// Converts the cursor into a [`CursorMutKey`], which allows mutating + /// elements in the tree. + /// + /// # Safety + /// + /// Since this cursor allows mutating elements, you must ensure that the + /// `BTreeSet` invariants are maintained. Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn with_mutable_key(self) -> CursorMutKey<'a, T, A> { + CursorMutKey { inner: unsafe { self.inner.with_mutable_key() } } + } +} + +impl<'a, T, A> CursorMutKey<'a, T, A> { + /// Advances the cursor to the next gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the end of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn next(&mut self) -> Option<&mut T> { + self.inner.next().map(|(k, _)| k) + } + + /// Advances the cursor to the previous gap, returning the element that it + /// moved over. + /// + /// If the cursor is already at the start of the set then `None` is returned + /// and the cursor is not moved. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn prev(&mut self) -> Option<&mut T> { + self.inner.prev().map(|(k, _)| k) + } + + /// Returns a reference to the next element without moving the cursor. + /// + /// If the cursor is at the end of the set then `None` is returned + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_next(&mut self) -> Option<&mut T> { + self.inner.peek_next().map(|(k, _)| k) + } + + /// Returns a reference to the previous element without moving the cursor. + /// + /// If the cursor is at the start of the set then `None` is returned. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn peek_prev(&mut self) -> Option<&mut T> { + self.inner.peek_prev().map(|(k, _)| k) + } + + /// Returns a read-only cursor pointing to the same location as the + /// `CursorMutKey`. + /// + /// The lifetime of the returned `Cursor` is bound to that of the + /// `CursorMutKey`, which means it cannot outlive the `CursorMutKey` and that the + /// `CursorMutKey` is frozen for the lifetime of the `Cursor`. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn as_cursor(&self) -> Cursor<'_, T> { + Cursor { inner: self.inner.as_cursor() } + } } impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { @@ -2217,6 +2309,92 @@ impl<'a, T: Ord, A: Allocator + Clone> CursorMut<'a, T, A> { } } +impl<'a, T: Ord, A: Allocator + Clone> CursorMutKey<'a, T, A> { + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The key of the newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_after_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_after_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// # Safety + /// + /// You must ensure that the `BTreeSet` invariants are maintained. + /// Specifically: + /// + /// * The newly inserted element must be unique in the tree. + /// * All elements in the tree must remain in sorted order. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub unsafe fn insert_before_unchecked(&mut self, value: T) { + unsafe { self.inner.insert_before_unchecked(value, SetValZST) } + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap before the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_after(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_after(value, SetValZST) + } + + /// Inserts a new element into the set in the gap that the + /// cursor is currently pointing to. + /// + /// After the insertion the cursor will be pointing at the gap after the + /// newly inserted element. + /// + /// If the inserted element is not greater than the element before the + /// cursor (if any), or if it not less than the element after the cursor (if + /// any), then an [`UnorderedKeyError`] is returned since this would + /// invalidate the [`Ord`] invariant between the elements of the set. + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn insert_before(&mut self, value: T) -> Result<(), UnorderedKeyError> { + self.inner.insert_before(value, SetValZST) + } + + /// Removes the next element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (before the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_next(&mut self) -> Option { + self.inner.remove_next().map(|(k, _)| k) + } + + /// Removes the precending element from the `BTreeSet`. + /// + /// The element that was removed is returned. The cursor position is + /// unchanged (after the removed element). + #[unstable(feature = "btree_cursors", issue = "107540")] + pub fn remove_prev(&mut self) -> Option { + self.inner.remove_prev().map(|(k, _)| k) + } +} + #[unstable(feature = "btree_cursors", issue = "107540")] pub use super::map::UnorderedKeyError; From 0bc501e0addf9dec2fe87613c5fdc6180364aceb Mon Sep 17 00:00:00 2001 From: Ken Micklas Date: Thu, 1 Aug 2024 21:02:51 +0100 Subject: [PATCH 09/12] Fix mutability in doc tests for `BTreeSet` cursors --- library/alloc/src/collections/btree/set.rs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/collections/btree/set.rs b/library/alloc/src/collections/btree/set.rs index 86401714639c0..362e32cc8f46a 100644 --- a/library/alloc/src/collections/btree/set.rs +++ b/library/alloc/src/collections/btree/set.rs @@ -1250,16 +1250,16 @@ impl BTreeSet { /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// /// let mut cursor = set.lower_bound_mut(Bound::Included(&2)); - /// assert_eq!(cursor.peek_prev(), Some(&mut 1)); - /// assert_eq!(cursor.peek_next(), Some(&mut 2)); + /// assert_eq!(cursor.peek_prev(), Some(&1)); + /// assert_eq!(cursor.peek_next(), Some(&2)); /// /// let mut cursor = set.lower_bound_mut(Bound::Excluded(&2)); - /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); - /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); /// /// let mut cursor = set.lower_bound_mut(Bound::Unbounded); /// assert_eq!(cursor.peek_prev(), None); - /// assert_eq!(cursor.peek_next(), Some(&mut 1)); + /// assert_eq!(cursor.peek_next(), Some(&1)); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] pub fn lower_bound_mut(&mut self, bound: Bound<&Q>) -> CursorMut<'_, T, A> @@ -1336,15 +1336,15 @@ impl BTreeSet { /// let mut set = BTreeSet::from([1, 2, 3, 4]); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Included(&3)) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 3)); - /// assert_eq!(cursor.peek_next(), Some(&mut 4)); + /// assert_eq!(cursor.peek_prev(), Some(&3)); + /// assert_eq!(cursor.peek_next(), Some(&4)); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Excluded(&3)) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 2)); - /// assert_eq!(cursor.peek_next(), Some(&mut 3)); + /// assert_eq!(cursor.peek_prev(), Some(&2)); + /// assert_eq!(cursor.peek_next(), Some(&3)); /// /// let mut cursor = unsafe { set.upper_bound_mut(Bound::Unbounded) }; - /// assert_eq!(cursor.peek_prev(), Some(&mut 4)); + /// assert_eq!(cursor.peek_prev(), Some(&4)); /// assert_eq!(cursor.peek_next(), None); /// ``` #[unstable(feature = "btree_cursors", issue = "107540")] From 8497800abde9214041e11f35efdbfa437f761001 Mon Sep 17 00:00:00 2001 From: clubby789 Date: Thu, 1 Aug 2024 15:41:17 +0000 Subject: [PATCH 10/12] Add test for updating enum discriminant through pointer --- .../issue-122600-ptr-discriminant-update.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/codegen/issues/issue-122600-ptr-discriminant-update.rs diff --git a/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs new file mode 100644 index 0000000000000..4b520a6206951 --- /dev/null +++ b/tests/codegen/issues/issue-122600-ptr-discriminant-update.rs @@ -0,0 +1,19 @@ +//@ compile-flags: -O +//@ min-llvm-version: 19 + +#![crate_type = "lib"] + +pub enum State { + A([u8; 753]), + B([u8; 753]), +} + +// CHECK-LABEL: @update +#[no_mangle] +pub unsafe fn update(s: *mut State) { + // CHECK-NEXT: start: + // CHECK-NEXT: store i8 + // CHECK-NEXT: ret + let State::A(v) = s.read() else { std::hint::unreachable_unchecked() }; + s.write(State::B(v)); +} From 249afea2ff4a1e3cfbe5f40c42c6f84938ee3143 Mon Sep 17 00:00:00 2001 From: bohan Date: Sun, 4 Aug 2024 15:38:11 +0800 Subject: [PATCH 11/12] docs(resolve): more explain about `target` --- compiler/rustc_resolve/src/imports.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 0fa5cde9424b5..c7af21027b8d3 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -48,6 +48,7 @@ pub(crate) enum ImportKind<'a> { /// `source` in `use prefix::source as target`. source: Ident, /// `target` in `use prefix::source as target`. + /// It will directly use `source` when the format is `use prefix::source`. target: Ident, /// Bindings to which `source` refers to. source_bindings: PerNS, Determinacy>>>, From d8c2b767c6a18780a617d82c6a232253e447e5db Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 4 Aug 2024 11:03:27 +0000 Subject: [PATCH 12/12] run-make: enable msvc for link-dedup --- tests/run-make/link-dedup/rmake.rs | 33 ++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/tests/run-make/link-dedup/rmake.rs b/tests/run-make/link-dedup/rmake.rs index 9bff3a4b44c7d..6075f31095424 100644 --- a/tests/run-make/link-dedup/rmake.rs +++ b/tests/run-make/link-dedup/rmake.rs @@ -5,20 +5,37 @@ // Without the --cfg flag, there should be a single -ltesta, no more, no less. // See https://github.com/rust-lang/rust/pull/84794 -//@ ignore-msvc +use std::fmt::Write; -use run_make_support::rustc; +use run_make_support::{is_msvc, rustc}; fn main() { rustc().input("depa.rs").run(); rustc().input("depb.rs").run(); rustc().input("depc.rs").run(); + let output = rustc().input("empty.rs").cfg("bar").run_fail(); - output.assert_stderr_contains(r#""-ltesta" "-ltestb" "-ltesta""#); - let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_contains(r#""-ltesta""#); - let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_not_contains(r#""-ltestb""#); + output.assert_stderr_contains(needle_from_libs(&["testa", "testb", "testa"])); + let output = rustc().input("empty.rs").run_fail(); - output.assert_stderr_not_contains(r#""-ltesta" "-ltesta" "-ltesta""#); + output.assert_stderr_contains(needle_from_libs(&["testa"])); + output.assert_stderr_not_contains(needle_from_libs(&["testb"])); + output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa", "testa"])); + // Adjacent identical native libraries are no longer deduplicated if + // they come from different crates (https://github.com/rust-lang/rust/pull/103311) + // so the following will fail: + //output.assert_stderr_not_contains(needle_from_libs(&["testa", "testa"])); +} + +fn needle_from_libs(libs: &[&str]) -> String { + let mut needle = String::new(); + for lib in libs { + if is_msvc() { + let _ = needle.write_fmt(format_args!(r#""{lib}.lib" "#)); + } else { + let _ = needle.write_fmt(format_args!(r#""-l{lib}" "#)); + } + } + needle.pop(); // remove trailing space + needle }