about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacob Pratt <jacob@jhpratt.dev>2025-03-08 01:27:20 -0500
committerGitHub <noreply@github.com>2025-03-08 01:27:20 -0500
commit720eacf08693418940e857379e1593b6891a09c3 (patch)
tree39100b87651a41ed803158284aa72f9f7d2a0c68
parent20f0108ada90e37c2350ad68fdc6afe56f51539d (diff)
parent22d0440993d6eab6e9faf35f729e2d52ba6d72a6 (diff)
downloadrust-720eacf08693418940e857379e1593b6891a09c3.tar.gz
rust-720eacf08693418940e857379e1593b6891a09c3.zip
Rollup merge of #136642 - bjorn3:separate_alloctest_crate, r=cuviper
Put the alloc unit tests in a separate alloctests package

Same rationale as https://github.com/rust-lang/rust/pull/135937. This PR has some extra complexity though as a decent amount of tests are testing internal implementation details rather than the public api. As such I opted to include the modules containing the types under test using `#[path]` into the alloctests package. This means that those modules still need `#[cfg(test)]`, but the rest of liballoc no longer need it.
-rw-r--r--compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch6
-rw-r--r--library/Cargo.lock10
-rw-r--r--library/Cargo.toml1
-rw-r--r--library/alloc/Cargo.toml26
-rw-r--r--library/alloc/src/alloc.rs18
-rw-r--r--library/alloc/src/borrow.rs6
-rw-r--r--library/alloc/src/bstr.rs20
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs5
-rw-r--r--library/alloc/src/collections/mod.rs24
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs1
-rw-r--r--library/alloc/src/collections/vec_deque/spec_extend.rs2
-rw-r--r--library/alloc/src/collections/vec_deque/spec_from_iter.rs1
-rw-r--r--library/alloc/src/ffi/c_str.rs16
-rw-r--r--library/alloc/src/lib.rs39
-rw-r--r--library/alloc/src/macros.rs23
-rw-r--r--library/alloc/src/raw_vec/mod.rs (renamed from library/alloc/src/raw_vec.rs)4
-rw-r--r--library/alloc/src/rc.rs10
-rw-r--r--library/alloc/src/slice.rs182
-rw-r--r--library/alloc/src/str.rs3
-rw-r--r--library/alloc/src/string.rs30
-rw-r--r--library/alloc/src/sync.rs4
-rw-r--r--library/alloc/src/vec/into_iter.rs5
-rw-r--r--library/alloc/src/vec/mod.rs47
-rw-r--r--library/alloc/tests/rc.rs259
-rw-r--r--library/alloctests/Cargo.toml47
-rw-r--r--library/alloctests/benches/binary_heap.rs (renamed from library/alloc/benches/binary_heap.rs)0
-rw-r--r--library/alloctests/benches/btree/map.rs (renamed from library/alloc/benches/btree/map.rs)0
-rw-r--r--library/alloctests/benches/btree/mod.rs (renamed from library/alloc/benches/btree/mod.rs)0
-rw-r--r--library/alloctests/benches/btree/set.rs (renamed from library/alloc/benches/btree/set.rs)0
-rw-r--r--library/alloctests/benches/lib.rs (renamed from library/alloc/benches/lib.rs)0
-rw-r--r--library/alloctests/benches/linked_list.rs (renamed from library/alloc/benches/linked_list.rs)0
-rw-r--r--library/alloctests/benches/slice.rs (renamed from library/alloc/benches/slice.rs)0
-rw-r--r--library/alloctests/benches/str.rs (renamed from library/alloc/benches/str.rs)0
-rw-r--r--library/alloctests/benches/string.rs (renamed from library/alloc/benches/string.rs)0
-rw-r--r--library/alloctests/benches/vec.rs (renamed from library/alloc/benches/vec.rs)0
-rw-r--r--library/alloctests/benches/vec_deque.rs (renamed from library/alloc/benches/vec_deque.rs)0
-rw-r--r--library/alloctests/benches/vec_deque_append.rs (renamed from library/alloc/benches/vec_deque_append.rs)0
-rw-r--r--library/alloctests/lib.rs93
-rw-r--r--library/alloctests/testing/crash_test.rs (renamed from library/alloc/src/testing/crash_test.rs)0
-rw-r--r--library/alloctests/testing/mod.rs (renamed from library/alloc/src/testing/mod.rs)0
-rw-r--r--library/alloctests/testing/ord_chaos.rs (renamed from library/alloc/src/testing/ord_chaos.rs)0
-rw-r--r--library/alloctests/testing/rng.rs (renamed from library/alloc/src/testing/rng.rs)0
-rw-r--r--library/alloctests/tests/alloc_test.rs (renamed from library/alloc/tests/alloc.rs)0
-rw-r--r--library/alloctests/tests/arc.rs (renamed from library/alloc/tests/arc.rs)0
-rw-r--r--library/alloctests/tests/autotraits.rs (renamed from library/alloc/tests/autotraits.rs)0
-rw-r--r--library/alloctests/tests/borrow.rs (renamed from library/alloc/tests/borrow.rs)0
-rw-r--r--library/alloctests/tests/boxed.rs (renamed from library/alloc/tests/boxed.rs)0
-rw-r--r--library/alloctests/tests/btree_set_hash.rs (renamed from library/alloc/tests/btree_set_hash.rs)0
-rw-r--r--library/alloctests/tests/c_str.rs (renamed from library/alloc/tests/c_str.rs)0
-rw-r--r--library/alloctests/tests/c_str2.rs (renamed from library/alloc/tests/c_str2.rs)0
-rw-r--r--library/alloctests/tests/collections/binary_heap.rs (renamed from library/alloc/tests/collections/binary_heap.rs)0
-rw-r--r--library/alloctests/tests/collections/mod.rs (renamed from library/alloc/tests/collections/mod.rs)0
-rw-r--r--library/alloctests/tests/const_fns.rs (renamed from library/alloc/tests/const_fns.rs)0
-rw-r--r--library/alloctests/tests/cow_str.rs (renamed from library/alloc/tests/cow_str.rs)0
-rw-r--r--library/alloctests/tests/fmt.rs (renamed from library/alloc/tests/fmt.rs)0
-rw-r--r--library/alloctests/tests/heap.rs (renamed from library/alloc/tests/heap.rs)0
-rw-r--r--library/alloctests/tests/lib.rs (renamed from library/alloc/tests/lib.rs)3
-rw-r--r--library/alloctests/tests/linked_list.rs (renamed from library/alloc/tests/linked_list.rs)0
-rw-r--r--library/alloctests/tests/misc_tests.rs (renamed from library/alloc/tests/misc_tests.rs)0
-rw-r--r--library/alloctests/tests/rc.rs (renamed from library/alloc/src/rc/tests.rs)276
-rw-r--r--library/alloctests/tests/slice.rs (renamed from library/alloc/tests/slice.rs)0
-rw-r--r--library/alloctests/tests/sort/ffi_types.rs (renamed from library/alloc/tests/sort/ffi_types.rs)0
-rw-r--r--library/alloctests/tests/sort/known_good_stable_sort.rs (renamed from library/alloc/tests/sort/known_good_stable_sort.rs)0
-rw-r--r--library/alloctests/tests/sort/mod.rs (renamed from library/alloc/tests/sort/mod.rs)0
-rw-r--r--library/alloctests/tests/sort/patterns.rs (renamed from library/alloc/tests/sort/patterns.rs)0
-rw-r--r--library/alloctests/tests/sort/tests.rs (renamed from library/alloc/tests/sort/tests.rs)0
-rw-r--r--library/alloctests/tests/sort/zipf.rs (renamed from library/alloc/tests/sort/zipf.rs)0
-rw-r--r--library/alloctests/tests/str.rs (renamed from library/alloc/tests/str.rs)0
-rw-r--r--library/alloctests/tests/string.rs (renamed from library/alloc/tests/string.rs)0
-rw-r--r--library/alloctests/tests/sync.rs (renamed from library/alloc/tests/sync.rs)0
-rw-r--r--library/alloctests/tests/task.rs (renamed from library/alloc/tests/task.rs)0
-rw-r--r--library/alloctests/tests/testing/crash_test.rs (renamed from library/alloc/tests/testing/crash_test.rs)0
-rw-r--r--library/alloctests/tests/testing/mod.rs (renamed from library/alloc/tests/testing/mod.rs)0
-rw-r--r--library/alloctests/tests/thin_box.rs (renamed from library/alloc/tests/thin_box.rs)0
-rw-r--r--library/alloctests/tests/vec.rs (renamed from library/alloc/tests/vec.rs)0
-rw-r--r--library/alloctests/tests/vec_deque.rs (renamed from library/alloc/tests/vec_deque.rs)0
-rw-r--r--library/alloctests/tests/vec_deque_alloc_error.rs (renamed from library/alloc/tests/vec_deque_alloc_error.rs)0
-rw-r--r--src/bootstrap/mk/Makefile.in2
-rw-r--r--src/bootstrap/src/core/build_steps/check.rs5
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs12
-rw-r--r--src/tools/tidy/src/style.rs2
81 files changed, 579 insertions, 603 deletions
diff --git a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
index c2027863b00..754025ff49d 100644
--- a/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
+++ b/compiler/rustc_codegen_cranelift/patches/0029-stdlib-Disable-f16-and-f128-in-compiler-builtins.patch
@@ -12,15 +12,15 @@ index 7165c3e48af..968552ad435 100644
 --- a/library/alloc/Cargo.toml
 +++ b/library/alloc/Cargo.toml
 @@ -11,7 +11,7 @@ test = { path = "../test" }
- edition = "2021"
+ bench = false
  
  [dependencies]
  core = { path = "../core", public = true }
 -compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] }
 +compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std', 'no-f16-f128'] }
  
- [dev-dependencies]
- rand = { version = "0.8.5", default-features = false, features = ["alloc"] }
+ [features]
+ compiler-builtins-mem = ['compiler_builtins/mem']
 -- 
 2.34.1
 
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 31656414121..405c69d9568 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -30,8 +30,6 @@ version = "0.0.0"
 dependencies = [
  "compiler_builtins",
  "core",
- "rand",
- "rand_xorshift",
 ]
 
 [[package]]
@@ -41,6 +39,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
 
 [[package]]
+name = "alloctests"
+version = "0.0.0"
+dependencies = [
+ "rand",
+ "rand_xorshift",
+]
+
+[[package]]
 name = "cc"
 version = "1.2.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/library/Cargo.toml b/library/Cargo.toml
