From 2bfd067a0d20d373804b5bfe48071f30af2685e1 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Mon, 17 Aug 2026 10:42:55 -0700 Subject: [PATCH 1/6] Implement `AsMut` and `AsRef` for `!`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This will allow e.g. `&[!]` to satisfy `&[T] where T: AsRef`. It follows the recommendation from the never documentation: > When writing your own traits, `!` should have an `impl` whenever > there is an obvious `impl` which doesn’t `panic!`. -- A class of use case for these impls is: * some code is generic over `T: AsRef`, * and is still useful in the case where there are no `T`s, because it takes `Option` or `&[T]` or any other input that can be empty or never-called, yet still do things with other inputs, in which case providing `T = !` is slightly better than the alternative of providing an inhabited placeholder type, because it ensures that the generic code is compiled with knowledge of the fact that that there will never be any `T`s, even if the specific code that cares about whether there are any `T`s doesn’t get inlined into the call site that doesn’t provide any `T`s. The test tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs had to be updated because it depended on this impl not existing. I’ve confirmed that the modified test still functions as a regression test by compiling it in nightly-2022-08-28 and seeing it ICE. (cherry picked from commit d016eb115dfdc0005069f3fe517148ead96dd120) --- library/core/src/convert/mod.rs | 22 +++++++++++++++++++ ...h-implicit-hrtb-without-dyn.pre2021.stderr | 13 ++++------- .../generic-with-implicit-hrtb-without-dyn.rs | 4 ++-- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index b0f74a8afb598..c86c70b5c4ca1 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -863,6 +863,28 @@ const impl AsMut for str { } } +#[stable(feature = "never_type", since = "1.100.0")] +#[expect( + clippy::explicit_auto_deref, + reason = "https://github.com/rust-lang/rust-clippy/issues/17713" +)] +impl AsRef for ! { + fn as_ref(&self) -> &T { + *self + } +} + +#[stable(feature = "never_type", since = "1.100.0")] +#[expect( + clippy::explicit_auto_deref, + reason = "https://github.com/rust-lang/rust-clippy/issues/17713" +)] +impl AsMut for ! { + fn as_mut(&mut self) -> &mut T { + *self + } +} + //////////////////////////////////////////////////////////////////////////////// // THE NO-ERROR ERROR TYPE //////////////////////////////////////////////////////////////////////////////// diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr index dc566ad50153a..54ea4882c4669 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.pre2021.stderr @@ -1,16 +1,11 @@ -error[E0277]: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied +error[E0277]: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied --> $DIR/generic-with-implicit-hrtb-without-dyn.rs:7:13 | LL | fn ice() -> impl AsRef { - | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `!` + | ^^^^^^^^^^^^^^^^^^^ the trait `AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not implemented for `()` ... -LL | todo!() - | ------- return type was inferred to be `!` here - | -help: `!` can be coerced to any type; consider casting it to a concrete type that implements the trait - | -LL | todo!() as /* Type */ - | +++++++++++++ +LL | () + | -- return type was inferred to be `()` here error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs index 64311a474cade..6c538e8c8ee16 100644 --- a/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs +++ b/tests/ui/impl-trait/generic-with-implicit-hrtb-without-dyn.rs @@ -5,10 +5,10 @@ #![allow(warnings)] fn ice() -> impl AsRef { - //[pre2021]~^ ERROR: the trait bound `!: AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] + //[pre2021]~^ ERROR: the trait bound `(): AsRef<(dyn for<'a> Fn(&'a ()) + 'static)>` is not satisfied [E0277] //[edition2021]~^^ ERROR: expected a type, found a trait [E0782] //[edition2021]~| ERROR: expected a type, found a trait [E0782] - todo!() + () } fn main() {} From 5d2c7eecc9e4628fdadb2efbdc932d44ef86cfa3 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Fri, 25 Sep 2026 17:37:42 +0200 Subject: [PATCH 2/6] Document zero sized allocations in `Box` and `Vec` (cherry picked from commit 604a21cab2edf48dc9b40e1a513273d52aafa167) --- library/alloc/src/boxed.rs | 133 ++++++++++++++++---- library/alloc/src/string.rs | 4 + library/alloc/src/vec/mod.rs | 237 ++++++++++++----------------------- 3 files changed, 193 insertions(+), 181 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 3ca823c22199b..5e2ca8f200459 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -53,20 +53,26 @@ //! //! # Memory layout //! -//! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for its allocation. It is -//! valid to convert both ways between a [`Box`] and a raw pointer allocated with the [`Global`] -//! allocator, given that the [`Layout`] used with the allocator is correct for the type and the raw -//! pointer points to a valid value of the right type. More precisely, a `value: *mut T` that has -//! been allocated with the [`Global`] allocator with `Layout::for_value(&*value)` may be converted -//! into a box using [`Box::::from_raw(value)`]. Conversely, the memory backing a `value: *mut T` -//! obtained from [`Box::::into_raw`] may be deallocated using the [`Global`] allocator with -//! [`Layout::for_value(&*value)`]. +//! For non-zero-sized values, a [`Box`] will use its allocator of type `A` for its allocation. +//! It is valid to convert both ways between a `Box` and a raw pointer allocated with `A`, so long as: +//! - the size of the pointee, as reported by [`size_of_val`], is non-zero, +//! - the [`Layout::for_value`] of the pointee [*fits*](Allocator#memory-fitting) the memory block, and +//! - the pointee is a valid instance of `T` (for the given metadata of the pointer). //! -//! For zero-sized values, the `Box` pointer has to be non-null and sufficiently aligned. The -//! recommended way to build a Box to a ZST if `Box::new` cannot be used is to use -//! [`ptr::NonNull::dangling`]. +//! For zero-sized values, a [`Box`] may use any sufficiently aligned non-null pointer. +//! While it is sound to convert a zero-sized allocation from `A` into a `Box`, as +//! long as it is backed by a valid value of `T`, doing so may lead to memory leaks, as +//! the destructor of [`Box`] will not call [`deallocate`](Allocator::deallocate) +//! on zero-sized values. It is recommended to use [`ptr::dangling`] instead. //! -//! On top of these basic layout requirements, a `Box` must point to a valid value of `T`. +//! Likewise, manually deallocating the raw pointer acquired from a `Box` is only sound +//! if the size of the pointee is non-zero, as zero-sized values may be represented by +//! a pointer that is not [*currently allocated*] by that allocator. It is recommended to +//! pair [`Box::into_raw_with_allocator`] with [`Box::from_raw_in`], rather than +//! doing this. +//! +//! Note that even the [`Global`] allocator might not use dangling pointers for +//! zero-sized allocations, even though *most* implementations do this. //! //! So long as `T: Sized`, a `Box` is guaranteed to be represented //! as a single pointer and is also ABI-compatible with C pointers @@ -172,6 +178,7 @@ //! and it's best to avoid relying on this edition-dependent behavior if you wish to preserve //! compatibility with future versions of the compiler. //! +//! [*currently allocated*]: Allocator#currently-allocated-memory //! [ucg#198]: https://github.com/rust-lang/unsafe-code-guidelines/issues/198 //! [ucg#326]: https://github.com/rust-lang/unsafe-code-guidelines/issues/326 //! [dereferencing]: core::ops::Deref @@ -275,12 +282,15 @@ impl Box { /// Allocates memory on the heap and then places `x` into it. /// /// This doesn't actually allocate if `T` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// /// ``` /// let five = Box::new(5); /// ``` + /// + /// [memory layout]: self#memory-layout #[cfg(not(no_global_oom_handling))] #[inline(always)] #[stable(feature = "rust1", since = "1.0.0")] @@ -367,6 +377,7 @@ impl Box { /// returning an error if the allocation fails /// /// This doesn't actually allocate if `T` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -376,6 +387,8 @@ impl Box { /// let five = Box::try_new(5)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` + /// + /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new(x: T) -> Result { @@ -434,6 +447,7 @@ impl Box { /// Allocates memory in the given allocator then places `x` into it. /// /// This doesn't actually allocate if `T` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -442,6 +456,8 @@ impl Box { /// /// let five = Box::new_in(5, System); /// ``` + /// + /// [memory layout]: self#memory-layout #[cfg(not(no_global_oom_handling))] #[stable(feature = "allocator_api", since = "1.100.0")] #[must_use] @@ -457,6 +473,7 @@ impl Box { /// returning an error if the allocation fails /// /// This doesn't actually allocate if `T` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -468,6 +485,8 @@ impl Box { /// let five = Box::try_new_in(5, System)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` + /// + /// [memory layout]: self#memory-layout #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] pub fn try_new_in(x: T, alloc: A) -> Result { @@ -774,6 +793,7 @@ impl Box { /// Allocates memory on the heap then clones `src` into it. /// /// This doesn't actually allocate if `src` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -782,6 +802,8 @@ impl Box { /// /// let hello: Box = Box::clone_from_ref("hello"); /// ``` + /// + /// [memory layout]: self#memory-layout #[cfg(not(no_global_oom_handling))] #[unstable(feature = "clone_from_ref", issue = "149075")] #[must_use] @@ -793,6 +815,7 @@ impl Box { /// Allocates memory on the heap then clones `src` into it, returning an error if allocation fails. /// /// This doesn't actually allocate if `src` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -802,6 +825,8 @@ impl Box { /// let hello: Box = Box::try_clone_from_ref("hello")?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` + /// + /// [memory layout]: self#memory-layout #[unstable(feature = "clone_from_ref", issue = "149075")] //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] @@ -814,6 +839,7 @@ impl Box { /// Allocates memory in the given allocator then clones `src` into it. /// /// This doesn't actually allocate if `src` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -824,6 +850,8 @@ impl Box { /// /// let hello: Box = Box::clone_from_ref_in("hello", System); /// ``` + /// + /// [memory layout]: self#memory-layout #[cfg(not(no_global_oom_handling))] #[unstable(feature = "clone_from_ref", issue = "149075")] //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] @@ -840,6 +868,7 @@ impl Box { /// Allocates memory in the given allocator then clones `src` into it, returning an error if allocation fails. /// /// This doesn't actually allocate if `src` is zero-sized. + /// See the [memory layout] section for more details. /// /// # Examples /// @@ -851,6 +880,8 @@ impl Box { /// let hello: Box = Box::try_clone_from_ref_in("hello", System)?; /// # Ok::<(), std::alloc::AllocError>(()) /// ``` + /// + /// [memory layout]: self#memory-layout #[unstable(feature = "clone_from_ref", issue = "149075")] //#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[inline] @@ -1300,9 +1331,16 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// - /// The raw pointer must point to a block of memory allocated by the global allocator. + /// The exact safety requirements are described in the [memory layout] section, together + /// with recommendations about how to handle the special case of zero-sized allocations + /// correctly. + /// + /// In particular, if the size of the pointee, as reported by [`size_of_val`], is + /// nonzero, then the raw pointer must point to a block of memory allocated by + /// [`Global`]. + /// If the size of the pointee is zero, then the raw pointer can be any + /// sufficiently aligned non-null pointer, e.g. [`ptr::dangling`]. /// - /// The safety conditions are described in the [memory layout] section. /// Note that the [considerations for unsafe code] apply to all `Box` values. /// /// # Examples @@ -1352,9 +1390,16 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same `NonNull` pointer. /// - /// The non-null pointer must point to a block of memory allocated by the global allocator. + /// The exact safety requirements are described in the [memory layout] section, together + /// with recommendations about how to handle the special case of zero-sized allocations + /// correctly. + /// + /// In particular, if the size of the pointee, as reported by [`size_of_val`], is + /// nonzero, then the raw pointer must point to a block of memory allocated by + /// [`Global`]. + /// If the size of the pointee is zero, then the raw pointer can be any + /// sufficiently aligned pointer, e.g. [`NonNull::dangling`]. /// - /// The safety conditions are described in the [memory layout] section. /// Note that the [considerations for unsafe code] apply to all `Box` values. /// /// # Examples @@ -1403,6 +1448,11 @@ impl Box { /// [`Box::from_raw`] function, allowing the `Box` destructor to perform /// the cleanup. /// + /// While manually deallocating the pointer through [`deallocate`] + /// is possible, you must only do this if the pointee's size, as reported by + /// [`size_of_val`], is non-zero (the `Box` may be a dangling pointer + /// otherwise). See the [memory layout] section for more details. + /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This /// is so that there is no conflict with a method on the inner type. @@ -1438,6 +1488,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + /// [`deallocate`]: Allocator::deallocate #[must_use = "losing the pointer will leak memory"] #[stable(feature = "box_raw", since = "1.4.0")] #[inline] @@ -1465,6 +1516,11 @@ impl Box { /// [`Box::from_non_null`] function, allowing the `Box` destructor to /// perform the cleanup. /// + /// While manually deallocating the pointer through [`deallocate`] + /// is possible, you must only do this if the pointee's size, as reported by + /// [`size_of_val`], is non-zero (the `Box` may be a dangling pointer + /// otherwise). See the [memory layout] section for more details. + /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_non_null(b)` instead of `b.into_non_null()`. /// This is so that there is no conflict with a method on the inner type. @@ -1499,6 +1555,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + /// [`deallocate`]: Allocator::deallocate #[must_use = "losing the pointer will leak memory"] #[stable(feature = "box_vec_non_null", since = "1.99.0")] #[inline] @@ -1517,9 +1574,8 @@ impl Box { /// /// After calling this function, the raw pointer is owned by the /// resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. For this - /// to be safe, the memory must have been allocated in accordance - /// with the [memory layout] used by `Box` . + /// the destructor of `T` and free the allocated memory, except + /// in the cases described in the [memory layout] section. /// /// # Safety /// @@ -1527,9 +1583,16 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// - /// The raw pointer must point to a block of memory allocated by `alloc`. + /// The exact safety requirements are described in the [memory layout] section, together + /// with recommendations about how to handle the special case of zero-sized allocations + /// correctly. + /// + /// In particular, if the size of the pointee, as reported by [`size_of_val`], is + /// nonzero, then the raw pointer must point to a block of memory allocated by + /// `alloc`. + /// If the size of the pointee is zero, then the raw pointer can be any + /// sufficiently aligned non-null pointer, e.g. [`ptr::dangling`]. /// - /// The safety conditions are described in the [memory layout] section. /// Note that the [considerations for unsafe code] apply to all `Box` values. /// /// # Examples @@ -1573,9 +1636,8 @@ impl Box { /// /// After calling this function, the `NonNull` pointer is owned by /// the resulting `Box`. Specifically, the `Box` destructor will call - /// the destructor of `T` and free the allocated memory. For this - /// to be safe, the memory must have been allocated in accordance - /// with the [memory layout] used by `Box` . + /// the destructor of `T` and free the allocated memory, except + /// in the cases described in the [memory layout] section. /// /// # Safety /// @@ -1583,9 +1645,16 @@ impl Box { /// memory problems. For example, a double-free may occur if the /// function is called twice on the same raw pointer. /// - /// The non-null pointer must point to a block of memory allocated by `alloc`. + /// The exact safety requirements are described in the [memory layout] section, together + /// with recommendations about how to handle the special case of zero-sized allocations + /// correctly. + /// + /// In particular, if the size of the pointee, as reported by [`size_of_val`], is + /// nonzero, then the raw pointer must point to a block of memory allocated by + /// `alloc`. + /// If the size of the pointee is zero, then the raw pointer can be any + /// sufficiently aligned pointer, e.g. [`NonNull::dangling`]. /// - /// The safety conditions are described in the [memory layout] section. /// Note that the [considerations for unsafe code] apply to all `Box` values. /// /// # Examples @@ -1634,6 +1703,11 @@ impl Box { /// [`Box::from_raw_in`] function, allowing the `Box` destructor to perform /// the cleanup. /// + /// While manually deallocating the pointer through [`deallocate`] + /// is possible, you must only do this if the pointee's size, as reported by + /// [`size_of_val`], is non-zero (the `Box` may be a dangling pointer + /// otherwise). See the [memory layout] section for more details. + /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_raw_with_allocator(b)` instead of `b.into_raw_with_allocator()`. This /// is so that there is no conflict with a method on the inner type. @@ -1664,6 +1738,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + /// [`deallocate`]: Allocator::deallocate #[must_use = "losing the pointer will leak memory"] #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] @@ -1693,6 +1768,11 @@ impl Box { /// [`Box::from_non_null_in`] function, allowing the `Box` destructor to /// perform the cleanup. /// + /// While manually deallocating the pointer through [`deallocate`] + /// is possible, you must only do this if the pointee's size, as reported by + /// [`size_of_val`], is non-zero (the `Box` may be a dangling pointer + /// otherwise). See the [memory layout] section for more details. + /// /// Note: this is an associated function, which means that you have /// to call it as `Box::into_non_null_with_allocator(b)` instead of /// `b.into_non_null_with_allocator()`. This is so that there is no @@ -1722,6 +1802,7 @@ impl Box { /// ``` /// /// [memory layout]: self#memory-layout + /// [`deallocate`]: Allocator::deallocate #[must_use = "losing the pointer will leak memory"] #[stable(feature = "allocator_api", since = "1.100.0")] #[inline] diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b363b6862f7e5..d8cae389aea85 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -940,6 +940,10 @@ impl String { /// into a `String` with the [`from_raw_parts`] function, allowing /// the destructor to perform the cleanup. /// + /// If `capacity == 0`, then `pointer` may be dangling. Otherwise, + /// it will always be valid for reads and writes over `capacity` + /// bytes, and point to the start of the string. + /// /// [`from_raw_parts`]: String::from_raw_parts /// /// # Examples diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 501896bf4f043..ddc65e17bae0b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -51,25 +51,50 @@ //! //! # Memory layout //! -//! When the type is non-zero-sized and the capacity is nonzero, [`Vec`] uses the [`Global`] -//! allocator for its allocation. It is valid to convert both ways between such a [`Vec`] and a raw -//! pointer allocated with the [`Global`] allocator, provided that the [`Layout`] used with the -//! allocator is correct for a sequence of `capacity` elements of the type, and the first `len` -//! values pointed to by the raw pointer are valid. More precisely, a `ptr: *mut T` that has been -//! allocated with the [`Global`] allocator with [`Layout::array::(capacity)`][Layout::array] may -//! be converted into a vec using -//! [`Vec::::from_raw_parts(ptr, len, capacity)`](Vec::from_raw_parts). Conversely, the memory -//! backing a `value: *mut T` obtained from [`Vec::::as_mut_ptr`] may be deallocated using the -//! [`Global`] allocator with the same layout. +//! A [`Vec`] conceptually consists of a raw pointer `ptr` to the start of the allocation, a +//! length `len`, a capacity `cap`, and an allocator `alloc`. +//! While the exact fields and their order are not specified, a [`Vec`] can be converted to and +//! from these parts using [`Vec::into_raw_parts_with_allocator`], [`Vec::from_raw_parts_in`], +//! [`Vec::into_raw_parts`], and [`Vec::from_raw_parts`], as well as their [`NonNull`]-based +//! versions. //! -//! For zero-sized types (ZSTs), or when the capacity is zero, the `Vec` pointer must be non-null -//! and sufficiently aligned. The recommended way to build a `Vec` of ZSTs if [`vec!`] cannot be -//! used is to use [`ptr::NonNull::dangling`]. +//! The parts of a [`Vec`] have the following invariants: //! +//! * If [`size_of::()`](size_of) and `cap` are non-zero, then: +//! - `ptr` must point to the start of a memory block [*currently allocated*] via `alloc`. +//! - [`Layout::array::(cap)`] must [*fit*] the memory block of `ptr`. In particular, +//! * `T` must have the same alignment as the [`Layout`] `ptr` was allocated with, and +//! * `size_of::() * cap` must be at least the size of the [`Layout`] `ptr` was +//! allocated with, and at most the size of the allocation returned the allocator. +//! - `size_of::() * cap` must be at most [`isize::MAX`]. +//! See the safety documentation of [`pointer::offset`]. +//! * If [`size_of::()`](size_of) or `cap` is zero, then `ptr` must be any sufficiently aligned non-null pointer. +//! +//! NOTE: `ptr` will not be passed to the allocator for deallocation by the destructor of [`Vec`] +//! in this case. Thus, it is unwise to use a pointer acquired from the allocator for this, as +//! overallocated memory may end up being leaked. Use [`ptr::dangling`] instead. +//! * The following must always be satisfied: +//! - `len` needs to be less than or equal to `cap`. +//! - At `ptr`, there are at least `len` valid values of type `T`, laid out contiguously +//! (like an array). These values are considered owned by the [`Vec`]. +//! +//! It is sound to create a [`Vec`] from parts that satisfy these invariants. +//! +//! Conversely, the memory backing `ptr` obtained from [`Vec::as_mut_ptr`] or +//! [`Vec::into_raw_parts_with_allocator`]-like methods may be deallocated +//! using the allocator, with layout [`Layout::array::(cap)`], provided +//! that [`size_of::()`](size_of) or `cap` is non-zero. +//! To automatically handle the case where the allocation is zero-sized, +//! it is recommended to use [`Vec::from_raw_parts_in`], instead of manually +//! deallocating. +//! +//! [*fit*]: crate::alloc::Allocator#memory-fitting +//! [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory +//! [`allocate`]: crate::alloc::Allocator::allocate //! [`push`]: Vec::push //! [`ptr::NonNull::dangling`]: NonNull::dangling //! [`Layout`]: crate::alloc::Layout -//! [Layout::array]: crate::alloc::Layout::array +//! [`Layout::array::(cap)`]: crate::alloc::Layout::array #![stable(feature = "rust1", since = "1.0.0")] @@ -303,35 +328,13 @@ mod sve_retain; /// /// # Guarantees /// +/// The following section is to be read as an addendum of the +/// [memory layout](self#memory-layout) section. +/// /// Due to its incredibly fundamental nature, `Vec` makes a lot of guarantees /// about its design. This ensures that it's as low-overhead as possible in /// the general case, and can be correctly manipulated in primitive ways -/// by unsafe code. Note that these guarantees refer to an unqualified `Vec`. -/// If additional type parameters are added (e.g., to support custom allocators), -/// overriding their defaults may change the behavior. -/// -/// Most fundamentally, `Vec` is and always will be a (pointer, capacity, length) -/// triplet. No more, no less. The order of these fields is completely -/// unspecified, and you should use the appropriate methods to modify these. -/// The pointer will never be null, so this type is null-pointer-optimized. -/// -/// However, the pointer might not actually point to allocated memory. In particular, -/// if you construct a `Vec` with capacity 0 via [`Vec::new`], [`vec![]`][`vec!`], -/// [`Vec::with_capacity(0)`][`Vec::with_capacity`], or by calling [`shrink_to_fit`] -/// on an empty Vec, it will not allocate memory. Similarly, if you store zero-sized -/// types inside a `Vec`, it will not allocate space for them. *Note that in this case -/// the `Vec` might not report a [`capacity`] of 0*. `Vec` will allocate if and only -/// if [size_of::\]\() * [capacity]\() > 0. In general, `Vec`'s allocation -/// details are very subtle --- if you intend to allocate memory using a `Vec` -/// and use it for something else (either to pass to unsafe code, or to build your -/// own memory-backed collection), be sure to deallocate this memory by using -/// `from_raw_parts` to recover the `Vec` and then dropping it. -/// -/// If a `Vec` *has* allocated memory, then the memory it points to is on the heap -/// (as defined by the allocator Rust is configured to use by default), and its -/// pointer points to [`len`] initialized, contiguous elements in order (what -/// you would see if you coerced it to a slice), followed by [capacity] - [len] -/// logically uninitialized, contiguous elements. +/// by unsafe code. /// /// A vector containing the elements `'a'` and `'b'` with capacity 4 can be /// visualized as below. The top part is the `Vec` struct, it contains a @@ -472,7 +475,7 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector [will not allocate]. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -482,11 +485,12 @@ impl Vec { /// If it is important to know the exact allocated capacity of a `Vec`, /// always use the [`capacity`] method after construction. /// - /// For `Vec` where `T` is a zero-sized type, there will be no allocation - /// and the capacity will always be `usize::MAX`. + /// For `Vec` where `T` is a zero-sized type, the vector + /// [will not allocate], and the capacity will always be `usize::MAX`. /// /// [Capacity and reallocation]: #capacity-and-reallocation /// [`capacity`]: Vec::capacity + /// [will not allocate]: self#memory-layout /// /// # Panics /// @@ -532,12 +536,14 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector [will not allocate]. /// /// # Errors /// /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, /// or if the allocator reports allocation failure. + /// + /// [will not allocate]: self#memory-layout #[inline] #[unstable(feature = "try_with_capacity", issue = "91913")] pub fn try_with_capacity(capacity: usize) -> Result { @@ -548,34 +554,10 @@ impl Vec { /// /// # Safety /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * If `T` is not a zero-sized type and the capacity is nonzero, `ptr` must have - /// been allocated using the global allocator, such as via the [`alloc::alloc`] - /// function. If `T` is a zero-sized type or the capacity is zero, `ptr` need - /// only be non-null and aligned. - /// * `T` needs to have the same alignment as what `ptr` was allocated with, - /// if the pointer is required to be allocated. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (i.e. the allocated size in bytes), if - /// nonzero, needs to be the same size as the pointer was allocated with. - /// (Because similar to alignment, [`dealloc`] must be called with the same - /// layout `size`.) - /// * `length` needs to be less than or equal to `capacity`. - /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to be the capacity that the pointer was allocated with, - /// if the pointer is required to be allocated. - /// * The allocated size in bytes must be no larger than `isize::MAX`. - /// See the safety documentation of [`pointer::offset`]. - /// - /// These requirements are always upheld by any `ptr` that has been allocated - /// via `Vec`. Other allocation sources are allowed if the invariants are - /// upheld. - /// - /// Violating these may cause problems like corrupting the allocator's + /// The parts must satisfy the invariants described in the [memory layout] section, + /// with allocator [`Global`]. + /// + /// Violating them may cause problems like corrupting the allocator's /// internal data structures. For example it is normally **not** safe /// to build a `Vec` from a pointer to a C `char` array with length /// `size_t`, doing so is only safe if the array was initially allocated by @@ -594,8 +576,7 @@ impl Vec { /// function. /// /// [`String`]: crate::string::String - /// [`alloc::alloc`]: crate::alloc::alloc - /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [memory layout]: self#memory-layout /// /// # Examples /// @@ -655,29 +636,10 @@ impl Vec { /// /// # Safety /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` must have been allocated using the global allocator, such as via - /// the [`alloc::alloc`] function. - /// * `T` needs to have the same alignment as what `ptr` was allocated with. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (i.e. the allocated size in bytes) needs - /// to be the same size as the pointer was allocated with. (Because similar to - /// alignment, [`dealloc`] must be called with the same layout `size`.) - /// * `length` needs to be less than or equal to `capacity`. - /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to be the capacity that the pointer was allocated with. - /// * The allocated size in bytes must be no larger than `isize::MAX`. - /// See the safety documentation of [`pointer::offset`]. - /// - /// These requirements are always upheld by any `ptr` that has been allocated - /// via `Vec`. Other allocation sources are allowed if the invariants are - /// upheld. - /// - /// Violating these may cause problems like corrupting the allocator's + /// The parts must satisfy the invariants described in the [memory layout] section, + /// with allocator [`Global`]. + /// + /// Violating them may cause problems like corrupting the allocator's /// internal data structures. For example it is normally **not** safe /// to build a `Vec` from a pointer to a C `char` array with length /// `size_t`, doing so is only safe if the array was initially allocated by @@ -696,8 +658,7 @@ impl Vec { /// function. /// /// [`String`]: crate::string::String - /// [`alloc::alloc`]: crate::alloc::alloc - /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc + /// [memory layout]: self#memory-layout /// /// # Examples /// @@ -920,7 +881,7 @@ const impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector [will not allocate]. /// /// It is important to note that although the returned vector has the /// minimum *capacity* specified, the vector will have a zero *length*. For @@ -930,11 +891,12 @@ const impl Vec { /// If it is important to know the exact allocated capacity of a `Vec`, /// always use the [`capacity`] method after construction. /// - /// For `Vec` where `T` is a zero-sized type, there will be no allocation - /// and the capacity will always be `usize::MAX`. + /// For `Vec` where `T` is a zero-sized type, the vector + /// [will not allocate], and the capacity will always be `usize::MAX`. /// /// [Capacity and reallocation]: #capacity-and-reallocation /// [`capacity`]: Vec::capacity + /// [will not allocate]: self#memory-layout /// /// # Panics /// @@ -1072,12 +1034,14 @@ impl Vec { /// /// The vector will be able to hold at least `capacity` elements without /// reallocating. This method is allowed to allocate for more elements than - /// `capacity`. If `capacity` is zero, the vector will not allocate. + /// `capacity`. If `capacity` is zero, the vector [will not allocate]. /// /// # Errors /// /// Returns an error if the capacity exceeds `isize::MAX` _bytes_, /// or if the allocator reports allocation failure. + /// + /// [will not allocate]: self#memory-layout #[inline] #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] // #[unstable(feature = "try_with_capacity", issue = "91913")] @@ -1090,28 +1054,9 @@ impl Vec { /// /// # Safety /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. - /// * `T` needs to have the same alignment as what `ptr` was allocated with. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (i.e. the allocated size in bytes) needs - /// to be the same size as the pointer was allocated with. (Because similar to - /// alignment, [`dealloc`] must be called with the same layout `size`.) - /// * `length` needs to be less than or equal to `capacity`. - /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. - /// * The allocated size in bytes must be no larger than `isize::MAX`. - /// See the safety documentation of [`pointer::offset`]. - /// - /// These requirements are always upheld by any `ptr` that has been allocated - /// via `Vec`. Other allocation sources are allowed if the invariants are - /// upheld. - /// - /// Violating these may cause problems like corrupting the allocator's + /// The parts must satisfy the invariants described in the [memory layout] section. + /// + /// Violating them may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. /// It's also not safe to build one from a `Vec` and its length, because @@ -1126,9 +1071,8 @@ impl Vec { /// function. /// /// [`String`]: crate::string::String - /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc - /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory - /// [*fit*]: crate::alloc::Allocator#memory-fitting + /// [`allocate`]: crate::alloc::Allocator::allocate + /// [memory layout]: self#memory-layout /// /// # Examples /// @@ -1204,28 +1148,9 @@ impl Vec { /// /// # Safety /// - /// This is highly unsafe, due to the number of invariants that aren't - /// checked: - /// - /// * `ptr` must be [*currently allocated*] via the given allocator `alloc`. - /// * `T` needs to have the same alignment as what `ptr` was allocated with. - /// (`T` having a less strict alignment is not sufficient, the alignment really - /// needs to be equal to satisfy the [`dealloc`] requirement that memory must be - /// allocated and deallocated with the same layout.) - /// * The size of `T` times the `capacity` (i.e. the allocated size in bytes) needs - /// to be the same size as the pointer was allocated with. (Because similar to - /// alignment, [`dealloc`] must be called with the same layout `size`.) - /// * `length` needs to be less than or equal to `capacity`. - /// * The first `length` values must be properly initialized values of type `T`. - /// * `capacity` needs to [*fit*] the layout size that the pointer was allocated with. - /// * The allocated size in bytes must be no larger than `isize::MAX`. - /// See the safety documentation of [`pointer::offset`]. - /// - /// These requirements are always upheld by any `ptr` that has been allocated - /// via `Vec`. Other allocation sources are allowed if the invariants are - /// upheld. - /// - /// Violating these may cause problems like corrupting the allocator's + /// The parts must satisfy the invariants described in the [memory layout] section. + /// + /// Violating them may cause problems like corrupting the allocator's /// internal data structures. For example it is **not** safe /// to build a `Vec` from a pointer to a C `char` array with length `size_t`. /// It's also not safe to build one from a `Vec` and its length, because @@ -1241,8 +1166,7 @@ impl Vec { /// /// [`String`]: crate::string::String /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc - /// [*currently allocated*]: crate::alloc::Allocator#currently-allocated-memory - /// [*fit*]: crate::alloc::Allocator#memory-fitting + /// [memory layout]: self#memory-layout /// /// # Examples /// @@ -1902,7 +1826,7 @@ impl Vec { } /// Returns a raw pointer to the vector's buffer, or a dangling raw pointer - /// valid for zero sized reads if the vector didn't allocate. + /// valid for zero sized reads if the vector [didn't allocate]. /// /// The caller must ensure that the vector outlives the pointer this /// function returns, or else it will end up dangling. @@ -1954,6 +1878,7 @@ impl Vec { /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null + /// [didn't allocate]: self#memory-layout #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] @@ -1966,7 +1891,7 @@ impl Vec { } /// Returns a raw mutable pointer to the vector's buffer, or a dangling - /// raw pointer valid for zero sized reads if the vector didn't allocate. + /// raw pointer valid for zero sized reads if the vector [didn't allocate]. /// /// The caller must ensure that the vector outlives the pointer this /// function returns, or else it will end up dangling. @@ -2038,6 +1963,7 @@ impl Vec { /// [`as_non_null`]: Vec::as_non_null /// [`dealloc`]: crate::alloc::GlobalAlloc::dealloc /// [`ManuallyDrop`]: core::mem::ManuallyDrop + /// [didn't allocate]: self#memory-layout #[stable(feature = "vec_as_ptr", since = "1.37.0")] #[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")] #[rustc_never_returns_null_ptr] @@ -2050,7 +1976,7 @@ impl Vec { } /// Returns a `NonNull` pointer to the vector's buffer, or a dangling - /// `NonNull` pointer valid for zero sized reads if the vector didn't allocate. + /// `NonNull` pointer valid for zero sized reads if the vector [didn't allocate]. /// /// The caller must ensure that the vector outlives the pointer this /// function returns, or else it will end up dangling. @@ -2105,6 +2031,7 @@ impl Vec { /// [`as_mut_ptr`]: Vec::as_mut_ptr /// [`as_ptr`]: Vec::as_ptr /// [`as_non_null`]: Vec::as_non_null + /// [didn't allocate]: self#memory-layout #[unstable(feature = "vec_as_non_null", issue = "157843")] #[rustc_const_unstable(feature = "vec_as_non_null", issue = "157843")] #[rustc_as_ptr] From c473ea65d6d35e805efd4f70adef328b4af972ac Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 16 Oct 2026 17:44:34 -0700 Subject: [PATCH 3/6] Add a fallback for `-static-pie` missing CRT objects We already have a fallback when the linker doesn't support `-static-pie` to use plain `-static` instead. However, it is also possible that the linker understands that option, but the C library doesn't have the necessary CRT objects. For example, `gcc` has known this option for a long time, but `glibc` doesn't support it for `powerpc` targets at all. We can detect this case in the link output for `-static` fallback too. (cherry picked from commit 4332bd9e92063767333e53d32af2d035109adf04) --- compiler/rustc_codegen_ssa/src/back/link.rs | 22 ++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 221998abf6128..a9c9df94af406 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1349,17 +1349,25 @@ fn link_natively( continue; } - // Detect '-static-pie' used with an older version of gcc or clang not supporting it. - // Fallback from '-static-pie' to '-static' in that case. + // Detect '-static-pie' used with an older version of gcc or clang not supporting it, + // or with glibc that's missing crt objects, e.g. for arches that don't support it. + // Fallback from '-static-pie' to '-static' in either case. + let mut static_pie_message = None; if matches!(flavor, LinkerFlavor::Gnu(Cc::Yes, _)) - && unknown_arg_regex.is_match(&out) - && (out.contains("-static-pie") || out.contains("--no-dynamic-linker")) && cmd.get_args().iter().any(|e| e == "-static-pie") { + if unknown_arg_regex.is_match(&out) + && (out.contains("-static-pie") || out.contains("--no-dynamic-linker")) + { + static_pie_message = + Some("Linker does not support -static-pie command line option."); + } else if Regex::new(r"cannot (find|open) g?rcrt1\.o:").unwrap().is_match(&out) { + static_pie_message = Some("C library is missing static-PIE startup objects."); + } + } + if let Some(message) = static_pie_message { info!("linker output: {:?}", out); - warn!( - "Linker does not support -static-pie command line option. Retrying with -static instead." - ); + warn!("{message} Retrying with -static instead."); // Mirror `add_(pre,post)_link_objects` to replace CRT objects. let self_contained_crt_objects = self_contained_components.is_crt_objects_enabled(); let opts = &sess.target; From 64b4e11fcfe6c048f249dec0c3afd10c5bcf7485 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 22 Oct 2026 14:21:57 +0200 Subject: [PATCH 4/6] Update to LLVM 23.1.4 (cherry picked from commit 8ee14d7f3c15dee79a3f839bcb93abc61949bd44) --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 915c669d232e4..f738f3b0ed65c 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 915c669d232e4cad467ba95ff041041e2e7c3f69 +Subproject commit f738f3b0ed65c01edcb44a504a77edc12a82c319 From 75d8ddba734c909ae0c27de87dd2b78e5b1dfe8a Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Thu, 15 Oct 2026 13:53:59 -0700 Subject: [PATCH 5/6] rebind the trait pred when emitting imperfect derive help (cherry picked from commit c4da87ca44ebf499a122b4c2ee941cbdd03158c4) --- .../src/error_reporting/traits/suggestions.rs | 2 +- .../derives/imperfect-derive-higher-ranked.rs | 11 +++++++ .../imperfect-derive-higher-ranked.stderr | 29 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 tests/ui/derives/imperfect-derive-higher-ranked.rs create mode 100644 tests/ui/derives/imperfect-derive-higher-ranked.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ff9db46445135..68690454f2bae 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6764,7 +6764,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { tcx, ObligationCause::dummy(), param_env, - ty::TraitRef::new(tcx, trait_def_id, trait_args), + parent_trait_pred.rebind(ty::TraitRef::new(tcx, trait_def_id, trait_args)), ); self.predicate_may_hold(&obligation) }) diff --git a/tests/ui/derives/imperfect-derive-higher-ranked.rs b/tests/ui/derives/imperfect-derive-higher-ranked.rs new file mode 100644 index 0000000000000..e876af6661822 --- /dev/null +++ b/tests/ui/derives/imperfect-derive-higher-ranked.rs @@ -0,0 +1,11 @@ +// regression test for #164376 + +#[derive(Clone)] +struct S<'a, T>(&'a T); + +fn require() where for<'a> S<'a, T>: Clone {} + +fn main() { + require::<&'static mut u8>(); + //~^ ERROR the trait bound `&'static mut u8: Clone` is not satisfied +} diff --git a/tests/ui/derives/imperfect-derive-higher-ranked.stderr b/tests/ui/derives/imperfect-derive-higher-ranked.stderr new file mode 100644 index 0000000000000..fa619de722b45 --- /dev/null +++ b/tests/ui/derives/imperfect-derive-higher-ranked.stderr @@ -0,0 +1,29 @@ +error[E0277]: the trait bound `&'static mut u8: Clone` is not satisfied + --> $DIR/imperfect-derive-higher-ranked.rs:9:15 + | +LL | require::<&'static mut u8>(); + | ^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `&'static mut u8` + | +help: the trait `Clone` is implemented for `u8` + --> $SRC_DIR/core/src/clone.rs:LL:COL + ::: $SRC_DIR/core/src/clone.rs:LL:COL + | + = note: in this macro invocation +note: required for `S<'a, &'static mut u8>` to implement `for<'a> Clone` + --> $DIR/imperfect-derive-higher-ranked.rs:4:8 + | +LL | #[derive(Clone)] + | ----- in this derive macro expansion +LL | struct S<'a, T>(&'a T); + | ^ - type parameter would need to implement `for<'a> Clone` + = help: consider manually implementing `for<'a> Clone` to avoid undesired bounds caused by "imperfect derives" + = note: to learn more, visit +note: required by a bound in `require` + --> $DIR/imperfect-derive-higher-ranked.rs:6:41 + | +LL | fn require() where for<'a> S<'a, T>: Clone {} + | ^^^^^ required by this bound in `require` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. From 769fa5d041d913230bc15a80fb778769f96298e0 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 2 Nov 2026 09:15:44 +0100 Subject: [PATCH 6/6] Disable cargo tests on `aarch64-apple` Done because of issues with github ci, see https://github.com/rust-lang/rust/issues/165241 --- src/ci/github-actions/jobs.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 0fdf50d20a255..49778314d2e8c 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -621,10 +621,10 @@ auto: --skip tests --skip library --skip tidyselftest - && ./x.py --stage 2 test - --host=aarch64-apple-darwin - --target=aarch64-apple-darwin - src/tools/cargo +# && ./x.py --stage 2 test +# --host=aarch64-apple-darwin +# --target=aarch64-apple-darwin +# src/tools/cargo RUST_CONFIGURE_ARGS: >- --enable-sanitizers --enable-profiler @@ -674,10 +674,10 @@ auto: --skip tests --skip library --skip tidyselftest - && ./x.py --stage 2 test - --host=aarch64-apple-darwin - --target=aarch64-apple-darwin - src/tools/cargo +# && ./x.py --stage 2 test +# --host=aarch64-apple-darwin +# --target=aarch64-apple-darwin +# src/tools/cargo RUST_CONFIGURE_ARGS: >- --enable-sanitizers --enable-profiler