index 1205f7c9ed6..4d5955593ff 100644
--- a/library/Cargo.toml
+++ b/library/Cargo.toml
@@ -4,6 +4,7 @@ members = [
   "std",
   "sysroot",
   "coretests",
+  "alloctests",
 ]
 
 exclude = [
diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml
index 4cb83501256..dbdf292433b 100644
--- a/library/alloc/Cargo.toml
+++ b/library/alloc/Cargo.toml
@@ -10,32 +10,14 @@ autotests = false
 autobenches = false
 edition = "2021"
 
+[lib]
+test = false
+bench = false
+
 [dependencies]
 core = { path = "../core", public = true }
 compiler_builtins = { version = "=0.1.151", features = ['rustc-dep-of-std'] }
 
-[dev-dependencies]
-rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
-rand_xorshift = "0.4.0"
-
-[[test]]
-name = "alloctests"
-path = "tests/lib.rs"
-
-[[test]]
-name = "vec_deque_alloc_error"
-path = "tests/vec_deque_alloc_error.rs"
-
-[[bench]]
-name = "allocbenches"
-path = "benches/lib.rs"
-test = true
-
-[[bench]]
-name = "vec_deque_append_bench"
-path = "benches/vec_deque_append.rs"
-harness = false
-
 [features]
 compiler-builtins-mem = ['compiler_builtins/mem']
 compiler-builtins-c = ["compiler_builtins/c"]
diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs
index 3bfdc68dcda..2f752f6eb39 100644
--- a/library/alloc/src/alloc.rs
+++ b/library/alloc/src/alloc.rs
@@ -5,9 +5,7 @@
 #[stable(feature = "alloc_module", since = "1.28.0")]
 #[doc(inline)]
 pub use core::alloc::*;
-#[cfg(not(test))]
 use core::hint;
-#[cfg(not(test))]
 use core::ptr::{self, NonNull};
 
 unsafe extern "Rust" {
@@ -44,14 +42,10 @@ unsafe extern "Rust" {
 /// accessed through the [free functions in `alloc`](self#functions).
 #[unstable(feature = "allocator_api", issue = "32838")]
 #[derive(Copy, Clone, Default, Debug)]
-#[cfg(not(test))]
 // the compiler needs to know when a Box uses the global allocator vs a custom one
 #[lang = "global_alloc_ty"]
 pub struct Global;
 
-#[cfg(test)]
-pub use std::alloc::Global;
-
 /// Allocates memory with the global allocator.
 ///
 /// This function forwards calls to the [`GlobalAlloc::alloc`] method
@@ -180,7 +174,6 @@ pub unsafe fn alloc_zeroed(layout: Layout) -> *mut u8 {
     }
 }
 
-#[cfg(not(test))]
 impl Global {
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
@@ -246,7 +239,6 @@ impl Global {
 }
 
 #[unstable(feature = "allocator_api", issue = "32838")]
-#[cfg(not(test))]
 unsafe impl Allocator for Global {
     #[inline]
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
@@ -346,7 +338,7 @@ unsafe impl Allocator for Global {
 }
 
 /// The allocator for `Box`.
-#[cfg(all(not(no_global_oom_handling), not(test)))]
+#[cfg(not(no_global_oom_handling))]
 #[lang = "exchange_malloc"]
 #[inline]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
@@ -395,7 +387,7 @@ unsafe extern "Rust" {
 /// [no_std]: https://doc.rust-lang.org/reference/names/preludes.html#the-no_std-attribute
 #[stable(feature = "global_alloc", since = "1.28.0")]
 #[rustc_const_unstable(feature = "const_alloc_error", issue = "92523")]
-#[cfg(all(not(no_global_oom_handling), not(test)))]
+#[cfg(not(no_global_oom_handling))]
 #[cold]
 #[optimize(size)]
 pub const fn handle_alloc_error(layout: Layout) -> ! {
@@ -419,11 +411,7 @@ pub const fn handle_alloc_error(layout: Layout) -> ! {
     ct_error(layout)
 }
 
-// For alloc test `std::alloc::handle_alloc_error` can be used directly.
-#[cfg(all(not(no_global_oom_handling), test))]
-pub use std::alloc::handle_alloc_error;
-
-#[cfg(all(not(no_global_oom_handling), not(test)))]
+#[cfg(not(no_global_oom_handling))]
 #[doc(hidden)]
 #[allow(unused_attributes)]
 #[unstable(feature = "alloc_internals", issue = "none")]
diff --git a/library/alloc/src/borrow.rs b/library/alloc/src/borrow.rs
index 17dad3277b9..07f51b7614f 100644
--- a/library/alloc/src/borrow.rs
+++ b/library/alloc/src/borrow.rs
@@ -32,7 +32,7 @@ where
 /// implementing the `Clone` trait. But `Clone` works only for going from `&T`
 /// to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
 /// from any borrow of a given type.
-#[cfg_attr(not(test), rustc_diagnostic_item = "ToOwned")]
+#[rustc_diagnostic_item = "ToOwned"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToOwned {
     /// The resulting type after obtaining ownership.
@@ -54,7 +54,7 @@ pub trait ToOwned {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "cloning is often expensive and is not expected to have side effects"]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "to_owned_method")]
+    #[rustc_diagnostic_item = "to_owned_method"]
     fn to_owned(&self) -> Self::Owned;
 
     /// Uses borrowed data to replace owned data, usually by cloning.
@@ -175,7 +175,7 @@ where
 /// }
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Cow")]
+#[rustc_diagnostic_item = "Cow"]
 pub enum Cow<'a, B: ?Sized + 'a>
 where
     B: ToOwned,
diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs
index 61e61019b50..338c7ac7f88 100644
--- a/library/alloc/src/bstr.rs
+++ b/library/alloc/src/bstr.rs
@@ -12,13 +12,10 @@ use core::ops::{
     Deref, DerefMut, DerefPure, Index, IndexMut, Range, RangeFrom, RangeFull, RangeInclusive,
     RangeTo, RangeToInclusive,
 };
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 use core::str::FromStr;
 use core::{fmt, hash};
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 use crate::borrow::{Cow, ToOwned};
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 use crate::boxed::Box;
 #[cfg(not(no_rc))]
 use crate::rc::Rc;
@@ -181,7 +178,6 @@ impl Default for ByteString {
 
 // Omitted due to inference failures
 //
-// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 // #[unstable(feature = "bstr", issue = "134915")]
 // impl<'a, const N: usize> From<&'a [u8; N]> for ByteString {
 //     #[inline]
@@ -190,7 +186,6 @@ impl Default for ByteString {
 //     }
 // }
 //
-// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 // #[unstable(feature = "bstr", issue = "134915")]
 // impl<const N: usize> From<[u8; N]> for ByteString {
 //     #[inline]
@@ -199,7 +194,6 @@ impl Default for ByteString {
 //     }
 // }
 //
-// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 // #[unstable(feature = "bstr", issue = "134915")]
 // impl<'a> From<&'a [u8]> for ByteString {
 //     #[inline]
@@ -226,7 +220,6 @@ impl From<ByteString> for Vec<u8> {
 
 // Omitted due to inference failures
 //
-// #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 // #[unstable(feature = "bstr", issue = "134915")]
 // impl<'a> From<&'a str> for ByteString {
 //     #[inline]
@@ -243,7 +236,6 @@ impl From<ByteString> for Vec<u8> {
 //     }
 // }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl<'a> From<&'a ByteStr> for ByteString {
     #[inline]
@@ -252,7 +244,6 @@ impl<'a> From<&'a ByteStr> for ByteString {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl<'a> From<ByteString> for Cow<'a, ByteStr> {
     #[inline]
@@ -261,7 +252,6 @@ impl<'a> From<ByteString> for Cow<'a, ByteStr> {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl<'a> From<&'a ByteString> for Cow<'a, ByteStr> {
     #[inline]
@@ -330,7 +320,6 @@ impl FromIterator<ByteString> for ByteString {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl FromStr for ByteString {
     type Err = core::convert::Infallible;
@@ -488,7 +477,6 @@ impl PartialEq for ByteString {
 
 macro_rules! impl_partial_eq_ord_cow {
     ($lhs:ty, $rhs:ty) => {
-        #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
         #[allow(unused_lifetimes)]
         #[unstable(feature = "bstr", issue = "134915")]
         impl<'a> PartialEq<$rhs> for $lhs {
@@ -499,7 +487,6 @@ macro_rules! impl_partial_eq_ord_cow {
             }
         }
 
-        #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
         #[allow(unused_lifetimes)]
         #[unstable(feature = "bstr", issue = "134915")]
         impl<'a> PartialEq<$lhs> for $rhs {
@@ -510,7 +497,6 @@ macro_rules! impl_partial_eq_ord_cow {
             }
         }
 
-        #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
         #[allow(unused_lifetimes)]
         #[unstable(feature = "bstr", issue = "134915")]
         impl<'a> PartialOrd<$rhs> for $lhs {
@@ -521,7 +507,6 @@ macro_rules! impl_partial_eq_ord_cow {
             }
         }
 
-        #[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
         #[allow(unused_lifetimes)]
         #[unstable(feature = "bstr", issue = "134915")]
         impl<'a> PartialOrd<$lhs> for $rhs {
@@ -572,7 +557,6 @@ impl PartialOrd for ByteString {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl ToOwned for ByteStr {
     type Owned = ByteString;
@@ -605,7 +589,6 @@ impl<'a> TryFrom<&'a ByteString> for &'a str {
 
 // Additional impls for `ByteStr` that require types from `alloc`:
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl Clone for Box<ByteStr> {
     #[inline]
@@ -614,7 +597,6 @@ impl Clone for Box<ByteStr> {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> {
     #[inline]
@@ -623,7 +605,6 @@ impl<'a> From<&'a ByteStr> for Cow<'a, ByteStr> {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl From<Box<[u8]>> for Box<ByteStr> {
     #[inline]
@@ -633,7 +614,6 @@ impl From<Box<[u8]>> for Box<ByteStr> {
     }
 }
 
-#[cfg(not(test))] // https://github.com/rust-lang/rust/issues/135100
 #[unstable(feature = "bstr", issue = "134915")]
 impl From<Box<ByteStr>> for Box<[u8]> {
     #[inline]
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index 965fd63a529..b764b8fa5d9 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -153,7 +153,9 @@ use core::{fmt, ptr};
 use crate::alloc::Global;
 use crate::collections::TryReserveError;
 use crate::slice;
-use crate::vec::{self, AsVecIntoIter, Vec};
+#[cfg(not(test))]
+use crate::vec::AsVecIntoIter;
+use crate::vec::{self, Vec};
 
 /// A priority queue implemented with a binary heap.
 ///
@@ -1600,6 +1602,7 @@ unsafe impl<I, A: Allocator> InPlaceIterable for IntoIter<I, A> {
     const MERGE_BY: Option<NonZero<usize>> = NonZero::new(1);
 }
 
+#[cfg(not(test))]
 unsafe impl<I> AsVecIntoIter for IntoIter<I> {
     type Item = I;
 
diff --git a/library/alloc/src/collections/mod.rs b/library/alloc/src/collections/mod.rs
index 020cf4d7365..fac4d1a65ab 100644
--- a/library/alloc/src/collections/mod.rs
+++ b/library/alloc/src/collections/mod.rs
@@ -1,5 +1,8 @@
 //! Collection types.
 
+// Note: This module is also included in the alloctests crate using #[path] to
+// run the tests. See the comment there for an explanation why this is the case.
+
 #![stable(feature = "rust1", since = "1.0.0")]
 
 #[cfg(not(no_global_oom_handling))]
@@ -24,41 +27,54 @@ pub mod btree_map {
 pub mod btree_set {
     //! An ordered set based on a B-Tree.
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg(not(test))]
     pub use super::btree::set::*;
 }
 
+#[cfg(not(test))]
 use core::fmt::Display;
 
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
+#[cfg(not(test))]
 pub use binary_heap::BinaryHeap;
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
+#[cfg(not(test))]
 pub use btree_map::BTreeMap;
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
+#[cfg(not(test))]
 pub use btree_set::BTreeSet;
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
+#[cfg(not(test))]
 pub use linked_list::LinkedList;
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)]
+#[cfg(not(test))]
 pub use vec_deque::VecDeque;
 
+#[cfg(not(test))]
 use crate::alloc::{Layout, LayoutError};
 
 /// The error type for `try_reserve` methods.
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "try_reserve", since = "1.57.0")]
+#[cfg(not(test))]
 pub struct TryReserveError {
     kind: TryReserveErrorKind,
 }
 
+#[cfg(test)]
+pub use realalloc::collections::TryReserveError;
+
+#[cfg(not(test))]
 impl TryReserveError {
     /// Details about the allocation that caused the error
     #[inline]
@@ -80,6 +96,7 @@ impl TryReserveError {
     reason = "Uncertain how much info should be exposed",
     issue = "48043"
 )]
+#[cfg(not(test))]
 pub enum TryReserveErrorKind {
     /// Error due to the computed capacity exceeding the collection's maximum
     /// (usually `isize::MAX` bytes).
@@ -103,11 +120,15 @@ pub enum TryReserveErrorKind {
     },
 }
 
+#[cfg(test)]
+pub use realalloc::collections::TryReserveErrorKind;
+
 #[unstable(
     feature = "try_reserve_kind",
     reason = "Uncertain how much info should be exposed",
     issue = "48043"
 )]
+#[cfg(not(test))]
 impl From<TryReserveErrorKind> for TryReserveError {
     #[inline]
     fn from(kind: TryReserveErrorKind) -> Self {
@@ -116,6 +137,7 @@ impl From<TryReserveErrorKind> for TryReserveError {
 }
 
 #[unstable(feature = "try_reserve_kind", reason = "new API", issue = "48043")]
+#[cfg(not(test))]
 impl From<LayoutError> for TryReserveErrorKind {
     /// Always evaluates to [`TryReserveErrorKind::CapacityOverflow`].
     #[inline]
@@ -125,6 +147,7 @@ impl From<LayoutError> for TryReserveErrorKind {
 }
 
 #[stable(feature = "try_reserve", since = "1.57.0")]
+#[cfg(not(test))]
 impl Display for TryReserveError {
     fn fmt(
         &self,
@@ -152,4 +175,5 @@ trait SpecExtend<I: IntoIterator> {
 }
 
 #[stable(feature = "try_reserve", since = "1.57.0")]
+#[cfg(not(test))]
 impl core::error::Error for TryReserveError {}
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 299c8b8679e..f8844e2d3a5 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -645,6 +645,7 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// initialized rather than only supporting `0..len`.  Requires that
     /// `initialized.start` ≤ `initialized.end` ≤ `capacity`.
     #[inline]
+    #[cfg(not(test))]
     pub(crate) unsafe fn from_contiguous_raw_parts_in(
         ptr: *mut T,
         initialized: Range<usize>,
diff --git a/library/alloc/src/collections/vec_deque/spec_extend.rs b/library/alloc/src/collections/vec_deque/spec_extend.rs
index d246385ca84..7c7072c4c3a 100644
--- a/library/alloc/src/collections/vec_deque/spec_extend.rs
+++ b/library/alloc/src/collections/vec_deque/spec_extend.rs
@@ -3,6 +3,7 @@ use core::slice;
 
 use super::VecDeque;
 use crate::alloc::Allocator;
+#[cfg(not(test))]
 use crate::vec;
 
 // Specialization trait used for VecDeque::extend
@@ -78,6 +79,7 @@ where
     }
 }
 
+#[cfg(not(test))]
 impl<T, A: Allocator> SpecExtend<T, vec::IntoIter<T>> for VecDeque<T, A> {
     #[track_caller]
     fn spec_extend(&mut self, mut iterator: vec::IntoIter<T>) {
diff --git a/library/alloc/src/collections/vec_deque/spec_from_iter.rs b/library/alloc/src/collections/vec_deque/spec_from_iter.rs
index 1efe84d6d7d..c80a30c2103 100644
--- a/library/alloc/src/collections/vec_deque/spec_from_iter.rs
+++ b/library/alloc/src/collections/vec_deque/spec_from_iter.rs
@@ -19,6 +19,7 @@ where
     }
 }
 
+#[cfg(not(test))]
 impl<T> SpecFromIter<T, crate::vec::IntoIter<T>> for VecDeque<T> {
     #[inline]
     fn spec_from_iter(iterator: crate::vec::IntoIter<T>) -> Self {
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index fd93045a5ac..f6743c65710 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -10,7 +10,6 @@ use core::{fmt, mem, ops, ptr, slice};
 use crate::borrow::{Cow, ToOwned};
 use crate::boxed::Box;
 use crate::rc::Rc;
-use crate::slice::hack::into_vec;
 use crate::string::String;
 #[cfg(target_has_atomic = "ptr")]
 use crate::sync::Arc;
@@ -103,7 +102,7 @@ use crate::vec::Vec;
 /// of `CString` instances can lead to invalid memory accesses, memory leaks,
 /// and other memory errors.
 #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")]
+#[rustc_diagnostic_item = "cstring_type"]
 #[stable(feature = "alloc_c_string", since = "1.64.0")]
 pub struct CString {
     // Invariant 1: the slice ends with a zero byte and has a length of at least one.
@@ -491,7 +490,7 @@ impl CString {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_bytes(self) -> Vec<u8> {
-        let mut vec = into_vec(self.into_inner());
+        let mut vec = self.into_inner().into_vec();
         let _nul = vec.pop();
         debug_assert_eq!(_nul, Some(0u8));
         vec
@@ -512,7 +511,7 @@ impl CString {
     #[must_use = "`self` will be dropped if the result is not used"]
     #[stable(feature = "cstring_into", since = "1.7.0")]
     pub fn into_bytes_with_nul(self) -> Vec<u8> {
-        into_vec(self.into_inner())
+        self.into_inner().into_vec()
     }
 
     /// Returns the contents of this `CString` as a slice of bytes.
@@ -573,7 +572,7 @@ impl CString {
     #[inline]
     #[must_use]
     #[stable(feature = "as_c_str", since = "1.20.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "cstring_as_c_str")]
+    #[rustc_diagnostic_item = "cstring_as_c_str"]
     pub fn as_c_str(&self) -> &CStr {
         &*self
     }
@@ -755,7 +754,6 @@ impl<'a> From<Cow<'a, CStr>> for CString {
     }
 }
 
-#[cfg(not(test))]
 #[stable(feature = "box_from_c_str", since = "1.17.0")]
 impl From<&CStr> for Box<CStr> {
     /// Converts a `&CStr` into a `Box<CStr>`,
@@ -766,7 +764,6 @@ impl From<&CStr> for Box<CStr> {
     }
 }
 
-#[cfg(not(test))]
 #[stable(feature = "box_from_mut_slice", since = "1.84.0")]
 impl From<&mut CStr> for Box<CStr> {
     /// Converts a `&mut CStr` into a `Box<CStr>`,
@@ -845,7 +842,6 @@ impl TryFrom<CString> for String {
     }
 }
 
-#[cfg(not(test))]
 #[stable(feature = "more_box_slice_clone", since = "1.29.0")]
 impl Clone for Box<CStr> {
     #[inline]
@@ -971,7 +967,6 @@ impl Default for Rc<CStr> {
     }
 }
 
-#[cfg(not(test))]
 #[stable(feature = "default_box_extra", since = "1.17.0")]
 impl Default for Box<CStr> {
     fn default() -> Box<CStr> {
@@ -1080,7 +1075,7 @@ impl ToOwned for CStr {
     }
 
     fn clone_into(&self, target: &mut CString) {
-        let mut b = into_vec(mem::take(&mut target.inner));
+        let mut b = mem::take(&mut target.inner).into_vec();
         self.to_bytes_with_nul().clone_into(&mut b);
         target.inner = b.into_boxed_slice();
     }
@@ -1113,7 +1108,6 @@ impl AsRef<CStr> for CString {
     }
 }
 
-#[cfg(not(test))]
 impl CStr {
     /// Converts a `CStr` into a <code>[Cow]<[str]></code>.
     ///
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 265b68d3b0e..f0cdb1e4e0f 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -93,7 +93,6 @@
 //
 // Library features:
 // tidy-alphabetical-start
-#![cfg_attr(test, feature(str_as_str))]
 #![feature(alloc_layout_extra)]
 #![feature(allocator_api)]
 #![feature(array_chunks)]
@@ -161,13 +160,11 @@
 //
 // Language features:
 // tidy-alphabetical-start
-#![cfg_attr(not(test), feature(coroutine_trait))]
-#![cfg_attr(test, feature(panic_update_hook))]
-#![cfg_attr(test, feature(test))]
 #![feature(allocator_internals)]
 #![feature(allow_internal_unstable)]
 #![feature(cfg_sanitize)]
 #![feature(const_precise_live_drops)]
+#![feature(coroutine_trait)]
 #![feature(decl_macro)]
 #![feature(dropck_eyepatch)]
 #![feature(fundamental)]
@@ -200,15 +197,6 @@
 // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing.
 #![feature(intra_doc_pointers)]
 
-// Allow testing this library
-#[cfg(test)]
-#[macro_use]
-extern crate std;
-#[cfg(test)]
-extern crate test;
-#[cfg(test)]
-mod testing;
-
 // Module with internal macros used by other modules (needs to be included before other modules).
 #[macro_use]
 mod macros;
@@ -216,7 +204,6 @@ mod macros;
 mod raw_vec;
 
 // Heaps provided for low-level allocation strategies
-
 pub mod alloc;
 
 // Primitive types using the heaps above
@@ -224,13 +211,8 @@ pub mod alloc;
 // Need to conditionally define the mod from `boxed.rs` to avoid
 // duplicating the lang-items when building in test cfg; but also need
 // to allow code to have `use boxed::Box;` declarations.
-#[cfg(not(test))]
-pub mod boxed;
-#[cfg(test)]
-mod boxed {
-    pub(crate) use std::boxed::Box;
-}
 pub mod borrow;
+pub mod boxed;
 #[unstable(feature = "bstr", issue = "134915")]
 pub mod bstr;
 pub mod collections;
@@ -254,20 +236,3 @@ pub mod __export {
     pub use core::format_args;
     pub use core::hint::must_use;
 }
-
-#[cfg(test)]
-#[allow(dead_code)] // Not used in all configurations
-pub(crate) mod test_helpers {
-    /// Copied from `std::test_helpers::test_rng`, since these tests rely on the
-    /// seed not being the same for every RNG invocation too.
-    pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
-        use std::hash::{BuildHasher, Hash, Hasher};
-        let mut hasher = std::hash::RandomState::new().build_hasher();
-        std::panic::Location::caller().hash(&mut hasher);
-        let hc64 = hasher.finish();
-        let seed_vec =
-            hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<crate::vec::Vec<u8>>();
-        let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
-        rand::SeedableRng::from_seed(seed)
-    }
-}
diff --git a/library/alloc/src/macros.rs b/library/alloc/src/macros.rs
index c000fd6f4ef..214192b8c9a 100644
--- a/library/alloc/src/macros.rs
+++ b/library/alloc/src/macros.rs
@@ -34,7 +34,7 @@
 /// be mindful of side effects.
 ///
 /// [`Vec`]: crate::vec::Vec
-#[cfg(all(not(no_global_oom_handling), not(test)))]
+#[cfg(not(no_global_oom_handling))]
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_diagnostic_item = "vec_macro"]
@@ -55,25 +55,6 @@ macro_rules! vec {
     );
 }
 
-// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
-// required for this macro definition, is not available. Instead use the
-// `slice::into_vec`  function which is only available with cfg(test)
-// NB see the slice::hack module in slice.rs for more information
-#[cfg(all(not(no_global_oom_handling), test))]
-#[allow(unused_macro_rules)]
-macro_rules! vec {
-    () => (
-        $crate::vec::Vec::new()
-    );
-    ($elem:expr; $n:expr) => (
-        $crate::vec::from_elem($elem, $n)
-    );
-    ($($x:expr),*) => (
-        $crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
-    );
-    ($($x:expr,)*) => (vec![$($x),*])
-}
-
 /// Creates a `String` using interpolation of runtime expressions.
 ///
 /// The first argument `format!` receives is a format string. This must be a string
@@ -120,7 +101,7 @@ macro_rules! vec {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable(hint_must_use, liballoc_internals)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "format_macro")]
+#[rustc_diagnostic_item = "format_macro"]
 macro_rules! format {
     ($($arg:tt)*) => {
         $crate::__export::must_use({
diff --git a/library/alloc/src/raw_vec.rs b/library/alloc/src/raw_vec/mod.rs
index 70f32fbaab4..99ebc5c4bfc 100644
--- a/library/alloc/src/raw_vec.rs
+++ b/library/alloc/src/raw_vec/mod.rs
@@ -1,4 +1,8 @@
 #![unstable(feature = "raw_vec_internals", reason = "unstable const warnings", issue = "none")]
+#![cfg_attr(test, allow(dead_code))]
+
+// Note: This module is also included in the alloctests crate using #[path] to
+// run the tests. See the comment there for an explanation why this is the case.
 
 use core::marker::PhantomData;
 use core::mem::{ManuallyDrop, MaybeUninit, SizedTypeProperties};
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 5847bd8f281..fc1cee28d03 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -263,23 +263,17 @@ use core::ptr::{self, NonNull, drop_in_place};
 #[cfg(not(no_global_oom_handling))]
 use core::slice::from_raw_parts_mut;
 use core::{borrow, fmt, hint};
-#[cfg(test)]
-use std::boxed::Box;
 
 #[cfg(not(no_global_oom_handling))]
 use crate::alloc::handle_alloc_error;
 use crate::alloc::{AllocError, Allocator, Global, Layout};
 use crate::borrow::{Cow, ToOwned};
-#[cfg(not(test))]
 use crate::boxed::Box;
 #[cfg(not(no_global_oom_handling))]
 use crate::string::String;
 #[cfg(not(no_global_oom_handling))]
 use crate::vec::Vec;
 
-#[cfg(test)]
-mod tests;
-
 // This is repr(C) to future-proof against possible field-reordering, which
 // would interfere with otherwise safe [into|from]_raw() of transmutable
 // inner types.
@@ -310,7 +304,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout {
 ///
 /// [get_mut]: Rc::get_mut
 #[doc(search_unbox)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Rc")]
+#[rustc_diagnostic_item = "Rc"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_insignificant_dtor]
 pub struct Rc<
@@ -2988,7 +2982,7 @@ impl<T, I: iter::TrustedLen<Item = T>> ToRcSlice<T> for I {
 ///
 /// [`upgrade`]: Weak::upgrade
 #[stable(feature = "rc_weak", since = "1.4.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "RcWeak")]
+#[rustc_diagnostic_item = "RcWeak"]
 pub struct Weak<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 8baf9685062..7c5d22e1ee9 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -8,9 +8,6 @@
 //! A few functions are provided to create a slice from a value reference
 //! or from a raw pointer.
 #![stable(feature = "rust1", since = "1.0.0")]
-// Many of the usings in this module are only used in the test configuration.
-// It's cleaner to just turn off the unused_imports warning than to fix them.
-#![cfg_attr(test, allow(unused_imports, dead_code))]
 
 use core::borrow::{Borrow, BorrowMut};
 #[cfg(not(no_global_oom_handling))]
@@ -63,16 +60,6 @@ pub use core::slice::{range, try_range};
 ////////////////////////////////////////////////////////////////////////////////
 // Basic slice extension methods
 ////////////////////////////////////////////////////////////////////////////////
-
-// HACK(japaric) needed for the implementation of `vec!` macro during testing
-// N.B., see the `hack` module in this file for more details.
-#[cfg(test)]
-pub use hack::into_vec;
-// HACK(japaric) needed for the implementation of `Vec::clone` during testing
-// N.B., see the `hack` module in this file for more details.
-#[cfg(test)]
-pub use hack::to_vec;
-
 use crate::alloc::Allocator;
 #[cfg(not(no_global_oom_handling))]
 use crate::alloc::Global;
@@ -81,98 +68,6 @@ use crate::borrow::ToOwned;
 use crate::boxed::Box;
 use crate::vec::Vec;
 
-// HACK(japaric): With cfg(test) `impl [T]` is not available, these three
-// functions are actually methods that are in `impl [T]` but not in
-// `core::slice::SliceExt` - we need to supply these functions for the
-// `test_permutations` test
-#[allow(unreachable_pub)] // cfg(test) pub above
-pub(crate) mod hack {
-    use core::alloc::Allocator;
-
-    use crate::boxed::Box;
-    use crate::vec::Vec;
-
-    // We shouldn't add inline attribute to this since this is used in
-    // `vec!` macro mostly and causes perf regression. See #71204 for
-    // discussion and perf results.
-    #[allow(missing_docs)]
-    pub fn into_vec<T, A: Allocator>(b: Box<[T], A>) -> Vec<T, A> {
-        unsafe {
-            let len = b.len();
-            let (b, alloc) = Box::into_raw_with_allocator(b);
-            Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
-        }
-    }
-
-    #[cfg(not(no_global_oom_handling))]
-    #[allow(missing_docs)]
-    #[inline]
-    pub fn to_vec<T: ConvertVec, A: Allocator>(s: &[T], alloc: A) -> Vec<T, A> {
-        T::to_vec(s, alloc)
-    }
-
-    #[cfg(not(no_global_oom_handling))]
-    pub trait ConvertVec {
-        fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A>
-        where
-            Self: Sized;
-    }
-
-    #[cfg(not(no_global_oom_handling))]
-    impl<T: Clone> ConvertVec for T {
-        #[inline]
-        default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
-            struct DropGuard<'a, T, A: Allocator> {
-                vec: &'a mut Vec<T, A>,
-                num_init: usize,
-            }
-            impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> {
-                #[inline]
-                fn drop(&mut self) {
-                    // SAFETY:
-                    // items were marked initialized in the loop below
-                    unsafe {
-                        self.vec.set_len(self.num_init);
-                    }
-                }
-            }
-            let mut vec = Vec::with_capacity_in(s.len(), alloc);
-            let mut guard = DropGuard { vec: &mut vec, num_init: 0 };
-            let slots = guard.vec.spare_capacity_mut();
-            // .take(slots.len()) is necessary for LLVM to remove bounds checks
-            // and has better codegen than zip.
-            for (i, b) in s.iter().enumerate().take(slots.len()) {
-                guard.num_init = i;
-                slots[i].write(b.clone());
-            }
-            core::mem::forget(guard);
-            // SAFETY:
-            // the vec was allocated and initialized above to at least this length.
-            unsafe {
-                vec.set_len(s.len());
-            }
-            vec
-        }
-    }
-
-    #[cfg(not(no_global_oom_handling))]
-    impl<T: Copy> ConvertVec for T {
-        #[inline]
-        fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
-            let mut v = Vec::with_capacity_in(s.len(), alloc);
-            // SAFETY:
-            // allocated above with the capacity of `s`, and initialize to `s.len()` in
-            // ptr::copy_to_non_overlapping below.
-            unsafe {
-                s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
-                v.set_len(s.len());
-            }
-            v
-        }
-    }
-}
-
-#[cfg(not(test))]
 impl<T> [T] {
     /// Sorts the slice, preserving initial order of equal elements.
     ///
@@ -501,8 +396,64 @@ impl<T> [T] {
     where
         T: Clone,
     {
-        // N.B., see the `hack` module in this file for more details.
-        hack::to_vec(self, alloc)
+        return T::to_vec(self, alloc);
+
+        trait ConvertVec {
+            fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A>
+            where
+                Self: Sized;
+        }
+
+        impl<T: Clone> ConvertVec for T {
+            #[inline]
+            default fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
+                struct DropGuard<'a, T, A: Allocator> {
+                    vec: &'a mut Vec<T, A>,
+                    num_init: usize,
+                }
+                impl<'a, T, A: Allocator> Drop for DropGuard<'a, T, A> {
+                    #[inline]
+                    fn drop(&mut self) {
+                        // SAFETY:
+                        // items were marked initialized in the loop below
+                        unsafe {
+                            self.vec.set_len(self.num_init);
+                        }
+                    }
+                }
+                let mut vec = Vec::with_capacity_in(s.len(), alloc);
+                let mut guard = DropGuard { vec: &mut vec, num_init: 0 };
+                let slots = guard.vec.spare_capacity_mut();
+                // .take(slots.len()) is necessary for LLVM to remove bounds checks
+                // and has better codegen than zip.
+                for (i, b) in s.iter().enumerate().take(slots.len()) {
+                    guard.num_init = i;
+                    slots[i].write(b.clone());
+                }
+                core::mem::forget(guard);
+                // SAFETY:
+                // the vec was allocated and initialized above to at least this length.
+                unsafe {
+                    vec.set_len(s.len());
+                }
+                vec
+            }
+        }
+
+        impl<T: Copy> ConvertVec for T {
+            #[inline]
+            fn to_vec<A: Allocator>(s: &[Self], alloc: A) -> Vec<Self, A> {
+                let mut v = Vec::with_capacity_in(s.len(), alloc);
+                // SAFETY:
+                // allocated above with the capacity of `s`, and initialize to `s.len()` in
+                // ptr::copy_to_non_overlapping below.
+                unsafe {
+                    s.as_ptr().copy_to_nonoverlapping(v.as_mut_ptr(), s.len());
+                    v.set_len(s.len());
+                }
+                v
+            }
+        }
     }
 
     /// Converts `self` into a vector without clones or allocation.
@@ -522,10 +473,13 @@ impl<T> [T] {
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "slice_into_vec")]
+    #[rustc_diagnostic_item = "slice_into_vec"]
     pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
-        // N.B., see the `hack` module in this file for more details.
-        hack::into_vec(self)
+        unsafe {
+            let len = self.len();
+            let (b, alloc) = Box::into_raw_with_allocator(self);
+            Vec::from_raw_parts_in(b as *mut T, len, len, alloc)
+        }
     }
 
     /// Creates a vector by copying a slice `n` times.
@@ -666,7 +620,6 @@ impl<T> [T] {
     }
 }
 
-#[cfg(not(test))]
 impl [u8] {
     /// Returns a vector containing a copy of this slice where each byte
     /// is mapped to its ASCII upper case equivalent.
@@ -883,14 +836,9 @@ impl<T: Copy, A: Allocator> SpecCloneIntoVec<T, A> for [T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> ToOwned for [T] {
     type Owned = Vec<T>;
-    #[cfg(not(test))]
-    fn to_owned(&self) -> Vec<T> {
-        self.to_vec()
-    }
 
-    #[cfg(test)]
     fn to_owned(&self) -> Vec<T> {
-        hack::to_vec(self, Global)
+        self.to_vec()
     }
 
     fn clone_into(&self, target: &mut Vec<T>) {
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index 6fee8d3fe33..0664f2c3cf2 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -219,7 +219,6 @@ impl ToOwned for str {
 }
 
 /// Methods for string slices.
-#[cfg(not(test))]
 impl str {
     /// Converts a `Box<str>` into a `Box<[u8]>` without copying or allocating.
     ///
@@ -631,7 +630,6 @@ pub unsafe fn from_boxed_utf8_unchecked(v: Box<[u8]>) -> Box<str> {
 #[unstable(feature = "str_internals", issue = "none")]
 #[doc(hidden)]
 #[inline]
-#[cfg(not(test))]
 #[cfg(not(no_global_oom_handling))]
 pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) {
     // Process the input in chunks of 16 bytes to enable auto-vectorization.
@@ -704,7 +702,6 @@ pub fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, &str) {
     }
 }
 #[inline]
-#[cfg(not(test))]
 #[cfg(not(no_global_oom_handling))]
 #[allow(dead_code)]
 /// Faster implementation of string replacement for ASCII to ASCII cases.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 2c034786549..2ba797ab2ad 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -356,7 +356,7 @@ use crate::vec::{self, Vec};
 /// [`as_str()`]: String::as_str
 #[derive(PartialEq, PartialOrd, Eq, Ord)]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), lang = "String")]
+#[lang = "String"]
 pub struct String {
     vec: Vec<u8>,
 }
@@ -438,7 +438,7 @@ impl String {
     /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_string_new", since = "1.39.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_new")]
+    #[rustc_diagnostic_item = "string_new"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub const fn new() -> String {
@@ -501,17 +501,6 @@ impl String {
         Ok(String { vec: Vec::try_with_capacity(capacity)? })
     }
 
-    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
-    // required for this method definition, is not available. Since we don't
-    // require this method for testing purposes, I'll just stub it
-    // NB see the slice::hack module in slice.rs for more information
-    #[inline]
-    #[cfg(test)]
-    #[allow(missing_docs)]
-    pub fn from_str(_: &str) -> String {
-        panic!("not available with cfg(test)");
-    }
-
     /// Converts a vector of bytes to a `String`.
     ///
     /// A string ([`String`]) is made of bytes ([`u8`]), and a vector of bytes
@@ -570,7 +559,7 @@ impl String {
     /// [`into_bytes`]: String::into_bytes
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_from_utf8")]
+    #[rustc_diagnostic_item = "string_from_utf8"]
     pub fn from_utf8(vec: Vec<u8>) -> Result<String, FromUtf8Error> {
         match str::from_utf8(&vec) {
             Ok(..) => Ok(String { vec }),
@@ -1071,7 +1060,7 @@ impl String {
     #[inline]
     #[must_use]
     #[stable(feature = "string_as_str", since = "1.7.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_str")]
+    #[rustc_diagnostic_item = "string_as_str"]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     pub const fn as_str(&self) -> &str {
         // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error
@@ -1094,7 +1083,7 @@ impl String {
     #[inline]
     #[must_use]
     #[stable(feature = "string_as_str", since = "1.7.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_as_mut_str")]
+    #[rustc_diagnostic_item = "string_as_mut_str"]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     pub const fn as_mut_str(&mut self) -> &mut str {
         // SAFETY: String contents are stipulated to be valid UTF-8, invalid contents are an error
@@ -1117,7 +1106,7 @@ impl String {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_confusables("append", "push")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_push_str")]
+    #[rustc_diagnostic_item = "string_push_str"]
     pub fn push_str(&mut self, string: &str) {
         self.vec.extend_from_slice(string.as_bytes())
     }
@@ -1755,7 +1744,7 @@ impl String {
     #[cfg(not(no_global_oom_handling))]
     #[inline]
     #[stable(feature = "insert_str", since = "1.16.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "string_insert_str")]
+    #[rustc_diagnostic_item = "string_insert_str"]
     pub fn insert_str(&mut self, idx: usize, string: &str) {
         assert!(self.is_char_boundary(idx));
 
@@ -2724,7 +2713,7 @@ impl FromStr for String {
 /// implementation for free.
 ///
 /// [`Display`]: fmt::Display
-#[cfg_attr(not(test), rustc_diagnostic_item = "ToString")]
+#[rustc_diagnostic_item = "ToString"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait ToString {
     /// Converts the given value to a `String`.
@@ -2739,7 +2728,7 @@ pub trait ToString {
     /// ```
     #[rustc_conversion_suggestion]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "to_string_method")]
+    #[rustc_diagnostic_item = "to_string_method"]
     fn to_string(&self) -> String;
 }
 
@@ -2979,7 +2968,6 @@ impl From<&String> for String {
 }
 
 // note: test pulls in std, which causes errors here
-#[cfg(not(test))]
 #[stable(feature = "string_from_box", since = "1.18.0")]
 impl From<Box<str>> for String {
     /// Converts the given boxed `str` slice to a [`String`].
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 21ee59cc538..4999319f618 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -235,7 +235,7 @@ macro_rules! acquire {
 ///
 /// [rc_examples]: crate::rc#examples
 #[doc(search_unbox)]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Arc")]
+#[rustc_diagnostic_item = "Arc"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_insignificant_dtor]
 pub struct Arc<
@@ -312,7 +312,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
 ///
 /// [`upgrade`]: Weak::upgrade
 #[stable(feature = "arc_weak", since = "1.4.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "ArcWeak")]
+#[rustc_diagnostic_item = "ArcWeak"]
 pub struct Weak<
     T: ?Sized,
     #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 52597e41c1c..3eee988b6c9 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -472,14 +472,9 @@ where
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "vec_into_iter_clone", since = "1.8.0")]
 impl<T: Clone, A: Allocator + Clone> Clone for IntoIter<T, A> {
-    #[cfg(not(test))]
     fn clone(&self) -> Self {
         self.as_slice().to_vec_in(self.alloc.deref().clone()).into_iter()
     }
-    #[cfg(test)]
-    fn clone(&self) -> Self {
-        crate::slice::to_vec(self.as_slice(), self.alloc.deref().clone()).into_iter()
-    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 49878f2b6fa..ce668540598 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -404,7 +404,7 @@ mod spec_extend;
 /// [owned slice]: Box
 /// [`into_boxed_slice`]: Vec::into_boxed_slice
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "Vec")]
+#[rustc_diagnostic_item = "Vec"]
 #[rustc_insignificant_dtor]
 pub struct Vec<T, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global> {
     buf: RawVec<T, A>,
@@ -428,7 +428,7 @@ impl<T> Vec<T> {
     /// ```
     #[inline]
     #[rustc_const_stable(feature = "const_vec_new", since = "1.39.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_new")]
+    #[rustc_diagnostic_item = "vec_new"]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
     pub const fn new() -> Self {
@@ -489,7 +489,7 @@ impl<T> Vec<T> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_with_capacity")]
+    #[rustc_diagnostic_item = "vec_with_capacity"]
     #[track_caller]
     pub fn with_capacity(capacity: usize) -> Self {
         Self::with_capacity_in(capacity, Global)
@@ -1279,7 +1279,7 @@ impl<T, A: Allocator> Vec<T, A> {
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[track_caller]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_reserve")]
+    #[rustc_diagnostic_item = "vec_reserve"]
     pub fn reserve(&mut self, additional: usize) {
         self.buf.reserve(self.len, additional);
     }
@@ -1568,7 +1568,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_slice")]
+    #[rustc_diagnostic_item = "vec_as_slice"]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     pub const fn as_slice(&self) -> &[T] {
         // SAFETY: `slice::from_raw_parts` requires pointee is a contiguous, aligned buffer of size
@@ -1600,7 +1600,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_as_mut_slice")]
+    #[rustc_diagnostic_item = "vec_as_mut_slice"]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     pub const fn as_mut_slice(&mut self) -> &mut [T] {
         // SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of
@@ -2511,7 +2511,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// Takes *O*(1) time.
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_pop")]
+    #[rustc_diagnostic_item = "vec_pop"]
     pub fn pop(&mut self) -> Option<T> {
         if self.len == 0 {
             None
@@ -2712,7 +2712,7 @@ impl<T, A: Allocator> Vec<T, A> {
     /// assert!(!v.is_empty());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg_attr(not(test), rustc_diagnostic_item = "vec_is_empty")]
+    #[rustc_diagnostic_item = "vec_is_empty"]
     #[rustc_const_unstable(feature = "const_vec_string_slice", issue = "129041")]
     pub const fn is_empty(&self) -> bool {
         self.len() == 0
@@ -3193,7 +3193,7 @@ impl<T: PartialEq, A: Allocator> Vec<T, A> {
 #[doc(hidden)]
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg_attr(not(test), rustc_diagnostic_item = "vec_from_elem")]
+#[rustc_diagnostic_item = "vec_from_elem"]
 #[track_caller]
 pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
     <T as SpecFromElem>::from_elem(elem, n, Global)
@@ -3293,23 +3293,12 @@ unsafe impl<T, A: Allocator> ops::DerefPure for Vec<T, A> {}
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone, A: Allocator + Clone> Clone for Vec<T, A> {
-    #[cfg(not(test))]
     #[track_caller]
     fn clone(&self) -> Self {
         let alloc = self.allocator().clone();
         <[T]>::to_vec_in(&**self, alloc)
     }
 
-    // HACK(japaric): with cfg(test) the inherent `[T]::to_vec` method, which is
-    // required for this method definition, is not available. Instead use the
-    // `slice::to_vec` function which is only available with cfg(test)
-    // NB see the slice::hack module in slice.rs for more information
-    #[cfg(test)]
-    fn clone(&self) -> Self {
-        let alloc = self.allocator().clone();
-        crate::slice::to_vec(&**self, alloc)
-    }
-
     /// Overwrites the contents of `self` with a clone of the contents of `source`.
     ///
     /// This method is preferred over simply assigning `source.clone()` to `self`,
@@ -3854,15 +3843,10 @@ impl<T: Clone> From<&[T]> for Vec<T> {
     /// ```
     /// assert_eq!(Vec::from(&[1, 2, 3][..]), vec![1, 2, 3]);
     /// ```
-    #[cfg(not(test))]
     #[track_caller]
     fn from(s: &[T]) -> Vec<T> {
         s.to_vec()
     }
-    #[cfg(test)]
-    fn from(s: &[T]) -> Vec<T> {
-        crate::slice::to_vec(s, Global)
-    }
 }
 
 #[cfg(not(no_global_oom_handling))]
@@ -3875,15 +3859,10 @@ impl<T: Clone> From<&mut [T]> for Vec<T> {
     /// ```
     /// assert_eq!(Vec::from(&mut [1, 2, 3][..]), vec![1, 2, 3]);
     /// ```
-    #[cfg(not(test))]
     #[track_caller]
     fn from(s: &mut [T]) -> Vec<T> {
         s.to_vec()
     }
-    #[cfg(test)]
-    fn from(s: &mut [T]) -> Vec<T> {
-        crate::slice::to_vec(s, Global)
-    }
 }
 
 #[cfg(not(no_global_oom_handling))]
@@ -3928,16 +3907,10 @@ impl<T, const N: usize> From<[T; N]> for Vec<T> {
     /// ```
     /// assert_eq!(Vec::from([1, 2, 3]), vec![1, 2, 3]);
     /// ```
-    #[cfg(not(test))]
     #[track_caller]
     fn from(s: [T; N]) -> Vec<T> {
         <[T]>::into_vec(Box::new(s))
     }
-
-    #[cfg(test)]
-    fn from(s: [T; N]) -> Vec<T> {
-        crate::slice::into_vec(Box::new(s))
-    }
 }
 
 #[stable(feature = "vec_from_cow_slice", since = "1.14.0")]
@@ -3966,7 +3939,6 @@ where
 }
 
 // note: test pulls in std, which causes errors here
-#[cfg(not(test))]
 #[stable(feature = "vec_from_box", since = "1.18.0")]
 impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
     /// Converts a boxed slice into a vector by transferring ownership of
@@ -3985,7 +3957,6 @@ impl<T, A: Allocator> From<Box<[T], A>> for Vec<T, A> {
 
 // note: test pulls in std, which causes errors here
 #[cfg(not(no_global_oom_handling))]
-#[cfg(not(test))]
 #[stable(feature = "box_from_vec", since = "1.20.0")]
 impl<T, A: Allocator> From<Vec<T, A>> for Box<[T], A> {
     /// Converts a vector into a boxed slice.
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
deleted file mode 100644
index 9d82a7621a2..00000000000
--- a/library/alloc/tests/rc.rs
+++ /dev/null
@@ -1,259 +0,0 @@
-use std::any::Any;
-use std::cell::{Cell, RefCell};
-use std::iter::TrustedLen;
-use std::rc::{Rc, Weak};
-
-#[test]
-fn uninhabited() {
-    enum Void {}
-    let mut a = Weak::<Void>::new();
-    a = a.clone();
-    assert!(a.upgrade().is_none());
-
-    let mut a: Weak<dyn Any> = a; // Unsizing
-    a = a.clone();
-    assert!(a.upgrade().is_none());
-}
-
-#[test]
-fn slice() {
-    let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]);
-    let a: Rc<[u32]> = a; // Unsizing
-    let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion
-    assert_eq!(a, b);
-
-    // Exercise is_dangling() with a DST
-    let mut a = Rc::downgrade(&a);
-    a = a.clone();
-    assert!(a.upgrade().is_some());
-}
-
-#[test]
-fn trait_object() {
-    let a: Rc<u32> = Rc::new(4);
-    let a: Rc<dyn Any> = a; // Unsizing
-
-    // Exercise is_dangling() with a DST
-    let mut a = Rc::downgrade(&a);
-    a = a.clone();
-    assert!(a.upgrade().is_some());
-
-    let mut b = Weak::<u32>::new();
-    b = b.clone();
-    assert!(b.upgrade().is_none());
-    let mut b: Weak<dyn Any> = b; // Unsizing
-    b = b.clone();
-    assert!(b.upgrade().is_none());
-}
-
-#[test]
-fn float_nan_ne() {
-    let x = Rc::new(f32::NAN);
-    assert!(x != x);
-    assert!(!(x == x));
-}
-
-#[test]
-fn partial_eq() {
-    struct TestPEq(RefCell<usize>);
-    impl PartialEq for TestPEq {
-        fn eq(&self, other: &TestPEq) -> bool {
-            *self.0.borrow_mut() += 1;
-            *other.0.borrow_mut() += 1;
-            true
-        }
-    }
-    let x = Rc::new(TestPEq(RefCell::new(0)));
-    assert!(x == x);
-    assert!(!(x != x));
-    assert_eq!(*x.0.borrow(), 4);
-}
-
-#[test]
-fn eq() {
-    #[derive(Eq)]
-    struct TestEq(RefCell<usize>);
-    impl PartialEq for TestEq {
-        fn eq(&self, other: &TestEq) -> bool {
-            *self.0.borrow_mut() += 1;
-            *other.0.borrow_mut() += 1;
-            true
-        }
-    }
-    let x = Rc::new(TestEq(RefCell::new(0)));
-    assert!(x == x);
-    assert!(!(x != x));
-    assert_eq!(*x.0.borrow(), 0);
-}
-
-const SHARED_ITER_MAX: u16 = 100;
-
-fn assert_trusted_len<I: TrustedLen>(_: &I) {}
-
-#[test]
-fn shared_from_iter_normal() {
-    // Exercise the base implementation for non-`TrustedLen` iterators.
-    {
-        // `Filter` is never `TrustedLen` since we don't
-        // know statically how many elements will be kept:
-        let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);
-
-        // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
-        let vec = iter.clone().collect::<Vec<_>>();
-        let rc = iter.collect::<Rc<[_]>>();
-        assert_eq!(&*vec, &*rc);
-
-        // Clone a bit and let these get dropped.
-        {
-            let _rc_2 = rc.clone();
-            let _rc_3 = rc.clone();
-            let _rc_4 = Rc::downgrade(&_rc_3);
-        }
-    } // Drop what hasn't been here.
-}
-
-#[test]
-fn shared_from_iter_trustedlen_normal() {
-    // Exercise the `TrustedLen` implementation under normal circumstances
-    // where `size_hint()` matches `(_, Some(exact_len))`.
-    {
-        let iter = (0..SHARED_ITER_MAX).map(Box::new);
-        assert_trusted_len(&iter);
-
-        // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
-        let vec = iter.clone().collect::<Vec<_>>();
-        let rc = iter.collect::<Rc<[_]>>();
-        assert_eq!(&*vec, &*rc);
-        assert_eq!(size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, size_of_val(&*rc));
-
-        // Clone a bit and let these get dropped.
-        {
-            let _rc_2 = rc.clone();
-            let _rc_3 = rc.clone();
-            let _rc_4 = Rc::downgrade(&_rc_3);
-        }
-    } // Drop what hasn't been here.
-
-    // Try a ZST to make sure it is handled well.
-    {
-        let iter = (0..SHARED_ITER_MAX).map(drop);
-        let vec = iter.clone().collect::<Vec<_>>();
-        let rc = iter.collect::<Rc<[_]>>();
-        assert_eq!(&*vec, &*rc);
-        assert_eq!(0, size_of_val(&*rc));
-        {
-            let _rc_2 = rc.clone();
-            let _rc_3 = rc.clone();
-            let _rc_4 = Rc::downgrade(&_rc_3);
-        }
-    }
-}
-
-#[test]
-#[should_panic = "I've almost got 99 problems."]
-fn shared_from_iter_trustedlen_panic() {
-    // Exercise the `TrustedLen` implementation when `size_hint()` matches
-    // `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
-    let iter = (0..SHARED_ITER_MAX).map(|val| match val {
-        98 => panic!("I've almost got 99 problems."),
-        _ => Box::new(val),
-    });
-    assert_trusted_len(&iter);
-    let _ = iter.collect::<Rc<[_]>>();
-
-    panic!("I am unreachable.");
-}
-
-#[test]
-fn shared_from_iter_trustedlen_no_fuse() {
-    // Exercise the `TrustedLen` implementation when `size_hint()` matches
-    // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
-    struct Iter(std::vec::IntoIter<Option<Box<u8>>>);
-
-    unsafe impl TrustedLen for Iter {}
-
-    impl Iterator for Iter {
-        fn size_hint(&self) -> (usize, Option<usize>) {
-            (2, Some(2))
-        }
-
-        type Item = Box<u8>;
-
-        fn next(&mut self) -> Option<Self::Item> {
-            self.0.next().flatten()
-        }
-    }
-
-    let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))];
-    let iter = Iter(vec.into_iter());
-    assert_trusted_len(&iter);
-    assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>());
-}
-
-#[test]
-fn weak_may_dangle() {
-    fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> {
-        val.clone()
-    }
-
-    // Without #[may_dangle] we get:
-    let mut val = Weak::new();
-    hmm(&mut val);
-    //  ~~~~~~~~ borrowed value does not live long enough
-    //
-    // `val` dropped here while still borrowed
-    // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
-}
-
-/// Test that a panic from a destructor does not leak the allocation.
-#[test]
-#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
-fn panic_no_leak() {
-    use std::alloc::{AllocError, Allocator, Global, Layout};
-    use std::panic::{AssertUnwindSafe, catch_unwind};
-    use std::ptr::NonNull;
-
-    struct AllocCount(Cell<i32>);
-    unsafe impl Allocator for AllocCount {
-        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
-            self.0.set(self.0.get() + 1);
-            Global.allocate(layout)
-        }
-        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
-            self.0.set(self.0.get() - 1);
-            unsafe { Global.deallocate(ptr, layout) }
-        }
-    }
-
-    struct PanicOnDrop;
-    impl Drop for PanicOnDrop {
-        fn drop(&mut self) {
-            panic!("PanicOnDrop");
-        }
-    }
-
-    let alloc = AllocCount(Cell::new(0));
-    let rc = Rc::new_in(PanicOnDrop, &alloc);
-    assert_eq!(alloc.0.get(), 1);
-
-    let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err();
-    assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop");
-    assert_eq!(alloc.0.get(), 0);
-}
-
-#[allow(unused)]
-mod pin_coerce_unsized {
-    use alloc::rc::{Rc, UniqueRc};
-    use core::pin::Pin;
-
-    pub trait MyTrait {}
-    impl MyTrait for String {}
-
-    // Pin coercion should work for Rc
-    pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> {
-        arg
-    }
-    pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> {
-        arg
-    }
-}
diff --git a/library/alloctests/Cargo.toml b/library/alloctests/Cargo.toml
new file mode 100644
index 00000000000..306375f5f01
--- /dev/null
+++ b/library/alloctests/Cargo.toml
@@ -0,0 +1,47 @@
+[package]
+name = "alloctests"
+version = "0.0.0"
+license = "MIT OR Apache-2.0"
+repository = "https://github.com/rust-lang/rust.git"
+description = "Tests for the Rust Allocation Library"
+autotests = false
+autobenches = false
+edition = "2021"
+
+[lib]
+path = "lib.rs"
+test = true
+bench = true
+doc = false
+
+[dev-dependencies]
+rand = { version = "0.9.0", default-features = false, features = ["alloc"] }
+rand_xorshift = "0.4.0"
+
+[[test]]
+name = "alloctests"
+path = "tests/lib.rs"
+
+[[test]]
+name = "vec_deque_alloc_error"
+path = "tests/vec_deque_alloc_error.rs"
+
+[[bench]]
+name = "allocbenches"
+path = "benches/lib.rs"
+test = true
+
+[[bench]]
+name = "vec_deque_append_bench"
+path = "benches/vec_deque_append.rs"
+harness = false
+
+[lints.rust.unexpected_cfgs]
+level = "warn"
+check-cfg = [
+    'cfg(bootstrap)',
+    'cfg(no_global_oom_handling)',
+    'cfg(no_rc)',
+    'cfg(no_sync)',
+    'cfg(randomized_layouts)',
+]
diff --git a/library/alloc/benches/binary_heap.rs b/library/alloctests/benches/binary_heap.rs
index 1b8f7f1c242..1b8f7f1c242 100644
--- a/library/alloc/benches/binary_heap.rs
+++ b/library/alloctests/benches/binary_heap.rs
diff --git a/library/alloc/benches/btree/map.rs b/library/alloctests/benches/btree/map.rs
index 20f02dc3a96..20f02dc3a96 100644
--- a/library/alloc/benches/btree/map.rs
+++ b/library/alloctests/benches/btree/map.rs
diff --git a/library/alloc/benches/btree/mod.rs b/library/alloctests/benches/btree/mod.rs
index 095ca5dd2e2..095ca5dd2e2 100644
--- a/library/alloc/benches/btree/mod.rs
+++ b/library/alloctests/benches/btree/mod.rs
diff --git a/library/alloc/benches/btree/set.rs b/library/alloctests/benches/btree/set.rs
index 5aa395b4d52..5aa395b4d52 100644
--- a/library/alloc/benches/btree/set.rs
+++ b/library/alloctests/benches/btree/set.rs
diff --git a/library/alloc/benches/lib.rs b/library/alloctests/benches/lib.rs
index 2633154318c..2633154318c 100644
--- a/library/alloc/benches/lib.rs
+++ b/library/alloctests/benches/lib.rs
diff --git a/library/alloc/benches/linked_list.rs b/library/alloctests/benches/linked_list.rs
index b9322b6d4c3..b9322b6d4c3 100644
--- a/library/alloc/benches/linked_list.rs
+++ b/library/alloctests/benches/linked_list.rs
diff --git a/library/alloc/benches/slice.rs b/library/alloctests/benches/slice.rs
index 27b0e6fac0a..27b0e6fac0a 100644
--- a/library/alloc/benches/slice.rs
+++ b/library/alloctests/benches/slice.rs
diff --git a/library/alloc/benches/str.rs b/library/alloctests/benches/str.rs
index 98c7c5413ca..98c7c5413ca 100644
--- a/library/alloc/benches/str.rs
+++ b/library/alloctests/benches/str.rs
diff --git a/library/alloc/benches/string.rs b/library/alloctests/benches/string.rs
index 3d79ab78c69..3d79ab78c69 100644
--- a/library/alloc/benches/string.rs
+++ b/library/alloctests/benches/string.rs
diff --git a/library/alloc/benches/vec.rs b/library/alloctests/benches/vec.rs
index 1dab71fa1f4..1dab71fa1f4 100644
--- a/library/alloc/benches/vec.rs
+++ b/library/alloctests/benches/vec.rs
diff --git a/library/alloc/benches/vec_deque.rs b/library/alloctests/benches/vec_deque.rs
index a56f8496963..a56f8496963 100644
--- a/library/alloc/benches/vec_deque.rs
+++ b/library/alloctests/benches/vec_deque.rs
diff --git a/library/alloc/benches/vec_deque_append.rs b/library/alloctests/benches/vec_deque_append.rs
index 7c805da9737..7c805da9737 100644
--- a/library/alloc/benches/vec_deque_append.rs
+++ b/library/alloctests/benches/vec_deque_append.rs
diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs
new file mode 100644
index 00000000000..6ce8a6d9ca1
--- /dev/null
+++ b/library/alloctests/lib.rs
@@ -0,0 +1,93 @@
+#![cfg(test)]
+#![allow(unused_attributes)]
+#![unstable(feature = "alloctests", issue = "none")]
+#![no_std]
+// Lints:
+#![deny(unsafe_op_in_unsafe_fn)]
+#![warn(deprecated_in_future)]
+#![warn(missing_debug_implementations)]
+#![allow(explicit_outlives_requirements)]
+#![allow(internal_features)]
+#![allow(rustdoc::redundant_explicit_links)]
+#![warn(rustdoc::unescaped_backticks)]
+#![deny(ffi_unwind_calls)]
+//
+// Library features:
+// tidy-alphabetical-start
+#![feature(alloc_layout_extra)]
+#![feature(allocator_api)]
+#![feature(array_into_iter_constructors)]
+#![feature(assert_matches)]
+#![feature(core_intrinsics)]
+#![feature(exact_size_is_empty)]
+#![feature(extend_one)]
+#![feature(extend_one_unchecked)]
+#![feature(hasher_prefixfree_extras)]
+#![feature(inplace_iteration)]
+#![feature(iter_advance_by)]
+#![feature(iter_next_chunk)]
+#![feature(maybe_uninit_slice)]
+#![feature(maybe_uninit_uninit_array_transpose)]
+#![feature(ptr_internals)]
+#![feature(sized_type_properties)]
+#![feature(slice_iter_mut_as_mut_slice)]
+#![feature(slice_ptr_get)]
+#![feature(slice_range)]
+#![feature(std_internals)]
+#![feature(temporary_niche_types)]
+#![feature(trusted_fused)]
+#![feature(trusted_len)]
+#![feature(trusted_random_access)]
+#![feature(try_reserve_kind)]
+#![feature(try_trait_v2)]
+// tidy-alphabetical-end
+//
+// Language features:
+// tidy-alphabetical-start
+#![feature(cfg_sanitize)]
+#![feature(dropck_eyepatch)]
+#![feature(lang_items)]
+#![feature(min_specialization)]
+#![feature(negative_impls)]
+#![feature(never_type)]
+#![feature(optimize_attribute)]
+#![feature(rustc_allow_const_fn_unstable)]
+#![feature(rustc_attrs)]
+#![feature(staged_api)]
+#![feature(test)]
+#![rustc_preserve_ub_checks]
+// tidy-alphabetical-end
+
+// Allow testing this library
+extern crate alloc as realalloc;
+#[macro_use]
+extern crate std;
+#[cfg(test)]
+extern crate test;
+mod testing;
+use realalloc::*;
+
+// We are directly including collections and raw_vec here as both use non-public
+// methods and fields in tests and as such need to have the types to test in the
+// same crate as the tests themself.
+#[path = "../alloc/src/collections/mod.rs"]
+mod collections;
+
+#[path = "../alloc/src/raw_vec/mod.rs"]
+mod raw_vec;
+
+#[allow(dead_code)] // Not used in all configurations
+pub(crate) mod test_helpers {
+    /// Copied from `std::test_helpers::test_rng`, since these tests rely on the
+    /// seed not being the same for every RNG invocation too.
+    pub(crate) fn test_rng() -> rand_xorshift::XorShiftRng {
+        use std::hash::{BuildHasher, Hash, Hasher};
+        let mut hasher = std::hash::RandomState::new().build_hasher();
+        std::panic::Location::caller().hash(&mut hasher);
+        let hc64 = hasher.finish();
+        let seed_vec =
+            hc64.to_le_bytes().into_iter().chain(0u8..8).collect::<crate::vec::Vec<u8>>();
+        let seed: [u8; 16] = seed_vec.as_slice().try_into().unwrap();
+        rand::SeedableRng::from_seed(seed)
+    }
+}
diff --git a/library/alloc/src/testing/crash_test.rs b/library/alloctests/testing/crash_test.rs
index 8e00e4f41e5..8e00e4f41e5 100644
--- a/library/alloc/src/testing/crash_test.rs
+++ b/library/alloctests/testing/crash_test.rs
diff --git a/library/alloc/src/testing/mod.rs b/library/alloctests/testing/mod.rs
index c8457daf93e..c8457daf93e 100644
--- a/library/alloc/src/testing/mod.rs
+++ b/library/alloctests/testing/mod.rs
diff --git a/library/alloc/src/testing/ord_chaos.rs b/library/alloctests/testing/ord_chaos.rs
index 55e1ae5e3de..55e1ae5e3de 100644
--- a/library/alloc/src/testing/ord_chaos.rs
+++ b/library/alloctests/testing/ord_chaos.rs
diff --git a/library/alloc/src/testing/rng.rs b/library/alloctests/testing/rng.rs
index 77d3348f38a..77d3348f38a 100644
--- a/library/alloc/src/testing/rng.rs
+++ b/library/alloctests/testing/rng.rs
diff --git a/library/alloc/tests/alloc.rs b/library/alloctests/tests/alloc_test.rs
index 1e722d66795..1e722d66795 100644
--- a/library/alloc/tests/alloc.rs
+++ b/library/alloctests/tests/alloc_test.rs
diff --git a/library/alloc/tests/arc.rs b/library/alloctests/tests/arc.rs
index 0baa50f439b..0baa50f439b 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloctests/tests/arc.rs
diff --git a/library/alloc/tests/autotraits.rs b/library/alloctests/tests/autotraits.rs
index 6b82deeac8a..6b82deeac8a 100644
--- a/library/alloc/tests/autotraits.rs
+++ b/library/alloctests/tests/autotraits.rs
diff --git a/library/alloc/tests/borrow.rs b/library/alloctests/tests/borrow.rs
index af7efb7d782..af7efb7d782 100644
--- a/library/alloc/tests/borrow.rs
+++ b/library/alloctests/tests/borrow.rs
diff --git a/library/alloc/tests/boxed.rs b/library/alloctests/tests/boxed.rs
index 94389cf2de9..94389cf2de9 100644
--- a/library/alloc/tests/boxed.rs
+++ b/library/alloctests/tests/boxed.rs
diff --git a/library/alloc/tests/btree_set_hash.rs b/library/alloctests/tests/btree_set_hash.rs
index 71a3a143209..71a3a143209 100644
--- a/library/alloc/tests/btree_set_hash.rs
+++ b/library/alloctests/tests/btree_set_hash.rs
diff --git a/library/alloc/tests/c_str.rs b/library/alloctests/tests/c_str.rs
index 4a581793956..4a581793956 100644
--- a/library/alloc/tests/c_str.rs
+++ b/library/alloctests/tests/c_str.rs
diff --git a/library/alloc/tests/c_str2.rs b/library/alloctests/tests/c_str2.rs
index 0f4c27fa123..0f4c27fa123 100644
--- a/library/alloc/tests/c_str2.rs
+++ b/library/alloctests/tests/c_str2.rs
diff --git a/library/alloc/tests/collections/binary_heap.rs b/library/alloctests/tests/collections/binary_heap.rs
index 95f4c3e614f..95f4c3e614f 100644
--- a/library/alloc/tests/collections/binary_heap.rs
+++ b/library/alloctests/tests/collections/binary_heap.rs
diff --git a/library/alloc/tests/collections/mod.rs b/library/alloctests/tests/collections/mod.rs
index e73f3aaef8c..e73f3aaef8c 100644
--- a/library/alloc/tests/collections/mod.rs
+++ b/library/alloctests/tests/collections/mod.rs
diff --git a/library/alloc/tests/const_fns.rs b/library/alloctests/tests/const_fns.rs
index 4e7d7fc833e..4e7d7fc833e 100644
--- a/library/alloc/tests/const_fns.rs
+++ b/library/alloctests/tests/const_fns.rs
diff --git a/library/alloc/tests/cow_str.rs b/library/alloctests/tests/cow_str.rs
index 62a5c245a54..62a5c245a54 100644
--- a/library/alloc/tests/cow_str.rs
+++ b/library/alloctests/tests/cow_str.rs
diff --git a/library/alloc/tests/fmt.rs b/library/alloctests/tests/fmt.rs
index c13074c53b7..c13074c53b7 100644
--- a/library/alloc/tests/fmt.rs
+++ b/library/alloctests/tests/fmt.rs
diff --git a/library/alloc/tests/heap.rs b/library/alloctests/tests/heap.rs
index 246b341eeb3..246b341eeb3 100644
--- a/library/alloc/tests/heap.rs
+++ b/library/alloctests/tests/heap.rs
diff --git a/library/alloc/tests/lib.rs b/library/alloctests/tests/lib.rs
index 785070fb2bb..46c11ea150b 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloctests/tests/lib.rs
@@ -43,11 +43,12 @@
 #![deny(fuzzy_provenance_casts)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
+extern crate alloc;
 extern crate test;
 
 use std::hash::{DefaultHasher, Hash, Hasher};
 
-mod alloc;
+mod alloc_test;
 mod arc;
 mod autotraits;
 mod borrow;
diff --git a/library/alloc/tests/linked_list.rs b/library/alloctests/tests/linked_list.rs
index 65b09cb00c4..65b09cb00c4 100644
--- a/library/alloc/tests/linked_list.rs
+++ b/library/alloctests/tests/linked_list.rs
diff --git a/library/alloc/tests/misc_tests.rs b/library/alloctests/tests/misc_tests.rs
index b95d11cb07e..b95d11cb07e 100644
--- a/library/alloc/tests/misc_tests.rs
+++ b/library/alloctests/tests/misc_tests.rs
diff --git a/library/alloc/src/rc/tests.rs b/library/alloctests/tests/rc.rs
index 2210a7c24c0..bb68eb4ac9e 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloctests/tests/rc.rs
@@ -1,7 +1,263 @@
-use std::cell::RefCell;
-use std::clone::Clone;
+use std::any::Any;
+use std::cell::{Cell, RefCell};
+use std::iter::TrustedLen;
+use std::mem;
+use std::rc::{Rc, UniqueRc, Weak};
 
-use super::*;
+#[test]
+fn uninhabited() {
+    enum Void {}
+    let mut a = Weak::<Void>::new();
+    a = a.clone();
+    assert!(a.upgrade().is_none());
+
+    let mut a: Weak<dyn Any> = a; // Unsizing
+    a = a.clone();
+    assert!(a.upgrade().is_none());
+}
+
+#[test]
+fn slice() {
+    let a: Rc<[u32; 3]> = Rc::new([3, 2, 1]);
+    let a: Rc<[u32]> = a; // Unsizing
+    let b: Rc<[u32]> = Rc::from(&[3, 2, 1][..]); // Conversion
+    assert_eq!(a, b);
+
+    // Exercise is_dangling() with a DST
+    let mut a = Rc::downgrade(&a);
+    a = a.clone();
+    assert!(a.upgrade().is_some());
+}
+
+#[test]
+fn trait_object() {
+    let a: Rc<u32> = Rc::new(4);
+    let a: Rc<dyn Any> = a; // Unsizing
+
+    // Exercise is_dangling() with a DST
+    let mut a = Rc::downgrade(&a);
+    a = a.clone();
+    assert!(a.upgrade().is_some());
+
+    let mut b = Weak::<u32>::new();
+    b = b.clone();
+    assert!(b.upgrade().is_none());
+    let mut b: Weak<dyn Any> = b; // Unsizing
+    b = b.clone();
+    assert!(b.upgrade().is_none());
+}
+
+#[test]
+fn float_nan_ne() {
+    let x = Rc::new(f32::NAN);
+    assert!(x != x);
+    assert!(!(x == x));
+}
+
+#[test]
+fn partial_eq() {
+    struct TestPEq(RefCell<usize>);
+    impl PartialEq for TestPEq {
+        fn eq(&self, other: &TestPEq) -> bool {
+            *self.0.borrow_mut() += 1;
+            *other.0.borrow_mut() += 1;
+            true
+        }
+    }
+    let x = Rc::new(TestPEq(RefCell::new(0)));
+    assert!(x == x);
+    assert!(!(x != x));
+    assert_eq!(*x.0.borrow(), 4);
+}
+
+#[test]
+fn eq() {
+    #[derive(Eq)]
+    struct TestEq(RefCell<usize>);
+    impl PartialEq for TestEq {
+        fn eq(&self, other: &TestEq) -> bool {
+            *self.0.borrow_mut() += 1;
+            *other.0.borrow_mut() += 1;
+            true
+        }
+    }
+    let x = Rc::new(TestEq(RefCell::new(0)));
+    assert!(x == x);
+    assert!(!(x != x));
+    assert_eq!(*x.0.borrow(), 0);
+}
+
+const SHARED_ITER_MAX: u16 = 100;
+
+fn assert_trusted_len<I: TrustedLen>(_: &I) {}
+
+#[test]
+fn shared_from_iter_normal() {
+    // Exercise the base implementation for non-`TrustedLen` iterators.
+    {
+        // `Filter` is never `TrustedLen` since we don't
+        // know statically how many elements will be kept:
+        let iter = (0..SHARED_ITER_MAX).filter(|x| x % 2 == 0).map(Box::new);
+
+        // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
+        let vec = iter.clone().collect::<Vec<_>>();
+        let rc = iter.collect::<Rc<[_]>>();
+        assert_eq!(&*vec, &*rc);
+
+        // Clone a bit and let these get dropped.
+        {
+            let _rc_2 = rc.clone();
+            let _rc_3 = rc.clone();
+            let _rc_4 = Rc::downgrade(&_rc_3);
+        }
+    } // Drop what hasn't been here.
+}
+
+#[test]
+fn shared_from_iter_trustedlen_normal() {
+    // Exercise the `TrustedLen` implementation under normal circumstances
+    // where `size_hint()` matches `(_, Some(exact_len))`.
+    {
+        let iter = (0..SHARED_ITER_MAX).map(Box::new);
+        assert_trusted_len(&iter);
+
+        // Collecting into a `Vec<T>` or `Rc<[T]>` should make no difference:
+        let vec = iter.clone().collect::<Vec<_>>();
+        let rc = iter.collect::<Rc<[_]>>();
+        assert_eq!(&*vec, &*rc);
+        assert_eq!(size_of::<Box<u16>>() * SHARED_ITER_MAX as usize, size_of_val(&*rc));
+
+        // Clone a bit and let these get dropped.
+        {
+            let _rc_2 = rc.clone();
+            let _rc_3 = rc.clone();
+            let _rc_4 = Rc::downgrade(&_rc_3);
+        }
+    } // Drop what hasn't been here.
+
+    // Try a ZST to make sure it is handled well.
+    {
+        let iter = (0..SHARED_ITER_MAX).map(drop);
+        let vec = iter.clone().collect::<Vec<_>>();
+        let rc = iter.collect::<Rc<[_]>>();
+        assert_eq!(&*vec, &*rc);
+        assert_eq!(0, size_of_val(&*rc));
+        {
+            let _rc_2 = rc.clone();
+            let _rc_3 = rc.clone();
+            let _rc_4 = Rc::downgrade(&_rc_3);
+        }
+    }
+}
+
+#[test]
+#[should_panic = "I've almost got 99 problems."]
+fn shared_from_iter_trustedlen_panic() {
+    // Exercise the `TrustedLen` implementation when `size_hint()` matches
+    // `(_, Some(exact_len))` but where `.next()` drops before the last iteration.
+    let iter = (0..SHARED_ITER_MAX).map(|val| match val {
+        98 => panic!("I've almost got 99 problems."),
+        _ => Box::new(val),
+    });
+    assert_trusted_len(&iter);
+    let _ = iter.collect::<Rc<[_]>>();
+
+    panic!("I am unreachable.");
+}
+
+#[test]
+fn shared_from_iter_trustedlen_no_fuse() {
+    // Exercise the `TrustedLen` implementation when `size_hint()` matches
+    // `(_, Some(exact_len))` but where the iterator does not behave in a fused manner.
+    struct Iter(std::vec::IntoIter<Option<Box<u8>>>);
+
+    unsafe impl TrustedLen for Iter {}
+
+    impl Iterator for Iter {
+        fn size_hint(&self) -> (usize, Option<usize>) {
+            (2, Some(2))
+        }
+
+        type Item = Box<u8>;
+
+        fn next(&mut self) -> Option<Self::Item> {
+            self.0.next().flatten()
+        }
+    }
+
+    let vec = vec![Some(Box::new(42)), Some(Box::new(24)), None, Some(Box::new(12))];
+    let iter = Iter(vec.into_iter());
+    assert_trusted_len(&iter);
+    assert_eq!(&[Box::new(42), Box::new(24)], &*iter.collect::<Rc<[_]>>());
+}
+
+#[test]
+fn weak_may_dangle() {
+    fn hmm<'a>(val: &'a mut Weak<&'a str>) -> Weak<&'a str> {
+        val.clone()
+    }
+
+    // Without #[may_dangle] we get:
+    let mut val = Weak::new();
+    hmm(&mut val);
+    //  ~~~~~~~~ borrowed value does not live long enough
+    //
+    // `val` dropped here while still borrowed
+    // borrow might be used here, when `val` is dropped and runs the `Drop` code for type `std::rc::Weak`
+}
+
+/// Test that a panic from a destructor does not leak the allocation.
+#[test]
+#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
+fn panic_no_leak() {
+    use std::alloc::{AllocError, Allocator, Global, Layout};
+    use std::panic::{AssertUnwindSafe, catch_unwind};
+    use std::ptr::NonNull;
+
+    struct AllocCount(Cell<i32>);
+    unsafe impl Allocator for AllocCount {
+        fn allocate(&self, layout: Layout) -> Result<NonNull<[u8]>, AllocError> {
+            self.0.set(self.0.get() + 1);
+            Global.allocate(layout)
+        }
+        unsafe fn deallocate(&self, ptr: NonNull<u8>, layout: Layout) {
+            self.0.set(self.0.get() - 1);
+            unsafe { Global.deallocate(ptr, layout) }
+        }
+    }
+
+    struct PanicOnDrop;
+    impl Drop for PanicOnDrop {
+        fn drop(&mut self) {
+            panic!("PanicOnDrop");
+        }
+    }
+
+    let alloc = AllocCount(Cell::new(0));
+    let rc = Rc::new_in(PanicOnDrop, &alloc);
+    assert_eq!(alloc.0.get(), 1);
+
+    let panic_message = catch_unwind(AssertUnwindSafe(|| drop(rc))).unwrap_err();
+    assert_eq!(*panic_message.downcast_ref::<&'static str>().unwrap(), "PanicOnDrop");
+    assert_eq!(alloc.0.get(), 0);
+}
+
+#[allow(unused)]
+mod pin_coerce_unsized {
+    use alloc::rc::{Rc, UniqueRc};
+    use core::pin::Pin;
+
+    pub trait MyTrait {}
+    impl MyTrait for String {}
+
+    // Pin coercion should work for Rc
+    pub fn pin_rc(arg: Pin<Rc<String>>) -> Pin<Rc<dyn MyTrait>> {
+        arg
+    }
+    pub fn pin_unique_rc(arg: Pin<UniqueRc<String>>) -> Pin<UniqueRc<dyn MyTrait>> {
+        arg
+    }
+}
 
 #[test]
 fn test_clone() {
@@ -61,16 +317,20 @@ fn weak_self_cyclic() {
 
 #[test]
 fn is_unique() {
+    fn is_unique<T>(this: &Rc<T>) -> bool {
+        Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1
+    }
+
     let x = Rc::new(3);
-    assert!(Rc::is_unique(&x));
+    assert!(is_unique(&x));
     let y = x.clone();
-    assert!(!Rc::is_unique(&x));
+    assert!(!is_unique(&x));
     drop(y);
-    assert!(Rc::is_unique(&x));
+    assert!(is_unique(&x));
     let w = Rc::downgrade(&x);
-    assert!(!Rc::is_unique(&x));
+    assert!(!is_unique(&x));
     drop(w);
-    assert!(Rc::is_unique(&x));
+    assert!(is_unique(&x));
 }
 
 #[test]
diff --git a/library/alloc/tests/slice.rs b/library/alloctests/tests/slice.rs
index 2516563187f..2516563187f 100644
--- a/library/alloc/tests/slice.rs
+++ b/library/alloctests/tests/slice.rs
diff --git a/library/alloc/tests/sort/ffi_types.rs b/library/alloctests/tests/sort/ffi_types.rs
index 11515ea4769..11515ea4769 100644
--- a/library/alloc/tests/sort/ffi_types.rs
+++ b/library/alloctests/tests/sort/ffi_types.rs
diff --git a/library/alloc/tests/sort/known_good_stable_sort.rs b/library/alloctests/tests/sort/known_good_stable_sort.rs
index 2df89146253..2df89146253 100644
--- a/library/alloc/tests/sort/known_good_stable_sort.rs
+++ b/library/alloctests/tests/sort/known_good_stable_sort.rs
diff --git a/library/alloc/tests/sort/mod.rs b/library/alloctests/tests/sort/mod.rs
index 0e2494ca9d3..0e2494ca9d3 100644
--- a/library/alloc/tests/sort/mod.rs
+++ b/library/alloctests/tests/sort/mod.rs
diff --git a/library/alloc/tests/sort/patterns.rs b/library/alloctests/tests/sort/patterns.rs
index 0f1ec664d3d..0f1ec664d3d 100644
--- a/library/alloc/tests/sort/patterns.rs
+++ b/library/alloctests/tests/sort/patterns.rs
diff --git a/library/alloc/tests/sort/tests.rs b/library/alloctests/tests/sort/tests.rs
index d321f8df518..d321f8df518 100644
--- a/library/alloc/tests/sort/tests.rs
+++ b/library/alloctests/tests/sort/tests.rs
diff --git a/library/alloc/tests/sort/zipf.rs b/library/alloctests/tests/sort/zipf.rs
index 3dad2db521f..3dad2db521f 100644
--- a/library/alloc/tests/sort/zipf.rs
+++ b/library/alloctests/tests/sort/zipf.rs
diff --git a/library/alloc/tests/str.rs b/library/alloctests/tests/str.rs
index 906fa2d425e..906fa2d425e 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloctests/tests/str.rs
diff --git a/library/alloc/tests/string.rs b/library/alloctests/tests/string.rs
index d996c55f946..d996c55f946 100644
--- a/library/alloc/tests/string.rs
+++ b/library/alloctests/tests/string.rs
diff --git a/library/alloc/tests/sync.rs b/library/alloctests/tests/sync.rs
index 6d3ab1b1d11..6d3ab1b1d11 100644
--- a/library/alloc/tests/sync.rs
+++ b/library/alloctests/tests/sync.rs
diff --git a/library/alloc/tests/task.rs b/library/alloctests/tests/task.rs
index 390dec14484..390dec14484 100644
--- a/library/alloc/tests/task.rs
+++ b/library/alloctests/tests/task.rs
diff --git a/library/alloc/tests/testing/crash_test.rs b/library/alloctests/tests/testing/crash_test.rs
index 502fe6c10c6..502fe6c10c6 100644
--- a/library/alloc/tests/testing/crash_test.rs
+++ b/library/alloctests/tests/testing/crash_test.rs
diff --git a/library/alloc/tests/testing/mod.rs b/library/alloctests/tests/testing/mod.rs
index 0a3dd191dc8..0a3dd191dc8 100644
--- a/library/alloc/tests/testing/mod.rs
+++ b/library/alloctests/tests/testing/mod.rs
diff --git a/library/alloc/tests/thin_box.rs b/library/alloctests/tests/thin_box.rs
index 4c46b614127..4c46b614127 100644
--- a/library/alloc/tests/thin_box.rs
+++ b/library/alloctests/tests/thin_box.rs
diff --git a/library/alloc/tests/vec.rs b/library/alloctests/tests/vec.rs
index f430d979fa8..f430d979fa8 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloctests/tests/vec.rs
diff --git a/library/alloc/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs
index 1b03c29e5bd..1b03c29e5bd 100644
--- a/library/alloc/tests/vec_deque.rs
+++ b/library/alloctests/tests/vec_deque.rs
diff --git a/library/alloc/tests/vec_deque_alloc_error.rs b/library/alloctests/tests/vec_deque_alloc_error.rs
index 21a9118a05b..21a9118a05b 100644
--- a/library/alloc/tests/vec_deque_alloc_error.rs
+++ b/library/alloctests/tests/vec_deque_alloc_error.rs
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index 88aa70d4f2f..6cb0b19d763 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -56,6 +56,7 @@ check-aux:
 	# Run standard library tests in Miri.
 	$(Q)$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
+		library/alloctests \
 		library/alloc \
 		$(BOOTSTRAP_ARGS) \
 		--no-doc
@@ -63,6 +64,7 @@ check-aux:
 	$(Q)MIRIFLAGS="-Zmiri-disable-isolation" \
 		$(BOOTSTRAP) miri --stage 2 \
 		library/coretests \
+		library/alloctests \
 		library/alloc \
 		$(BOOTSTRAP_ARGS) \
 		--doc
diff --git a/src/bootstrap/src/core/build_steps/check.rs b/src/bootstrap/src/core/build_steps/check.rs
index b8bbe1eb5f8..18aa3119842 100644
--- a/src/bootstrap/src/core/build_steps/check.rs
+++ b/src/bootstrap/src/core/build_steps/check.rs
@@ -45,7 +45,10 @@ impl Step for Std {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.crate_or_deps("sysroot").crate_or_deps("coretests").path("library")
+        run.crate_or_deps("sysroot")
+            .crate_or_deps("coretests")
+            .crate_or_deps("alloctests")
+            .path("library")
     }
 
     fn make_run(run: RunConfig<'_>) {
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 4b7c8d5770e..e80f8f9a4b7 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -2609,7 +2609,7 @@ impl Step for Crate {
     const DEFAULT: bool = true;
 
     fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.crate_or_deps("sysroot").crate_or_deps("coretests")
+        run.crate_or_deps("sysroot").crate_or_deps("coretests").crate_or_deps("alloctests")
     }
 
     fn make_run(run: RunConfig<'_>) {
@@ -2724,12 +2724,16 @@ impl Step for Crate {
         };
 
         let mut crates = self.crates.clone();
-        // The core crate can't directly be tested. We could silently
-        // ignore it, but adding it's own test crate is less confusing
-        // for users. We still keep core itself for doctests.
+        // The core and alloc crates can't directly be tested. We
+        // could silently ignore them, but adding their own test
+        // crates is less confusing for users. We still keep core and
+        // alloc themself for doctests
         if crates.iter().any(|crate_| crate_ == "core") {
             crates.push("coretests".to_owned());
         }
+        if crates.iter().any(|crate_| crate_ == "alloc") {
+            crates.push("alloctests".to_owned());
+        }
 
         run_cargo_test(cargo, &[], &crates, &*crate_description(&self.crates), target, builder);
     }
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 205d6720718..2237eac200d 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -475,7 +475,7 @@ pub fn check(path: &Path, bad: &mut bool) {
                 && !trimmed.starts_with("//")
                 && !file.ancestors().any(|a| {
                     (a.ends_with("tests") && a.join("COMPILER_TESTS.md").exists())
-                        || a.ends_with("library/alloc/tests")
+                        || a.ends_with("library/alloctests")
                 })
                 && filename != "tests.rs"
             {