From 2a899dc1cfe37270cf976b54a2953133faafa0ae Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 7 Jul 2022 10:46:22 +0000
Subject: [PATCH 01/19] `UnsafeCell` now has no niches, ever.

---
 compiler/rustc_attr/src/builtin.rs            |   8 +-
 .../rustc_const_eval/src/interpret/intern.rs  |   2 +-
 .../src/interpret/validity.rs                 |   2 +-
 .../src/transform/check_consts/qualifs.rs     |   4 +-
 compiler/rustc_feature/src/active.rs          |   3 -
 compiler/rustc_lint/src/types.rs              |   2 +-
 compiler/rustc_middle/src/ty/adt.rs           |  11 +
 compiler/rustc_middle/src/ty/layout.rs        |  48 +--
 compiler/rustc_middle/src/ty/mod.rs           |  10 +-
 compiler/rustc_passes/src/check_attr.rs       |  21 +-
 compiler/rustc_span/src/symbol.rs             |   2 -
 library/core/src/cell.rs                      |   1 -
 library/core/src/lib.rs                       |   1 -
 src/test/ui/layout/unsafe-cell-hides-niche.rs |   5 +-
 src/test/ui/lint/clashing-extern-fn.rs        |   4 +-
 src/test/ui/lint/clashing-extern-fn.stderr    |  40 +--
 src/test/ui/repr/feature-gate-no-niche.rs     |  20 --
 src/test/ui/repr/feature-gate-no-niche.stderr |  35 --
 .../repr-no-niche-inapplicable-to-unions.rs   |  14 -
 ...epr-no-niche-inapplicable-to-unions.stderr |  19 -
 src/test/ui/repr/repr-no-niche.rs             | 327 ------------------
 .../clippy/clippy_lints/src/non_copy_const.rs |   2 +-
 22 files changed, 71 insertions(+), 510 deletions(-)
 delete mode 100644 src/test/ui/repr/feature-gate-no-niche.rs
 delete mode 100644 src/test/ui/repr/feature-gate-no-niche.stderr
 delete mode 100644 src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs
 delete mode 100644 src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr
 delete mode 100644 src/test/ui/repr/repr-no-niche.rs

diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index ce7c0eb72cd24..6673d75d99df0 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -856,7 +856,6 @@ pub enum ReprAttr {
     ReprSimd,
     ReprTransparent,
     ReprAlign(u32),
-    ReprNoNiche,
 }
 
 #[derive(Eq, PartialEq, Debug, Copy, Clone)]
@@ -904,7 +903,6 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                     sym::packed => Some(ReprPacked(1)),
                     sym::simd => Some(ReprSimd),
                     sym::transparent => Some(ReprTransparent),
-                    sym::no_niche => Some(ReprNoNiche),
                     sym::align => {
                         let mut err = struct_span_err!(
                             diagnostic,
@@ -943,7 +941,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         Ok(literal) => acc.push(ReprPacked(literal)),
                         Err(message) => literal_error = Some(message),
                     };
-                } else if matches!(name, sym::C | sym::simd | sym::transparent | sym::no_niche)
+                } else if matches!(name, sym::C | sym::simd | sym::transparent)
                     || int_type_of_word(name).is_some()
                 {
                     recognised = true;
@@ -1001,7 +999,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                     } else {
                         if matches!(
                             meta_item.name_or_empty(),
-                            sym::C | sym::simd | sym::transparent | sym::no_niche
+                            sym::C | sym::simd | sym::transparent
                         ) || int_type_of_word(meta_item.name_or_empty()).is_some()
                         {
                             recognised = true;
@@ -1039,7 +1037,7 @@ pub fn parse_repr_attr(sess: &Session, attr: &Attribute) -> Vec<ReprAttr> {
                         .emit();
                     } else if matches!(
                         meta_item.name_or_empty(),
-                        sym::C | sym::simd | sym::transparent | sym::no_niche
+                        sym::C | sym::simd | sym::transparent
                     ) || int_type_of_word(meta_item.name_or_empty()).is_some()
                     {
                         recognised = true;
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 9dfdafcb38e0b..7616e7a63d107 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -217,7 +217,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: CompileTimeMachine<'mir, 'tcx, const_eval::Memory
         }
 
         if let Some(def) = mplace.layout.ty.ty_adt_def() {
-            if Some(def.did()) == self.ecx.tcx.lang_items().unsafe_cell_type() {
+            if def.is_unsafe_cell() {
                 // We are crossing over an `UnsafeCell`, we can mutate again. This means that
                 // References we encounter inside here are interned as pointing to mutable
                 // allocations.
diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs
index 0bf78446e37fa..48ca5913fabbd 100644
--- a/compiler/rustc_const_eval/src/interpret/validity.rs
+++ b/compiler/rustc_const_eval/src/interpret/validity.rs
@@ -821,7 +821,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValueVisitor<'mir, 'tcx, M>
         // Special check preventing `UnsafeCell` in the inner part of constants
         if let Some(def) = op.layout.ty.ty_adt_def() {
             if matches!(self.ctfe_mode, Some(CtfeValidationMode::Const { inner: true, .. }))
-                && Some(def.did()) == self.ecx.tcx.lang_items().unsafe_cell_type()
+                && def.is_unsafe_cell()
             {
                 throw_validation_failure!(self.path, { "`UnsafeCell` in a `const`" });
             }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 6e5a0c813ac20..770286599d25f 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -96,13 +96,13 @@ impl Qualif for HasMutInterior {
     }
 
     fn in_adt_inherently<'tcx>(
-        cx: &ConstCx<'_, 'tcx>,
+        _cx: &ConstCx<'_, 'tcx>,
         adt: AdtDef<'tcx>,
         _: SubstsRef<'tcx>,
     ) -> bool {
         // Exactly one type, `UnsafeCell`, has the `HasMutInterior` qualif inherently.
         // It arises structurally for all other types.
-        Some(adt.did()) == cx.tcx.lang_items().unsafe_cell_type()
+        adt.is_unsafe_cell()
     }
 }
 
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index b54f0ef361a8d..117bdad971a20 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -156,9 +156,6 @@ declare_features! (
     (active, intrinsics, "1.0.0", None, None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
     (active, lang_items, "1.0.0", None, None),
-    /// Allows `#[repr(no_niche)]` (an implementation detail of `rustc`,
-    /// it is not on path for eventual stabilization).
-    (active, no_niche, "1.42.0", None, None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
     (active, omit_gdb_pretty_printer_section, "1.5.0", None, None),
     /// Allows using `#[prelude_import]` on glob `use` items.
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index be4843c7ff153..4ed9d9b27b297 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -705,7 +705,7 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
 
             // Types with a `#[repr(no_niche)]` attribute have their niche hidden.
             // The attribute is used by the UnsafeCell for example (the only use so far).
-            if def.repr().hide_niche() {
+            if def.is_unsafe_cell() {
                 return false;
             }
 
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index bf7cb610a9097..9972199c62e04 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -52,6 +52,8 @@ bitflags! {
         /// Indicates whether the variant list of this ADT is `#[non_exhaustive]`.
         /// (i.e., this flag is never set unless this ADT is an enum).
         const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
+        /// Indicates whether the type is `UnsafeCell`.
+        const IS_UNSAFE_CELL              = 1 << 9;
     }
 }
 
@@ -242,6 +244,9 @@ impl AdtDefData {
         if Some(did) == tcx.lang_items().manually_drop() {
             flags |= AdtFlags::IS_MANUALLY_DROP;
         }
+        if Some(did) == tcx.lang_items().unsafe_cell_type() {
+            flags |= AdtFlags::IS_UNSAFE_CELL;
+        }
 
         AdtDefData { did, variants, flags, repr }
     }
@@ -328,6 +333,12 @@ impl<'tcx> AdtDef<'tcx> {
         self.flags().contains(AdtFlags::IS_BOX)
     }
 
+    /// Returns `true` if this is UnsafeCell<T>.
+    #[inline]
+    pub fn is_unsafe_cell(self) -> bool {
+        self.flags().contains(AdtFlags::IS_UNSAFE_CELL)
+    }
+
     /// Returns `true` if this is `ManuallyDrop<T>`.
     #[inline]
     pub fn is_manually_drop(self) -> bool {
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index f87b6e4212d29..cef8a1dba7f8d 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -542,14 +542,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
             debug!("univariant offset: {:?} field: {:#?}", offset, field);
             offsets[i as usize] = offset;
 
-            if !repr.hide_niche() {
-                if let Some(mut niche) = field.largest_niche {
-                    let available = niche.available(dl);
-                    if available > largest_niche_available {
-                        largest_niche_available = available;
-                        niche.offset += offset;
-                        largest_niche = Some(niche);
-                    }
+            if let Some(mut niche) = field.largest_niche {
+                let available = niche.available(dl);
+                if available > largest_niche_available {
+                    largest_niche_available = available;
+                    niche.offset += offset;
+                    largest_niche = Some(niche);
                 }
             }
 
@@ -1104,23 +1102,29 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 assert!(valid_range.end >= end);
                                 valid_range.end = end;
                             }
-
-                            // Update `largest_niche` if we have introduced a larger niche.
-                            let niche = if def.repr().hide_niche() {
-                                None
+                            if def.is_unsafe_cell() {
+                                match scalar {
+                                    Scalar::Initialized { value, valid_range } => {
+                                        *valid_range = WrappingRange::full(value.size(dl))
+                                    }
+                                    // Already doesn't have any niches
+                                    Scalar::Union { .. } => {}
+                                }
+                                st.largest_niche = None;
                             } else {
-                                Niche::from_scalar(dl, Size::ZERO, *scalar)
-                            };
-                            if let Some(niche) = niche {
-                                match st.largest_niche {
-                                    Some(largest_niche) => {
-                                        // Replace the existing niche even if they're equal,
-                                        // because this one is at a lower offset.
-                                        if largest_niche.available(dl) <= niche.available(dl) {
-                                            st.largest_niche = Some(niche);
+                                // Update `largest_niche` if we have introduced a larger niche.
+                                let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
+                                if let Some(niche) = niche {
+                                    match st.largest_niche {
+                                        Some(largest_niche) => {
+                                            // Replace the existing niche even if they're equal,
+                                            // because this one is at a lower offset.
+                                            if largest_niche.available(dl) <= niche.available(dl) {
+                                                st.largest_niche = Some(niche);
+                                            }
                                         }
+                                        None => st.largest_niche = Some(niche),
                                     }
-                                    None => st.largest_niche = Some(niche),
                                 }
                             }
                         }
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 3a795af2121d0..058cf1a4183df 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1719,11 +1719,9 @@ bitflags! {
         const IS_TRANSPARENT     = 1 << 2;
         // Internal only for now. If true, don't reorder fields.
         const IS_LINEAR          = 1 << 3;
-        // If true, don't expose any niche to type's context.
-        const HIDE_NICHE         = 1 << 4;
         // If true, the type's layout can be randomized using
         // the seed stored in `ReprOptions.layout_seed`
-        const RANDOMIZE_LAYOUT   = 1 << 5;
+        const RANDOMIZE_LAYOUT   = 1 << 4;
         // Any of these flags being set prevent field reordering optimisation.
         const IS_UNOPTIMISABLE   = ReprFlags::IS_C.bits
                                  | ReprFlags::IS_SIMD.bits
@@ -1780,7 +1778,6 @@ impl ReprOptions {
                         ReprFlags::empty()
                     }
                     attr::ReprTransparent => ReprFlags::IS_TRANSPARENT,
-                    attr::ReprNoNiche => ReprFlags::HIDE_NICHE,
                     attr::ReprSimd => ReprFlags::IS_SIMD,
                     attr::ReprInt(i) => {
                         size = Some(i);
@@ -1833,11 +1830,6 @@ impl ReprOptions {
         self.flags.contains(ReprFlags::IS_LINEAR)
     }
 
-    #[inline]
-    pub fn hide_niche(&self) -> bool {
-        self.flags.contains(ReprFlags::HIDE_NICHE)
-    }
-
     /// Returns the discriminant type, given these `repr` options.
     /// This must only be called on enums!
     pub fn discr_type(&self) -> attr::IntType {
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 8c123c052e5ac..cd5357d796d9a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1808,21 +1808,6 @@ impl CheckAttrVisitor<'_> {
                         _ => ("a", "struct, enum, or union"),
                     }
                 }
-                sym::no_niche => {
-                    if !self.tcx.features().enabled(sym::no_niche) {
-                        feature_err(
-                            &self.tcx.sess.parse_sess,
-                            sym::no_niche,
-                            hint.span(),
-                            "the attribute `repr(no_niche)` is currently unstable",
-                        )
-                        .emit();
-                    }
-                    match target {
-                        Target::Struct | Target::Enum => continue,
-                        _ => ("a", "struct or enum"),
-                    }
-                }
                 sym::i8
                 | sym::u8
                 | sym::i16
@@ -1870,10 +1855,8 @@ impl CheckAttrVisitor<'_> {
         // This is not ideal, but tracking precisely which ones are at fault is a huge hassle.
         let hint_spans = hints.iter().map(|hint| hint.span());
 
-        // Error on repr(transparent, <anything else apart from no_niche>).
-        let non_no_niche = |hint: &&NestedMetaItem| hint.name_or_empty() != sym::no_niche;
-        let non_no_niche_count = hints.iter().filter(non_no_niche).count();
-        if is_transparent && non_no_niche_count > 1 {
+        // Error on repr(transparent, <anything else>).
+        if is_transparent && hints.len() > 1 {
             let hint_spans: Vec<_> = hint_spans.clone().collect();
             struct_span_err!(
                 self.tcx.sess,
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 65a2a18e02f8f..43312105fd6b0 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -979,7 +979,6 @@ symbols! {
         no_link,
         no_main,
         no_mangle,
-        no_niche,
         no_sanitize,
         no_stack_check,
         no_start,
@@ -1152,7 +1151,6 @@ symbols! {
         repr128,
         repr_align,
         repr_align_enum,
-        repr_no_niche,
         repr_packed,
         repr_simd,
         repr_transparent,
diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs
index 63c83ddb6f7cf..8a37fadc56f4c 100644
--- a/library/core/src/cell.rs
+++ b/library/core/src/cell.rs
@@ -1856,7 +1856,6 @@ impl<T: ?Sized + fmt::Display> fmt::Display for RefMut<'_, T> {
 #[lang = "unsafe_cell"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[repr(transparent)]
-#[repr(no_niche)] // rust-lang/rust#68303.
 pub struct UnsafeCell<T: ?Sized> {
     value: T,
 }
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 093c7d298734a..19775e7acda2f 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -191,7 +191,6 @@
 #![feature(never_type)]
 #![feature(no_core)]
 #![feature(no_coverage)] // rust-lang/rust#84605
-#![feature(no_niche)] // rust-lang/rust#68303
 #![feature(platform_intrinsics)]
 #![feature(prelude_import)]
 #![feature(repr_simd)]
diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 4ca3f7a1aad94..eb65756a5f643 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -5,8 +5,6 @@
 
 // run-pass
 
-#![feature(no_niche)]
-
 use std::cell::UnsafeCell;
 use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
@@ -16,8 +14,7 @@ struct Wrapper<T>(T);
 #[repr(transparent)]
 struct Transparent<T>(T);
 
-#[repr(no_niche)]
-struct NoNiche<T>(T);
+struct NoNiche<T>(UnsafeCell<T>);
 
 fn main() {
     assert_eq!(size_of::<Option<Wrapper<u32>>>(),     8);
diff --git a/src/test/ui/lint/clashing-extern-fn.rs b/src/test/ui/lint/clashing-extern-fn.rs
index 2ce4dd56eab0d..809e0602671fe 100644
--- a/src/test/ui/lint/clashing-extern-fn.rs
+++ b/src/test/ui/lint/clashing-extern-fn.rs
@@ -1,7 +1,6 @@
 // check-pass
 // aux-build:external_extern_fn.rs
 #![crate_type = "lib"]
-#![feature(no_niche)]
 #![warn(clashing_extern_declarations)]
 
 mod redeclared_different_signature {
@@ -400,9 +399,8 @@ mod hidden_niche {
         #[repr(transparent)]
         struct Transparent { x: NonZeroUsize }
 
-        #[repr(no_niche)]
         #[repr(transparent)]
-        struct TransparentNoNiche { y: NonZeroUsize }
+        struct TransparentNoNiche { y: UnsafeCell<NonZeroUsize> }
 
         extern "C" {
             fn hidden_niche_transparent() -> Option<Transparent>;
diff --git a/src/test/ui/lint/clashing-extern-fn.stderr b/src/test/ui/lint/clashing-extern-fn.stderr
index a856de322c8ca..4607f68499322 100644
--- a/src/test/ui/lint/clashing-extern-fn.stderr
+++ b/src/test/ui/lint/clashing-extern-fn.stderr
@@ -1,5 +1,5 @@
 warning: `clash` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:15:13
+  --> $DIR/clashing-extern-fn.rs:14:13
    |
 LL |             fn clash(x: u8);
    |             ---------------- `clash` previously declared here
@@ -8,7 +8,7 @@ LL |             fn clash(x: u64);
    |             ^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration
    |
 note: the lint level is defined here
-  --> $DIR/clashing-extern-fn.rs:5:9
+  --> $DIR/clashing-extern-fn.rs:4:9
    |
 LL | #![warn(clashing_extern_declarations)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -16,7 +16,7 @@ LL | #![warn(clashing_extern_declarations)]
               found `unsafe extern "C" fn(u64)`
 
 warning: `extern_link_name` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:53:9
+  --> $DIR/clashing-extern-fn.rs:52:9
    |
 LL | /     #[link_name = "extern_link_name"]
 LL | |     fn some_new_name(x: i16);
@@ -29,7 +29,7 @@ LL |           fn extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `some_other_extern_link_name` redeclares `some_other_new_name` with a different signature
-  --> $DIR/clashing-extern-fn.rs:56:9
+  --> $DIR/clashing-extern-fn.rs:55:9
    |
 LL |       fn some_other_new_name(x: i16);
    |       ------------------------------- `some_other_new_name` previously declared here
@@ -43,7 +43,7 @@ LL | |         fn some_other_extern_link_name(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `other_both_names_different` redeclares `link_name_same` with a different signature
-  --> $DIR/clashing-extern-fn.rs:60:9
+  --> $DIR/clashing-extern-fn.rs:59:9
    |
 LL | /     #[link_name = "link_name_same"]
 LL | |     fn both_names_different(x: i16);
@@ -58,7 +58,7 @@ LL | |         fn other_both_names_different(x: u32);
               found `unsafe extern "C" fn(u32)`
 
 warning: `different_mod` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:73:9
+  --> $DIR/clashing-extern-fn.rs:72:9
    |
 LL |         fn different_mod(x: u8);
    |         ------------------------ `different_mod` previously declared here
@@ -70,7 +70,7 @@ LL |         fn different_mod(x: u64);
               found `unsafe extern "C" fn(u64)`
 
 warning: `variadic_decl` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:83:9
+  --> $DIR/clashing-extern-fn.rs:82:9
    |
 LL |     fn variadic_decl(x: u8, ...);
    |     ----------------------------- `variadic_decl` previously declared here
@@ -82,7 +82,7 @@ LL |         fn variadic_decl(x: u8);
               found `unsafe extern "C" fn(u8)`
 
 warning: `weigh_banana` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:143:13
+  --> $DIR/clashing-extern-fn.rs:142:13
    |
 LL |             fn weigh_banana(count: *const Banana) -> u64;
    |             --------------------------------------------- `weigh_banana` previously declared here
@@ -94,7 +94,7 @@ LL |             fn weigh_banana(count: *const Banana) -> u64;
               found `unsafe extern "C" fn(*const three::Banana) -> u64`
 
 warning: `draw_point` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:172:13
+  --> $DIR/clashing-extern-fn.rs:171:13
    |
 LL |             fn draw_point(p: Point);
    |             ------------------------ `draw_point` previously declared here
@@ -106,7 +106,7 @@ LL |             fn draw_point(p: Point);
               found `unsafe extern "C" fn(sameish_members::b::Point)`
 
 warning: `origin` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:198:13
+  --> $DIR/clashing-extern-fn.rs:197:13
    |
 LL |             fn origin() -> Point3;
    |             ---------------------- `origin` previously declared here
@@ -118,7 +118,7 @@ LL |             fn origin() -> Point3;
               found `unsafe extern "C" fn() -> same_sized_members_clash::b::Point3`
 
 warning: `transparent_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:221:13
+  --> $DIR/clashing-extern-fn.rs:220:13
    |
 LL |             fn transparent_incorrect() -> T;
    |             -------------------------------- `transparent_incorrect` previously declared here
@@ -130,7 +130,7 @@ LL |             fn transparent_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `missing_return_type` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:239:13
+  --> $DIR/clashing-extern-fn.rs:238:13
    |
 LL |             fn missing_return_type() -> usize;
    |             ---------------------------------- `missing_return_type` previously declared here
@@ -142,7 +142,7 @@ LL |             fn missing_return_type();
               found `unsafe extern "C" fn()`
 
 warning: `non_zero_usize` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:257:13
+  --> $DIR/clashing-extern-fn.rs:256:13
    |
 LL |             fn non_zero_usize() -> core::num::NonZeroUsize;
    |             ----------------------------------------------- `non_zero_usize` previously declared here
@@ -154,7 +154,7 @@ LL |             fn non_zero_usize() -> usize;
               found `unsafe extern "C" fn() -> usize`
 
 warning: `non_null_ptr` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:259:13
+  --> $DIR/clashing-extern-fn.rs:258:13
    |
 LL |             fn non_null_ptr() -> core::ptr::NonNull<usize>;
    |             ----------------------------------------------- `non_null_ptr` previously declared here
@@ -166,7 +166,7 @@ LL |             fn non_null_ptr() -> *const usize;
               found `unsafe extern "C" fn() -> *const usize`
 
 warning: `option_non_zero_usize_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:357:13
+  --> $DIR/clashing-extern-fn.rs:356:13
    |
 LL |             fn option_non_zero_usize_incorrect() -> usize;
    |             ---------------------------------------------- `option_non_zero_usize_incorrect` previously declared here
@@ -178,7 +178,7 @@ LL |             fn option_non_zero_usize_incorrect() -> isize;
               found `unsafe extern "C" fn() -> isize`
 
 warning: `option_non_null_ptr_incorrect` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:359:13
+  --> $DIR/clashing-extern-fn.rs:358:13
    |
 LL |             fn option_non_null_ptr_incorrect() -> *const usize;
    |             --------------------------------------------------- `option_non_null_ptr_incorrect` previously declared here
@@ -190,7 +190,7 @@ LL |             fn option_non_null_ptr_incorrect() -> *const isize;
               found `unsafe extern "C" fn() -> *const isize`
 
 warning: `hidden_niche_transparent_no_niche` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:410:13
+  --> $DIR/clashing-extern-fn.rs:408:13
    |
 LL |             fn hidden_niche_transparent_no_niche() -> usize;
    |             ------------------------------------------------ `hidden_niche_transparent_no_niche` previously declared here
@@ -202,7 +202,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
               found `unsafe extern "C" fn() -> Option<TransparentNoNiche>`
 
 warning: `hidden_niche_unsafe_cell` redeclared with a different signature
-  --> $DIR/clashing-extern-fn.rs:414:13
+  --> $DIR/clashing-extern-fn.rs:412:13
    |
 LL |             fn hidden_niche_unsafe_cell() -> usize;
    |             --------------------------------------- `hidden_niche_unsafe_cell` previously declared here
@@ -214,7 +214,7 @@ LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize
               found `unsafe extern "C" fn() -> Option<UnsafeCell<NonZeroUsize>>`
 
 warning: `extern` block uses type `Option<TransparentNoNiche>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:410:55
+  --> $DIR/clashing-extern-fn.rs:408:55
    |
 LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoNiche>;
    |                                                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
@@ -224,7 +224,7 @@ LL |             fn hidden_niche_transparent_no_niche() -> Option<TransparentNoN
    = note: enum has no representation hint
 
 warning: `extern` block uses type `Option<UnsafeCell<NonZeroUsize>>`, which is not FFI-safe
-  --> $DIR/clashing-extern-fn.rs:414:46
+  --> $DIR/clashing-extern-fn.rs:412:46
    |
 LL |             fn hidden_niche_unsafe_cell() -> Option<UnsafeCell<NonZeroUsize>>;
    |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/src/test/ui/repr/feature-gate-no-niche.rs b/src/test/ui/repr/feature-gate-no-niche.rs
deleted file mode 100644
index 8872ee7119e4a..0000000000000
--- a/src/test/ui/repr/feature-gate-no-niche.rs
+++ /dev/null
@@ -1,20 +0,0 @@
-use std::num::NonZeroU8 as N8;
-use std::num::NonZeroU16 as N16;
-
-#[repr(no_niche)]
-pub struct Cloaked(N16);
-//~^^ ERROR the attribute `repr(no_niche)` is currently unstable [E0658]
-
-#[repr(transparent, no_niche)]
-pub struct Shadowy(N16);
-//~^^ ERROR the attribute `repr(no_niche)` is currently unstable [E0658]
-
-#[repr(no_niche)]
-pub enum Cloaked1 { _A(N16), }
-//~^^ ERROR the attribute `repr(no_niche)` is currently unstable [E0658]
-
-#[repr(no_niche)]
-pub enum Cloaked2 { _A(N16), _B(u8, N8) }
-//~^^ ERROR the attribute `repr(no_niche)` is currently unstable [E0658]
-
-fn main() { }
diff --git a/src/test/ui/repr/feature-gate-no-niche.stderr b/src/test/ui/repr/feature-gate-no-niche.stderr
deleted file mode 100644
index 34fd417cc99a2..0000000000000
--- a/src/test/ui/repr/feature-gate-no-niche.stderr
+++ /dev/null
@@ -1,35 +0,0 @@
-error[E0658]: the attribute `repr(no_niche)` is currently unstable
-  --> $DIR/feature-gate-no-niche.rs:4:8
-   |
-LL | #[repr(no_niche)]
-   |        ^^^^^^^^
-   |
-   = help: add `#![feature(no_niche)]` to the crate attributes to enable
-
-error[E0658]: the attribute `repr(no_niche)` is currently unstable
-  --> $DIR/feature-gate-no-niche.rs:8:21
-   |
-LL | #[repr(transparent, no_niche)]
-   |                     ^^^^^^^^
-   |
-   = help: add `#![feature(no_niche)]` to the crate attributes to enable
-
-error[E0658]: the attribute `repr(no_niche)` is currently unstable
-  --> $DIR/feature-gate-no-niche.rs:12:8
-   |
-LL | #[repr(no_niche)]
-   |        ^^^^^^^^
-   |
-   = help: add `#![feature(no_niche)]` to the crate attributes to enable
-
-error[E0658]: the attribute `repr(no_niche)` is currently unstable
-  --> $DIR/feature-gate-no-niche.rs:16:8
-   |
-LL | #[repr(no_niche)]
-   |        ^^^^^^^^
-   |
-   = help: add `#![feature(no_niche)]` to the crate attributes to enable
-
-error: aborting due to 4 previous errors
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs
deleted file mode 100644
index 870eda89c20d7..0000000000000
--- a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.rs
+++ /dev/null
@@ -1,14 +0,0 @@
-#![feature(no_niche)]
-
-use std::num::NonZeroU8 as N8;
-use std::num::NonZeroU16 as N16;
-
-#[repr(no_niche)]
-pub union Cloaked1 { _A: N16 }
-//~^^ ERROR attribute should be applied to a struct or enum [E0517]
-
-#[repr(no_niche)]
-pub union Cloaked2 { _A: N16, _B: (u8, N8) }
-//~^^ ERROR attribute should be applied to a struct or enum [E0517]
-
-fn main() { }
diff --git a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr b/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr
deleted file mode 100644
index 9af929d409473..0000000000000
--- a/src/test/ui/repr/repr-no-niche-inapplicable-to-unions.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error[E0517]: attribute should be applied to a struct or enum
-  --> $DIR/repr-no-niche-inapplicable-to-unions.rs:6:8
-   |
-LL | #[repr(no_niche)]
-   |        ^^^^^^^^
-LL | pub union Cloaked1 { _A: N16 }
-   | ------------------------------ not a struct or enum
-
-error[E0517]: attribute should be applied to a struct or enum
-  --> $DIR/repr-no-niche-inapplicable-to-unions.rs:10:8
-   |
-LL | #[repr(no_niche)]
-   |        ^^^^^^^^
-LL | pub union Cloaked2 { _A: N16, _B: (u8, N8) }
-   | -------------------------------------------- not a struct or enum
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0517`.
diff --git a/src/test/ui/repr/repr-no-niche.rs b/src/test/ui/repr/repr-no-niche.rs
deleted file mode 100644
index 2e6064aeb0074..0000000000000
--- a/src/test/ui/repr/repr-no-niche.rs
+++ /dev/null
@@ -1,327 +0,0 @@
-// run-pass
-
-// This file tests repr(no_niche), which causes an struct/enum to hide
-// any niche space that may exist in its internal state from the
-// context it appears in.
-
-// Here are the axes this test is seeking to cover:
-//
-// repr annotation:
-// visible: (); cloaked: (no_niche); transparent: (transparent); shadowy: (transparent, no_niche)
-//
-// enum vs struct
-//
-// niche-type via type-parameter vs inline declaration
-
-#![feature(decl_macro)]
-#![feature(no_niche)]
-
-use std::mem::size_of;
-use std::num::{NonZeroU8, NonZeroU16};
-
-mod struct_inline {
-    use std::num::NonZeroU16 as N16;
-
-    #[derive(Debug)] pub struct Visible(N16);
-
-    #[repr(no_niche)]
-    #[derive(Debug)] pub struct Cloaked(N16);
-
-    #[repr(transparent)]
-    #[derive(Debug)] pub struct Transparent(N16);
-
-    #[repr(transparent, no_niche)]
-    #[derive(Debug)] pub struct Shadowy(N16);
-}
-
-mod struct_param {
-    #[derive(Debug)] pub struct Visible<T>(T);
-
-    #[repr(no_niche)]
-    #[derive(Debug)] pub struct Cloaked<T>(T);
-
-    #[repr(transparent)]
-    #[derive(Debug)] pub struct Transparent<T>(T);
-
-    #[repr(transparent, no_niche)]
-    #[derive(Debug)] pub struct Shadowy<T>(T);
-}
-
-mod enum_inline {
-    use crate::two_fifty_six_variant_enum;
-    use std::num::{NonZeroU8 as N8, NonZeroU16 as N16};
-
-    #[derive(Debug)] pub enum Visible1 { _A(N16), }
-
-    #[repr(no_niche)]
-    #[derive(Debug)] pub enum Cloaked1 { _A(N16), }
-
-    // (N.B.: transparent enums must be univariant)
-    #[repr(transparent)]
-    #[derive(Debug)] pub enum Transparent { _A(N16), }
-
-    #[repr(transparent, no_niche)]
-    #[derive(Debug)] pub enum Shadowy { _A(N16), }
-
-    // including multivariant enums for completeness. Payload and
-    // number of variants (i.e. discriminant size) have been chosen so
-    // that layout including discriminant is 4 bytes, with no space in
-    // padding to hide another discrimnant from the surrounding
-    // context.
-    //
-    // (Note that multivariant enums cannot usefully expose a niche in
-    // general; this test is relying on that.)
-    two_fifty_six_variant_enum!(Visible2, N8);
-
-    two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2, N8);
-}
-
-mod enum_param {
-    use super::two_fifty_six_variant_enum;
-
-    #[derive(Debug)] pub enum Visible1<T> { _A(T), }
-
-    #[repr(no_niche)]
-    #[derive(Debug)] pub enum Cloaked1<T> { _A(T), }
-
-    // (N.B.: transparent enums must be univariant)
-    #[repr(transparent)]
-    #[derive(Debug)] pub enum Transparent<T> { _A(T), }
-
-    #[repr(transparent, no_niche)]
-    #[derive(Debug)] pub enum Shadowy<T> { _A(T), }
-
-    // including multivariant enums for completeness. Same notes apply
-    // here as above (assuming `T` is instantiated with `NonZeroU8`).
-    two_fifty_six_variant_enum!(Visible2<T>);
-
-    two_fifty_six_variant_enum!(#[repr(no_niche)] Cloaked2<T>);
-}
-
-fn main() {
-    // sanity-checks
-    assert_eq!(size_of::<struct_inline::Visible>(),               2);
-    assert_eq!(size_of::<struct_inline::Cloaked>(),               2);
-    assert_eq!(size_of::<struct_inline::Transparent>(),           2);
-    assert_eq!(size_of::<struct_inline::Shadowy>(),               2);
-
-    assert_eq!(size_of::<struct_param::Visible<NonZeroU16>>(), 2);
-    assert_eq!(size_of::<struct_param::Cloaked<NonZeroU16>>(), 2);
-    assert_eq!(size_of::<struct_param::Transparent<NonZeroU16>>(), 2);
-    assert_eq!(size_of::<struct_param::Shadowy<NonZeroU16>>(), 2);
-
-    assert_eq!(size_of::<enum_inline::Visible1>(),    2);
-    assert_eq!(size_of::<enum_inline::Cloaked1>(),    2);
-    assert_eq!(size_of::<enum_inline::Transparent>(), 2); // transparent enums are univariant
-    assert_eq!(size_of::<enum_inline::Shadowy>(),     2);
-    assert_eq!(size_of::<enum_inline::Visible2>(),    4);
-    assert_eq!(size_of::<enum_inline::Cloaked2>(),    4);
-
-    assert_eq!(size_of::<enum_param::Visible1<NonZeroU16>>(),    2);
-    assert_eq!(size_of::<enum_param::Cloaked1<NonZeroU16>>(),    2);
-    assert_eq!(size_of::<enum_param::Transparent<NonZeroU16>>(), 2);
-    assert_eq!(size_of::<enum_param::Shadowy<NonZeroU16>>(),     2);
-    assert_eq!(size_of::<enum_param::Visible2<NonZeroU8>>(),     4);
-    assert_eq!(size_of::<enum_param::Cloaked2<NonZeroU8>>(),     4);
-
-    // now the actual tests of no_niche: how do inputs above compose
-    // with `Option` type constructor. The cases with a `_+2` are the
-    // ones where no_niche fires.
-    assert_eq!(size_of::<Option<struct_inline::Visible>>(),       2);
-    assert_eq!(size_of::<Option<struct_inline::Cloaked>>(),       2+2);
-    assert_eq!(size_of::<Option<struct_inline::Transparent>>(),   2);
-    assert_eq!(size_of::<Option<struct_inline::Shadowy>>(),       2+2);
-
-    assert_eq!(size_of::<Option<struct_param::Visible<NonZeroU16>>>(),     2);
-    assert_eq!(size_of::<Option<struct_param::Cloaked<NonZeroU16>>>(),     2+2);
-    assert_eq!(size_of::<Option<struct_param::Transparent<NonZeroU16>>>(), 2);
-    assert_eq!(size_of::<Option<struct_param::Shadowy<NonZeroU16>>>(),     2+2);
-
-    assert_eq!(size_of::<Option<enum_inline::Visible1>>(),    2);
-    assert_eq!(size_of::<Option<enum_inline::Cloaked1>>(),    2+2);
-    assert_eq!(size_of::<Option<enum_inline::Transparent>>(), 2);
-    assert_eq!(size_of::<Option<enum_inline::Shadowy>>(),     2+2);
-    // cannot use niche of multivariant payload
-    assert_eq!(size_of::<Option<enum_inline::Visible2>>(),    4+2);
-    assert_eq!(size_of::<Option<enum_inline::Cloaked2>>(),    4+2);
-
-    assert_eq!(size_of::<Option<enum_param::Visible1<NonZeroU16>>>(),    2);
-    assert_eq!(size_of::<Option<enum_param::Cloaked1<NonZeroU16>>>(),    2+2);
-    assert_eq!(size_of::<Option<enum_param::Transparent<NonZeroU16>>>(), 2);
-    assert_eq!(size_of::<Option<enum_param::Shadowy<NonZeroU16>>>(),     2+2);
-    // cannot use niche of multivariant payload
-    assert_eq!(size_of::<Option<enum_param::Visible2<NonZeroU8>>>(),    4+2);
-    assert_eq!(size_of::<Option<enum_param::Cloaked2<NonZeroU8>>>(),    4+2);
-}
-
-macro two_fifty_six_variant_enum {
-    ($(#[$attr:meta])* $name:ident<$param:ident>) => {
-        #[derive(Debug)] $(#[$attr])*
-        pub enum $name<$param> {
-            _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
-            _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),
-            _V08($param, u16), _V09(u16, $param), _V0a($param, u16), _V0b(u16, $param),
-            _V0c($param, u16), _V0d(u16, $param), _V0e($param, u16), _V0f(u16, $param),
-
-            _V10($param, u16), _V11(u16, $param), _V12($param, u16), _V13(u16, $param),
-            _V14($param, u16), _V15(u16, $param), _V16($param, u16), _V17(u16, $param),
-            _V18($param, u16), _V19(u16, $param), _V1a($param, u16), _V1b(u16, $param),
-            _V1c($param, u16), _V1d(u16, $param), _V1e($param, u16), _V1f(u16, $param),
-
-            _V20($param, u16), _V21(u16, $param), _V22($param, u16), _V23(u16, $param),
-            _V24($param, u16), _V25(u16, $param), _V26($param, u16), _V27(u16, $param),
-            _V28($param, u16), _V29(u16, $param), _V2a($param, u16), _V2b(u16, $param),
-            _V2c($param, u16), _V2d(u16, $param), _V2e($param, u16), _V2f(u16, $param),
-
-            _V30($param, u16), _V31(u16, $param), _V32($param, u16), _V33(u16, $param),
-            _V34($param, u16), _V35(u16, $param), _V36($param, u16), _V37(u16, $param),
-            _V38($param, u16), _V39(u16, $param), _V3a($param, u16), _V3b(u16, $param),
-            _V3c($param, u16), _V3d(u16, $param), _V3e($param, u16), _V3f(u16, $param),
-
-            _V40($param, u16), _V41(u16, $param), _V42($param, u16), _V43(u16, $param),
-            _V44($param, u16), _V45(u16, $param), _V46($param, u16), _V47(u16, $param),
-            _V48($param, u16), _V49(u16, $param), _V4a($param, u16), _V4b(u16, $param),
-            _V4c($param, u16), _V4d(u16, $param), _V4e($param, u16), _V4f(u16, $param),
-
-            _V50($param, u16), _V51(u16, $param), _V52($param, u16), _V53(u16, $param),
-            _V54($param, u16), _V55(u16, $param), _V56($param, u16), _V57(u16, $param),
-            _V58($param, u16), _V59(u16, $param), _V5a($param, u16), _V5b(u16, $param),
-            _V5c($param, u16), _V5d(u16, $param), _V5e($param, u16), _V5f(u16, $param),
-
-            _V60($param, u16), _V61(u16, $param), _V62($param, u16), _V63(u16, $param),
-            _V64($param, u16), _V65(u16, $param), _V66($param, u16), _V67(u16, $param),
-            _V68($param, u16), _V69(u16, $param), _V6a($param, u16), _V6b(u16, $param),
-            _V6c($param, u16), _V6d(u16, $param), _V6e($param, u16), _V6f(u16, $param),
-
-            _V70($param, u16), _V71(u16, $param), _V72($param, u16), _V73(u16, $param),
-            _V74($param, u16), _V75(u16, $param), _V76($param, u16), _V77(u16, $param),
-            _V78($param, u16), _V79(u16, $param), _V7a($param, u16), _V7b(u16, $param),
-            _V7c($param, u16), _V7d(u16, $param), _V7e($param, u16), _V7f(u16, $param),
-
-            _V80($param, u16), _V81(u16, $param), _V82($param, u16), _V83(u16, $param),
-            _V84($param, u16), _V85(u16, $param), _V86($param, u16), _V87(u16, $param),
-            _V88($param, u16), _V89(u16, $param), _V8a($param, u16), _V8b(u16, $param),
-            _V8c($param, u16), _V8d(u16, $param), _V8e($param, u16), _V8f(u16, $param),
-
-            _V90($param, u16), _V91(u16, $param), _V92($param, u16), _V93(u16, $param),
-            _V94($param, u16), _V95(u16, $param), _V96($param, u16), _V97(u16, $param),
-            _V98($param, u16), _V99(u16, $param), _V9a($param, u16), _V9b(u16, $param),
-            _V9c($param, u16), _V9d(u16, $param), _V9e($param, u16), _V9f(u16, $param),
-
-            _Va0($param, u16), _Va1(u16, $param), _Va2($param, u16), _Va3(u16, $param),
-            _Va4($param, u16), _Va5(u16, $param), _Va6($param, u16), _Va7(u16, $param),
-            _Va8($param, u16), _Va9(u16, $param), _Vaa($param, u16), _Vab(u16, $param),
-            _Vac($param, u16), _Vad(u16, $param), _Vae($param, u16), _Vaf(u16, $param),
-
-            _Vb0($param, u16), _Vb1(u16, $param), _Vb2($param, u16), _Vb3(u16, $param),
-            _Vb4($param, u16), _Vb5(u16, $param), _Vb6($param, u16), _Vb7(u16, $param),
-            _Vb8($param, u16), _Vb9(u16, $param), _Vba($param, u16), _Vbb(u16, $param),
-            _Vbc($param, u16), _Vbd(u16, $param), _Vbe($param, u16), _Vbf(u16, $param),
-
-            _Vc0($param, u16), _Vc1(u16, $param), _Vc2($param, u16), _Vc3(u16, $param),
-            _Vc4($param, u16), _Vc5(u16, $param), _Vc6($param, u16), _Vc7(u16, $param),
-            _Vc8($param, u16), _Vc9(u16, $param), _Vca($param, u16), _Vcb(u16, $param),
-            _Vcc($param, u16), _Vcd(u16, $param), _Vce($param, u16), _Vcf(u16, $param),
-
-            _Vd0($param, u16), _Vd1(u16, $param), _Vd2($param, u16), _Vd3(u16, $param),
-            _Vd4($param, u16), _Vd5(u16, $param), _Vd6($param, u16), _Vd7(u16, $param),
-            _Vd8($param, u16), _Vd9(u16, $param), _Vda($param, u16), _Vdb(u16, $param),
-            _Vdc($param, u16), _Vdd(u16, $param), _Vde($param, u16), _Vdf(u16, $param),
-
-            _Ve0($param, u16), _Ve1(u16, $param), _Ve2($param, u16), _Ve3(u16, $param),
-            _Ve4($param, u16), _Ve5(u16, $param), _Ve6($param, u16), _Ve7(u16, $param),
-            _Ve8($param, u16), _Ve9(u16, $param), _Vea($param, u16), _Veb(u16, $param),
-            _Vec($param, u16), _Ved(u16, $param), _Vee($param, u16), _Vef(u16, $param),
-
-            _Vf0($param, u16), _Vf1(u16, $param), _Vf2($param, u16), _Vf3(u16, $param),
-            _Vf4($param, u16), _Vf5(u16, $param), _Vf6($param, u16), _Vf7(u16, $param),
-            _Vf8($param, u16), _Vf9(u16, $param), _Vfa($param, u16), _Vfb(u16, $param),
-            _Vfc($param, u16), _Vfd(u16, $param), _Vfe($param, u16), _Vff(u16, $param),
-        }
-    },
-
-    ($(#[$attr:meta])* $name:ident, $param:ty) => {
-        #[derive(Debug)] $(#[$attr])*
-        pub enum $name {
-            _V00($param, u16), _V01(u16, $param), _V02($param, u16), _V03(u16, $param),
-            _V04($param, u16), _V05(u16, $param), _V06($param, u16), _V07(u16, $param),
-            _V08($param, u16), _V09(u16, $param), _V0a($param, u16), _V0b(u16, $param),
-            _V0c($param, u16), _V0d(u16, $param), _V0e($param, u16), _V0f(u16, $param),
-
-            _V10($param, u16), _V11(u16, $param), _V12($param, u16), _V13(u16, $param),
-            _V14($param, u16), _V15(u16, $param), _V16($param, u16), _V17(u16, $param),
-            _V18($param, u16), _V19(u16, $param), _V1a($param, u16), _V1b(u16, $param),
-            _V1c($param, u16), _V1d(u16, $param), _V1e($param, u16), _V1f(u16, $param),
-
-            _V20($param, u16), _V21(u16, $param), _V22($param, u16), _V23(u16, $param),
-            _V24($param, u16), _V25(u16, $param), _V26($param, u16), _V27(u16, $param),
-            _V28($param, u16), _V29(u16, $param), _V2a($param, u16), _V2b(u16, $param),
-            _V2c($param, u16), _V2d(u16, $param), _V2e($param, u16), _V2f(u16, $param),
-
-            _V30($param, u16), _V31(u16, $param), _V32($param, u16), _V33(u16, $param),
-            _V34($param, u16), _V35(u16, $param), _V36($param, u16), _V37(u16, $param),
-            _V38($param, u16), _V39(u16, $param), _V3a($param, u16), _V3b(u16, $param),
-            _V3c($param, u16), _V3d(u16, $param), _V3e($param, u16), _V3f(u16, $param),
-
-            _V40($param, u16), _V41(u16, $param), _V42($param, u16), _V43(u16, $param),
-            _V44($param, u16), _V45(u16, $param), _V46($param, u16), _V47(u16, $param),
-            _V48($param, u16), _V49(u16, $param), _V4a($param, u16), _V4b(u16, $param),
-            _V4c($param, u16), _V4d(u16, $param), _V4e($param, u16), _V4f(u16, $param),
-
-            _V50($param, u16), _V51(u16, $param), _V52($param, u16), _V53(u16, $param),
-            _V54($param, u16), _V55(u16, $param), _V56($param, u16), _V57(u16, $param),
-            _V58($param, u16), _V59(u16, $param), _V5a($param, u16), _V5b(u16, $param),
-            _V5c($param, u16), _V5d(u16, $param), _V5e($param, u16), _V5f(u16, $param),
-
-            _V60($param, u16), _V61(u16, $param), _V62($param, u16), _V63(u16, $param),
-            _V64($param, u16), _V65(u16, $param), _V66($param, u16), _V67(u16, $param),
-            _V68($param, u16), _V69(u16, $param), _V6a($param, u16), _V6b(u16, $param),
-            _V6c($param, u16), _V6d(u16, $param), _V6e($param, u16), _V6f(u16, $param),
-
-            _V70($param, u16), _V71(u16, $param), _V72($param, u16), _V73(u16, $param),
-            _V74($param, u16), _V75(u16, $param), _V76($param, u16), _V77(u16, $param),
-            _V78($param, u16), _V79(u16, $param), _V7a($param, u16), _V7b(u16, $param),
-            _V7c($param, u16), _V7d(u16, $param), _V7e($param, u16), _V7f(u16, $param),
-
-            _V80($param, u16), _V81(u16, $param), _V82($param, u16), _V83(u16, $param),
-            _V84($param, u16), _V85(u16, $param), _V86($param, u16), _V87(u16, $param),
-            _V88($param, u16), _V89(u16, $param), _V8a($param, u16), _V8b(u16, $param),
-            _V8c($param, u16), _V8d(u16, $param), _V8e($param, u16), _V8f(u16, $param),
-
-            _V90($param, u16), _V91(u16, $param), _V92($param, u16), _V93(u16, $param),
-            _V94($param, u16), _V95(u16, $param), _V96($param, u16), _V97(u16, $param),
-            _V98($param, u16), _V99(u16, $param), _V9a($param, u16), _V9b(u16, $param),
-            _V9c($param, u16), _V9d(u16, $param), _V9e($param, u16), _V9f(u16, $param),
-
-            _Va0($param, u16), _Va1(u16, $param), _Va2($param, u16), _Va3(u16, $param),
-            _Va4($param, u16), _Va5(u16, $param), _Va6($param, u16), _Va7(u16, $param),
-            _Va8($param, u16), _Va9(u16, $param), _Vaa($param, u16), _Vab(u16, $param),
-            _Vac($param, u16), _Vad(u16, $param), _Vae($param, u16), _Vaf(u16, $param),
-
-            _Vb0($param, u16), _Vb1(u16, $param), _Vb2($param, u16), _Vb3(u16, $param),
-            _Vb4($param, u16), _Vb5(u16, $param), _Vb6($param, u16), _Vb7(u16, $param),
-            _Vb8($param, u16), _Vb9(u16, $param), _Vba($param, u16), _Vbb(u16, $param),
-            _Vbc($param, u16), _Vbd(u16, $param), _Vbe($param, u16), _Vbf(u16, $param),
-
-            _Vc0($param, u16), _Vc1(u16, $param), _Vc2($param, u16), _Vc3(u16, $param),
-            _Vc4($param, u16), _Vc5(u16, $param), _Vc6($param, u16), _Vc7(u16, $param),
-            _Vc8($param, u16), _Vc9(u16, $param), _Vca($param, u16), _Vcb(u16, $param),
-            _Vcc($param, u16), _Vcd(u16, $param), _Vce($param, u16), _Vcf(u16, $param),
-
-            _Vd0($param, u16), _Vd1(u16, $param), _Vd2($param, u16), _Vd3(u16, $param),
-            _Vd4($param, u16), _Vd5(u16, $param), _Vd6($param, u16), _Vd7(u16, $param),
-            _Vd8($param, u16), _Vd9(u16, $param), _Vda($param, u16), _Vdb(u16, $param),
-            _Vdc($param, u16), _Vdd(u16, $param), _Vde($param, u16), _Vdf(u16, $param),
-
-            _Ve0($param, u16), _Ve1(u16, $param), _Ve2($param, u16), _Ve3(u16, $param),
-            _Ve4($param, u16), _Ve5(u16, $param), _Ve6($param, u16), _Ve7(u16, $param),
-            _Ve8($param, u16), _Ve9(u16, $param), _Vea($param, u16), _Veb(u16, $param),
-            _Vec($param, u16), _Ved(u16, $param), _Vee($param, u16), _Vef(u16, $param),
-
-            _Vf0($param, u16), _Vf1(u16, $param), _Vf2($param, u16), _Vf3(u16, $param),
-            _Vf4($param, u16), _Vf5(u16, $param), _Vf6($param, u16), _Vf7(u16, $param),
-            _Vf8($param, u16), _Vf9(u16, $param), _Vfa($param, u16), _Vfb(u16, $param),
-            _Vfc($param, u16), _Vfd(u16, $param), _Vfe($param, u16), _Vff(u16, $param),
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/non_copy_const.rs b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
index a1ef32ae60805..6bce5fbd4c1fe 100644
--- a/src/tools/clippy/clippy_lints/src/non_copy_const.rs
+++ b/src/tools/clippy/clippy_lints/src/non_copy_const.rs
@@ -148,7 +148,7 @@ fn is_value_unfrozen_raw<'tcx>(
         match val.ty().kind() {
             // the fact that we have to dig into every structs to search enums
             // leads us to the point checking `UnsafeCell` directly is the only option.
-            ty::Adt(ty_def, ..) if Some(ty_def.did()) == cx.tcx.lang_items().unsafe_cell_type() => true,
+            ty::Adt(ty_def, ..) if ty_def.is_unsafe_cell() => true,
             ty::Array(..) | ty::Adt(..) | ty::Tuple(..) => {
                 let val = cx.tcx.destructure_mir_constant(cx.param_env, val);
                 val.fields.iter().any(|field| inner(cx, *field))

From 8d9f609d0d4465285ac9f0257c706c559644fef5 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Thu, 7 Jul 2022 11:19:57 +0000
Subject: [PATCH 02/19] Comment update

---
 compiler/rustc_lint/src/types.rs | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 4ed9d9b27b297..aca481df2e113 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -703,8 +703,7 @@ fn ty_is_known_nonnull<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>, mode: CItemKi
                 return true;
             }
 
-            // Types with a `#[repr(no_niche)]` attribute have their niche hidden.
-            // The attribute is used by the UnsafeCell for example (the only use so far).
+            // `UnsafeCell` has its niche hidden.
             if def.is_unsafe_cell() {
                 return false;
             }

From 4bfba76a3da28d780be3cb31fd6269b8bc6183df Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Fri, 8 Jul 2022 14:28:19 +0000
Subject: [PATCH 03/19] Add tests for libstd types

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 22 ++++++++++++++-----
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index eb65756a5f643..f6a8e0de27ad0 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -5,9 +5,10 @@
 
 // run-pass
 
-use std::cell::UnsafeCell;
+use std::cell::{UnsafeCell, RefCell, Cell};
 use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
+use std::sync::{Mutex, RwLock};
 
 struct Wrapper<T>(T);
 
@@ -18,12 +19,23 @@ struct NoNiche<T>(UnsafeCell<T>);
 
 fn main() {
     assert_eq!(size_of::<Option<Wrapper<u32>>>(),     8);
-    assert_eq!(size_of::<Option<Wrapper<N32>>>(),     4);
+    assert_eq!(size_of::<Option<Wrapper<N32>>>(),     4); // (✓ niche opt)
     assert_eq!(size_of::<Option<Transparent<u32>>>(), 8);
-    assert_eq!(size_of::<Option<Transparent<N32>>>(), 4);
+    assert_eq!(size_of::<Option<Transparent<N32>>>(), 4); // (✓ niche opt)
     assert_eq!(size_of::<Option<NoNiche<u32>>>(),     8);
-    assert_eq!(size_of::<Option<NoNiche<N32>>>(),     8);
+    assert_eq!(size_of::<Option<NoNiche<N32>>>(),     8); // (✗ niche opt)
 
     assert_eq!(size_of::<Option<UnsafeCell<u32>>>(),  8);
-    assert_eq!(size_of::<Option<UnsafeCell<N32>>>(),  8);
+    assert_eq!(size_of::<Option<UnsafeCell<N32>>>(),  8); // (✗ niche opt)
+
+    assert_eq!(size_of::<       UnsafeCell<&()> >(), 8);
+    assert_eq!(size_of::<Option<UnsafeCell<&()>>>(), 16); // (✗ niche opt)
+    assert_eq!(size_of::<             Cell<&()> >(), 8);
+    assert_eq!(size_of::<Option<      Cell<&()>>>(), 16); // (✗ niche opt)
+    assert_eq!(size_of::<          RefCell<&()> >(), 16);
+    assert_eq!(size_of::<Option<   RefCell<&()>>>(), 24); // (✗ niche opt)
+    assert_eq!(size_of::<           RwLock<&()> >(), 24);
+    assert_eq!(size_of::<Option<    RwLock<&()>>>(), 32); // (✗ niche opt)
+    assert_eq!(size_of::<            Mutex<&()> >(), 16);
+    assert_eq!(size_of::<Option<     Mutex<&()>>>(), 24); // (✗ niche opt)
 }

From 69b1b3c011143b573c904f0759d187588cc457c0 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Fri, 8 Jul 2022 14:47:25 +0000
Subject: [PATCH 04/19] Create a custom layout path for UnsafeCell instead of
 piggy backing on the layout_scalar_valid_range logic

---
 compiler/rustc_middle/src/ty/layout.rs        | 60 ++++++++++++-------
 src/test/ui/layout/unsafe-cell-hides-niche.rs |  9 +++
 2 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index cef8a1dba7f8d..6d87328ef5daa 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1076,6 +1076,34 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
 
                     let mut st = self.univariant_uninterned(ty, &variants[v], &def.repr(), kind)?;
                     st.variants = Variants::Single { index: v };
+
+                    if def.is_unsafe_cell() {
+                        let fill = |scalar: &mut _| match scalar {
+                            Scalar::Initialized { value, valid_range } => {
+                                *valid_range = WrappingRange::full(value.size(dl))
+                            }
+                            // Already doesn't have any niches
+                            Scalar::Union { .. } => {}
+                        };
+                        match &mut st.abi {
+                            Abi::Uninhabited => {}
+                            Abi::Scalar(scalar) => fill(scalar),
+                            Abi::ScalarPair(a, b) => {
+                                fill(a);
+                                fill(b);
+                            }
+                            Abi::Vector { element, count: _ } => {
+                                // Until we support types other than floats and integers in SIMD,
+                                // `element` must already be a full for its range, so there's nothing to
+                                // do here.
+                                assert!(element.is_always_valid(dl));
+                            }
+                            Abi::Aggregate { sized: _ } => {}
+                        }
+                        st.largest_niche = None;
+                        return Ok(tcx.intern_layout(st));
+                    }
+
                     let (start, end) = self.tcx.layout_scalar_valid_range(def.did());
                     match st.abi {
                         Abi::Scalar(ref mut scalar) | Abi::ScalarPair(ref mut scalar, _) => {
@@ -1102,29 +1130,19 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 assert!(valid_range.end >= end);
                                 valid_range.end = end;
                             }
-                            if def.is_unsafe_cell() {
-                                match scalar {
-                                    Scalar::Initialized { value, valid_range } => {
-                                        *valid_range = WrappingRange::full(value.size(dl))
-                                    }
-                                    // Already doesn't have any niches
-                                    Scalar::Union { .. } => {}
-                                }
-                                st.largest_niche = None;
-                            } else {
-                                // Update `largest_niche` if we have introduced a larger niche.
-                                let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
-                                if let Some(niche) = niche {
-                                    match st.largest_niche {
-                                        Some(largest_niche) => {
-                                            // Replace the existing niche even if they're equal,
-                                            // because this one is at a lower offset.
-                                            if largest_niche.available(dl) <= niche.available(dl) {
-                                                st.largest_niche = Some(niche);
-                                            }
+
+                            // Update `largest_niche` if we have introduced a larger niche.
+                            let niche = Niche::from_scalar(dl, Size::ZERO, *scalar);
+                            if let Some(niche) = niche {
+                                match st.largest_niche {
+                                    Some(largest_niche) => {
+                                        // Replace the existing niche even if they're equal,
+                                        // because this one is at a lower offset.
+                                        if largest_niche.available(dl) <= niche.available(dl) {
+                                            st.largest_niche = Some(niche);
                                         }
-                                        None => st.largest_niche = Some(niche),
                                     }
+                                    None => st.largest_niche = Some(niche),
                                 }
                             }
                         }
diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index f6a8e0de27ad0..2d3bb1d23c093 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -38,4 +38,13 @@ fn main() {
     assert_eq!(size_of::<Option<    RwLock<&()>>>(), 32); // (✗ niche opt)
     assert_eq!(size_of::<            Mutex<&()> >(), 16);
     assert_eq!(size_of::<Option<     Mutex<&()>>>(), 24); // (✗ niche opt)
+
+    assert_eq!(size_of::<       UnsafeCell<&[i32]> >(), 16);
+    assert_eq!(size_of::<Option<UnsafeCell<&[i32]>>>(), 24); // (✗ niche opt)
+    assert_eq!(size_of::<       UnsafeCell<(&(), &())> >(), 16);
+    assert_eq!(size_of::<Option<UnsafeCell<(&(), &())>>>(), 24); // (✗ niche opt)
+
+    trait Trait {}
+    assert_eq!(size_of::<       UnsafeCell<&dyn Trait> >(), 16);
+    assert_eq!(size_of::<Option<UnsafeCell<&dyn Trait>>>(), 24); // (✗ niche opt)
 }

From 423915590b08896ecc845b8b22910cb98c4c7e36 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:11:28 +0000
Subject: [PATCH 05/19] More obvious closure name

---
 compiler/rustc_middle/src/ty/layout.rs | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 6d87328ef5daa..8cbc0169bc7a4 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1078,7 +1078,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                     st.variants = Variants::Single { index: v };
 
                     if def.is_unsafe_cell() {
-                        let fill = |scalar: &mut _| match scalar {
+                        let hide_niches = |scalar: &mut _| match scalar {
                             Scalar::Initialized { value, valid_range } => {
                                 *valid_range = WrappingRange::full(value.size(dl))
                             }
@@ -1087,10 +1087,10 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                         };
                         match &mut st.abi {
                             Abi::Uninhabited => {}
-                            Abi::Scalar(scalar) => fill(scalar),
+                            Abi::Scalar(scalar) => hide_niches(scalar),
                             Abi::ScalarPair(a, b) => {
-                                fill(a);
-                                fill(b);
+                                hide_niches(a);
+                                hide_niches(b);
                             }
                             Abi::Vector { element, count: _ } => {
                                 // Until we support types other than floats and integers in SIMD,

From 984db78d771ec67d781e954da759dbea8667197a Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:25:41 +0000
Subject: [PATCH 06/19] Hide niches in SIMD types, too

---
 compiler/rustc_middle/src/ty/layout.rs        | 7 +------
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 8 ++++++++
 2 files changed, 9 insertions(+), 6 deletions(-)

diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index 8cbc0169bc7a4..1ed41db099ca0 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -1092,12 +1092,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
                                 hide_niches(a);
                                 hide_niches(b);
                             }
-                            Abi::Vector { element, count: _ } => {
-                                // Until we support types other than floats and integers in SIMD,
-                                // `element` must already be a full for its range, so there's nothing to
-                                // do here.
-                                assert!(element.is_always_valid(dl));
-                            }
+                            Abi::Vector { element, count: _ } => hide_niches(element),
                             Abi::Aggregate { sized: _ } => {}
                         }
                         st.largest_niche = None;
diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 2d3bb1d23c093..bb2156a5da727 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -5,6 +5,8 @@
 
 // run-pass
 
+#![feature(repr_simd)]
+
 use std::cell::{UnsafeCell, RefCell, Cell};
 use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
@@ -47,4 +49,10 @@ fn main() {
     trait Trait {}
     assert_eq!(size_of::<       UnsafeCell<&dyn Trait> >(), 16);
     assert_eq!(size_of::<Option<UnsafeCell<&dyn Trait>>>(), 24); // (✗ niche opt)
+
+    #[repr(simd)]
+    pub struct Vec4<T>([T; 4]);
+
+    assert_eq!(size_of::<       UnsafeCell<Vec4<N32>> >(), 16);
+    assert_eq!(size_of::<Option<UnsafeCell<Vec4<N32>>>>(), 32); // (✗ niche opt)
 }

From 3f4cf59323304a2e785aba564a6eb3bd473d5499 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:29:02 +0000
Subject: [PATCH 07/19] Move checks to compile-time

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index bb2156a5da727..385472ac88a7d 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -3,7 +3,7 @@
 // test checks that an `Option<UnsafeCell<NonZeroU32>>` has the same
 // size in memory as an `Option<UnsafeCell<u32>>` (namely, 8 bytes).
 
-// run-pass
+// check-pass
 
 #![feature(repr_simd)]
 
@@ -19,6 +19,13 @@ struct Transparent<T>(T);
 
 struct NoNiche<T>(UnsafeCell<T>);
 
+// Overwriting the runtime assertion and making it a compile-time assertion
+macro_rules! assert_eq {
+    ($a:expr, $b:literal) => {{
+        const _: () = assert!($a == $b);
+    }};
+}
+
 fn main() {
     assert_eq!(size_of::<Option<Wrapper<u32>>>(),     8);
     assert_eq!(size_of::<Option<Wrapper<N32>>>(),     4); // (✓ niche opt)

From af8536e32ff8840bb41c65a438ccf33568548e02 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:30:50 +0000
Subject: [PATCH 08/19] Simplify assertion macro

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 57 +++++++++----------
 1 file changed, 28 insertions(+), 29 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 385472ac88a7d..f5c1fe1320c56 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -8,7 +8,6 @@
 #![feature(repr_simd)]
 
 use std::cell::{UnsafeCell, RefCell, Cell};
-use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
 use std::sync::{Mutex, RwLock};
 
@@ -21,45 +20,45 @@ struct NoNiche<T>(UnsafeCell<T>);
 
 // Overwriting the runtime assertion and making it a compile-time assertion
 macro_rules! assert_eq {
-    ($a:expr, $b:literal) => {{
-        const _: () = assert!($a == $b);
+    ($a:ty, $b:literal) => {{
+        const _: () = assert!(std::mem::size_of::<$a>() == $b);
     }};
 }
 
 fn main() {
-    assert_eq!(size_of::<Option<Wrapper<u32>>>(),     8);
-    assert_eq!(size_of::<Option<Wrapper<N32>>>(),     4); // (✓ niche opt)
-    assert_eq!(size_of::<Option<Transparent<u32>>>(), 8);
-    assert_eq!(size_of::<Option<Transparent<N32>>>(), 4); // (✓ niche opt)
-    assert_eq!(size_of::<Option<NoNiche<u32>>>(),     8);
-    assert_eq!(size_of::<Option<NoNiche<N32>>>(),     8); // (✗ niche opt)
+    assert_eq!(Option<Wrapper<u32>>,     8);
+    assert_eq!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
+    assert_eq!(Option<Transparent<u32>>, 8);
+    assert_eq!(Option<Transparent<N32>>, 4); // (✓ niche opt)
+    assert_eq!(Option<NoNiche<u32>>,     8);
+    assert_eq!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
 
-    assert_eq!(size_of::<Option<UnsafeCell<u32>>>(),  8);
-    assert_eq!(size_of::<Option<UnsafeCell<N32>>>(),  8); // (✗ niche opt)
+    assert_eq!(Option<UnsafeCell<u32>>,  8);
+    assert_eq!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
 
-    assert_eq!(size_of::<       UnsafeCell<&()> >(), 8);
-    assert_eq!(size_of::<Option<UnsafeCell<&()>>>(), 16); // (✗ niche opt)
-    assert_eq!(size_of::<             Cell<&()> >(), 8);
-    assert_eq!(size_of::<Option<      Cell<&()>>>(), 16); // (✗ niche opt)
-    assert_eq!(size_of::<          RefCell<&()> >(), 16);
-    assert_eq!(size_of::<Option<   RefCell<&()>>>(), 24); // (✗ niche opt)
-    assert_eq!(size_of::<           RwLock<&()> >(), 24);
-    assert_eq!(size_of::<Option<    RwLock<&()>>>(), 32); // (✗ niche opt)
-    assert_eq!(size_of::<            Mutex<&()> >(), 16);
-    assert_eq!(size_of::<Option<     Mutex<&()>>>(), 24); // (✗ niche opt)
+    assert_eq!(       UnsafeCell<&()> , 8);
+    assert_eq!(Option<UnsafeCell<&()>>, 16); // (✗ niche opt)
+    assert_eq!(             Cell<&()> , 8);
+    assert_eq!(Option<      Cell<&()>>, 16); // (✗ niche opt)
+    assert_eq!(          RefCell<&()> , 16);
+    assert_eq!(Option<   RefCell<&()>>, 24); // (✗ niche opt)
+    assert_eq!(           RwLock<&()> , 24);
+    assert_eq!(Option<    RwLock<&()>>, 32); // (✗ niche opt)
+    assert_eq!(            Mutex<&()> , 16);
+    assert_eq!(Option<     Mutex<&()>>, 24); // (✗ niche opt)
 
-    assert_eq!(size_of::<       UnsafeCell<&[i32]> >(), 16);
-    assert_eq!(size_of::<Option<UnsafeCell<&[i32]>>>(), 24); // (✗ niche opt)
-    assert_eq!(size_of::<       UnsafeCell<(&(), &())> >(), 16);
-    assert_eq!(size_of::<Option<UnsafeCell<(&(), &())>>>(), 24); // (✗ niche opt)
+    assert_eq!(       UnsafeCell<&[i32]> , 16);
+    assert_eq!(Option<UnsafeCell<&[i32]>>, 24); // (✗ niche opt)
+    assert_eq!(       UnsafeCell<(&(), &())> , 16);
+    assert_eq!(Option<UnsafeCell<(&(), &())>>, 24); // (✗ niche opt)
 
     trait Trait {}
-    assert_eq!(size_of::<       UnsafeCell<&dyn Trait> >(), 16);
-    assert_eq!(size_of::<Option<UnsafeCell<&dyn Trait>>>(), 24); // (✗ niche opt)
+    assert_eq!(       UnsafeCell<&dyn Trait> , 16);
+    assert_eq!(Option<UnsafeCell<&dyn Trait>>, 24); // (✗ niche opt)
 
     #[repr(simd)]
     pub struct Vec4<T>([T; 4]);
 
-    assert_eq!(size_of::<       UnsafeCell<Vec4<N32>> >(), 16);
-    assert_eq!(size_of::<Option<UnsafeCell<Vec4<N32>>>>(), 32); // (✗ niche opt)
+    assert_eq!(       UnsafeCell<Vec4<N32>> , 16);
+    assert_eq!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)
 }

From fef596f6a243d311dc50b50f83f8339e326f1f66 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:31:21 +0000
Subject: [PATCH 09/19] Rename assertion macro

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 54 +++++++++----------
 1 file changed, 27 insertions(+), 27 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index f5c1fe1320c56..7fb55d8219ef8 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -19,46 +19,46 @@ struct Transparent<T>(T);
 struct NoNiche<T>(UnsafeCell<T>);
 
 // Overwriting the runtime assertion and making it a compile-time assertion
-macro_rules! assert_eq {
+macro_rules! assert_size {
     ($a:ty, $b:literal) => {{
         const _: () = assert!(std::mem::size_of::<$a>() == $b);
     }};
 }
 
 fn main() {
-    assert_eq!(Option<Wrapper<u32>>,     8);
-    assert_eq!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
-    assert_eq!(Option<Transparent<u32>>, 8);
-    assert_eq!(Option<Transparent<N32>>, 4); // (✓ niche opt)
-    assert_eq!(Option<NoNiche<u32>>,     8);
-    assert_eq!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
+    assert_size!(Option<Wrapper<u32>>,     8);
+    assert_size!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
+    assert_size!(Option<Transparent<u32>>, 8);
+    assert_size!(Option<Transparent<N32>>, 4); // (✓ niche opt)
+    assert_size!(Option<NoNiche<u32>>,     8);
+    assert_size!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
 
-    assert_eq!(Option<UnsafeCell<u32>>,  8);
-    assert_eq!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
+    assert_size!(Option<UnsafeCell<u32>>,  8);
+    assert_size!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
 
-    assert_eq!(       UnsafeCell<&()> , 8);
-    assert_eq!(Option<UnsafeCell<&()>>, 16); // (✗ niche opt)
-    assert_eq!(             Cell<&()> , 8);
-    assert_eq!(Option<      Cell<&()>>, 16); // (✗ niche opt)
-    assert_eq!(          RefCell<&()> , 16);
-    assert_eq!(Option<   RefCell<&()>>, 24); // (✗ niche opt)
-    assert_eq!(           RwLock<&()> , 24);
-    assert_eq!(Option<    RwLock<&()>>, 32); // (✗ niche opt)
-    assert_eq!(            Mutex<&()> , 16);
-    assert_eq!(Option<     Mutex<&()>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<&()> , 8);
+    assert_size!(Option<UnsafeCell<&()>>, 16); // (✗ niche opt)
+    assert_size!(             Cell<&()> , 8);
+    assert_size!(Option<      Cell<&()>>, 16); // (✗ niche opt)
+    assert_size!(          RefCell<&()> , 16);
+    assert_size!(Option<   RefCell<&()>>, 24); // (✗ niche opt)
+    assert_size!(           RwLock<&()> , 24);
+    assert_size!(Option<    RwLock<&()>>, 32); // (✗ niche opt)
+    assert_size!(            Mutex<&()> , 16);
+    assert_size!(Option<     Mutex<&()>>, 24); // (✗ niche opt)
 
-    assert_eq!(       UnsafeCell<&[i32]> , 16);
-    assert_eq!(Option<UnsafeCell<&[i32]>>, 24); // (✗ niche opt)
-    assert_eq!(       UnsafeCell<(&(), &())> , 16);
-    assert_eq!(Option<UnsafeCell<(&(), &())>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<&[i32]> , 16);
+    assert_size!(Option<UnsafeCell<&[i32]>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<(&(), &())> , 16);
+    assert_size!(Option<UnsafeCell<(&(), &())>>, 24); // (✗ niche opt)
 
     trait Trait {}
-    assert_eq!(       UnsafeCell<&dyn Trait> , 16);
-    assert_eq!(Option<UnsafeCell<&dyn Trait>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<&dyn Trait> , 16);
+    assert_size!(Option<UnsafeCell<&dyn Trait>>, 24); // (✗ niche opt)
 
     #[repr(simd)]
     pub struct Vec4<T>([T; 4]);
 
-    assert_eq!(       UnsafeCell<Vec4<N32>> , 16);
-    assert_eq!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)
+    assert_size!(       UnsafeCell<Vec4<N32>> , 16);
+    assert_size!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)
 }

From 9a204509d2fe9d0ea72cb79ed6e341de7a3bcacb Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:34:01 +0000
Subject: [PATCH 10/19] Show sizes in error output

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 7fb55d8219ef8..21ff0cb1e5527 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -18,10 +18,12 @@ struct Transparent<T>(T);
 
 struct NoNiche<T>(UnsafeCell<T>);
 
+struct Size<const S: usize>;
+
 // Overwriting the runtime assertion and making it a compile-time assertion
 macro_rules! assert_size {
     ($a:ty, $b:literal) => {{
-        const _: () = assert!(std::mem::size_of::<$a>() == $b);
+        const _: Size::<$b> = Size::<{std::mem::size_of::<$a>()}>;
     }};
 }
 

From fcd7207d0e5ab4a9598e3b6caf6248134e5f95d6 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 10:43:47 +0000
Subject: [PATCH 11/19] Make tests work on 32 bit and 64 bit

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 41 ++++++++++---------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 21ff0cb1e5527..2833f49a27bf6 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -8,6 +8,7 @@
 #![feature(repr_simd)]
 
 use std::cell::{UnsafeCell, RefCell, Cell};
+use std::mem::size_of;
 use std::num::NonZeroU32 as N32;
 use std::sync::{Mutex, RwLock};
 
@@ -22,11 +23,13 @@ struct Size<const S: usize>;
 
 // Overwriting the runtime assertion and making it a compile-time assertion
 macro_rules! assert_size {
-    ($a:ty, $b:literal) => {{
-        const _: Size::<$b> = Size::<{std::mem::size_of::<$a>()}>;
+    ($a:ty, $b:expr) => {{
+        const _: Size::<{$b}> = Size::<{size_of::<$a>()}>;
     }};
 }
 
+const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
+
 fn main() {
     assert_size!(Option<Wrapper<u32>>,     8);
     assert_size!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
@@ -38,25 +41,25 @@ fn main() {
     assert_size!(Option<UnsafeCell<u32>>,  8);
     assert_size!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
 
-    assert_size!(       UnsafeCell<&()> , 8);
-    assert_size!(Option<UnsafeCell<&()>>, 16); // (✗ niche opt)
-    assert_size!(             Cell<&()> , 8);
-    assert_size!(Option<      Cell<&()>>, 16); // (✗ niche opt)
-    assert_size!(          RefCell<&()> , 16);
-    assert_size!(Option<   RefCell<&()>>, 24); // (✗ niche opt)
-    assert_size!(           RwLock<&()> , 24);
-    assert_size!(Option<    RwLock<&()>>, 32); // (✗ niche opt)
-    assert_size!(            Mutex<&()> , 16);
-    assert_size!(Option<     Mutex<&()>>, 24); // (✗ niche opt)
-
-    assert_size!(       UnsafeCell<&[i32]> , 16);
-    assert_size!(Option<UnsafeCell<&[i32]>>, 24); // (✗ niche opt)
-    assert_size!(       UnsafeCell<(&(), &())> , 16);
-    assert_size!(Option<UnsafeCell<(&(), &())>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<&()> , PTR_SIZE);
+    assert_size!(Option<UnsafeCell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
+    assert_size!(             Cell<&()> , PTR_SIZE);
+    assert_size!(Option<      Cell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
+    assert_size!(          RefCell<&()> , PTR_SIZE * 2);
+    assert_size!(Option<   RefCell<&()>>, PTR_SIZE * 3); // (✗ niche opt)
+    assert_size!(           RwLock<&()> , if cfg!(target_pointer_width = "32") { 16 } else { 24 });
+    assert_size!(Option<    RwLock<&()>>, if cfg!(target_pointer_width = "32") { 20 } else { 32 }); // (✗ niche opt)
+    assert_size!(            Mutex<&()> , if cfg!(target_pointer_width = "32") { 12 } else { 16 });
+    assert_size!(Option<     Mutex<&()>>, if cfg!(target_pointer_width = "32") { 16 } else { 24 }); // (✗ niche opt)
+
+    assert_size!(       UnsafeCell<&[i32]> , PTR_SIZE * 2);
+    assert_size!(Option<UnsafeCell<&[i32]>>, PTR_SIZE * 3); // (✗ niche opt)
+    assert_size!(       UnsafeCell<(&(), &())> , PTR_SIZE * 2);
+    assert_size!(Option<UnsafeCell<(&(), &())>>, PTR_SIZE * 3); // (✗ niche opt)
 
     trait Trait {}
-    assert_size!(       UnsafeCell<&dyn Trait> , 16);
-    assert_size!(Option<UnsafeCell<&dyn Trait>>, 24); // (✗ niche opt)
+    assert_size!(       UnsafeCell<&dyn Trait> , PTR_SIZE * 2);
+    assert_size!(Option<UnsafeCell<&dyn Trait>>, PTR_SIZE * 3); // (✗ niche opt)
 
     #[repr(simd)]
     pub struct Vec4<T>([T; 4]);

From 8440208eb13ec1f680592b9a7793a67f2b1be15e Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 11:07:03 +0000
Subject: [PATCH 12/19] tidy

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 20 +++++++++++++++----
 1 file changed, 16 insertions(+), 4 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 2833f49a27bf6..1d0e1fce178d0 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -47,10 +47,22 @@ fn main() {
     assert_size!(Option<      Cell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
     assert_size!(          RefCell<&()> , PTR_SIZE * 2);
     assert_size!(Option<   RefCell<&()>>, PTR_SIZE * 3); // (✗ niche opt)
-    assert_size!(           RwLock<&()> , if cfg!(target_pointer_width = "32") { 16 } else { 24 });
-    assert_size!(Option<    RwLock<&()>>, if cfg!(target_pointer_width = "32") { 20 } else { 32 }); // (✗ niche opt)
-    assert_size!(            Mutex<&()> , if cfg!(target_pointer_width = "32") { 12 } else { 16 });
-    assert_size!(Option<     Mutex<&()>>, if cfg!(target_pointer_width = "32") { 16 } else { 24 }); // (✗ niche opt)
+    assert_size!(
+        RwLock<&()>,
+        if cfg!(target_pointer_width = "32") { 16 } else { 24 }
+    );
+    assert_size!(
+        Option<RwLock<&()>>,
+        if cfg!(target_pointer_width = "32") { 20 } else { 32 }
+    ); // (✗ niche opt)
+    assert_size!(
+        Mutex<&()> ,
+        if cfg!(target_pointer_width = "32") { 12 } else { 16 }
+    );
+    assert_size!(
+        Option<Mutex<&()>>,
+        if cfg!(target_pointer_width = "32") { 16 } else { 24 }
+    ); // (✗ niche opt)
 
     assert_size!(       UnsafeCell<&[i32]> , PTR_SIZE * 2);
     assert_size!(Option<UnsafeCell<&[i32]>>, PTR_SIZE * 3); // (✗ niche opt)

From d935c70afa464dcf16db532e39ae53621debd096 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 14:16:14 +0000
Subject: [PATCH 13/19] Don't allow accidental runtime-checks

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 101 +++++++++---------
 1 file changed, 50 insertions(+), 51 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 1d0e1fce178d0..865fc2ae29702 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -4,6 +4,7 @@
 // size in memory as an `Option<UnsafeCell<u32>>` (namely, 8 bytes).
 
 // check-pass
+// compile-flags: --crate-type=lib
 
 #![feature(repr_simd)]
 
@@ -23,59 +24,57 @@ struct Size<const S: usize>;
 
 // Overwriting the runtime assertion and making it a compile-time assertion
 macro_rules! assert_size {
-    ($a:ty, $b:expr) => {{
+    ($a:ty, $b:expr) => {
         const _: Size::<{$b}> = Size::<{size_of::<$a>()}>;
-    }};
+    };
 }
 
 const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
 
-fn main() {
-    assert_size!(Option<Wrapper<u32>>,     8);
-    assert_size!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
-    assert_size!(Option<Transparent<u32>>, 8);
-    assert_size!(Option<Transparent<N32>>, 4); // (✓ niche opt)
-    assert_size!(Option<NoNiche<u32>>,     8);
-    assert_size!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
-
-    assert_size!(Option<UnsafeCell<u32>>,  8);
-    assert_size!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
-
-    assert_size!(       UnsafeCell<&()> , PTR_SIZE);
-    assert_size!(Option<UnsafeCell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
-    assert_size!(             Cell<&()> , PTR_SIZE);
-    assert_size!(Option<      Cell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
-    assert_size!(          RefCell<&()> , PTR_SIZE * 2);
-    assert_size!(Option<   RefCell<&()>>, PTR_SIZE * 3); // (✗ niche opt)
-    assert_size!(
-        RwLock<&()>,
-        if cfg!(target_pointer_width = "32") { 16 } else { 24 }
-    );
-    assert_size!(
-        Option<RwLock<&()>>,
-        if cfg!(target_pointer_width = "32") { 20 } else { 32 }
-    ); // (✗ niche opt)
-    assert_size!(
-        Mutex<&()> ,
-        if cfg!(target_pointer_width = "32") { 12 } else { 16 }
-    );
-    assert_size!(
-        Option<Mutex<&()>>,
-        if cfg!(target_pointer_width = "32") { 16 } else { 24 }
-    ); // (✗ niche opt)
-
-    assert_size!(       UnsafeCell<&[i32]> , PTR_SIZE * 2);
-    assert_size!(Option<UnsafeCell<&[i32]>>, PTR_SIZE * 3); // (✗ niche opt)
-    assert_size!(       UnsafeCell<(&(), &())> , PTR_SIZE * 2);
-    assert_size!(Option<UnsafeCell<(&(), &())>>, PTR_SIZE * 3); // (✗ niche opt)
-
-    trait Trait {}
-    assert_size!(       UnsafeCell<&dyn Trait> , PTR_SIZE * 2);
-    assert_size!(Option<UnsafeCell<&dyn Trait>>, PTR_SIZE * 3); // (✗ niche opt)
-
-    #[repr(simd)]
-    pub struct Vec4<T>([T; 4]);
-
-    assert_size!(       UnsafeCell<Vec4<N32>> , 16);
-    assert_size!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)
-}
+assert_size!(Option<Wrapper<u32>>,     8);
+assert_size!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
+assert_size!(Option<Transparent<u32>>, 8);
+assert_size!(Option<Transparent<N32>>, 4); // (✓ niche opt)
+assert_size!(Option<NoNiche<u32>>,     8);
+assert_size!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
+
+assert_size!(Option<UnsafeCell<u32>>,  8);
+assert_size!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
+
+assert_size!(       UnsafeCell<&()> , PTR_SIZE);
+assert_size!(Option<UnsafeCell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
+assert_size!(             Cell<&()> , PTR_SIZE);
+assert_size!(Option<      Cell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
+assert_size!(          RefCell<&()> , PTR_SIZE * 2);
+assert_size!(Option<   RefCell<&()>>, PTR_SIZE * 3); // (✗ niche opt)
+assert_size!(
+    RwLock<&()>,
+    if cfg!(target_pointer_width = "32") { 16 } else { 24 }
+);
+assert_size!(
+    Option<RwLock<&()>>,
+    if cfg!(target_pointer_width = "32") { 20 } else { 32 }
+); // (✗ niche opt)
+assert_size!(
+    Mutex<&()> ,
+    if cfg!(target_pointer_width = "32") { 12 } else { 16 }
+);
+assert_size!(
+    Option<Mutex<&()>>,
+    if cfg!(target_pointer_width = "32") { 16 } else { 24 }
+); // (✗ niche opt)
+
+assert_size!(       UnsafeCell<&[i32]> , PTR_SIZE * 2);
+assert_size!(Option<UnsafeCell<&[i32]>>, PTR_SIZE * 3); // (✗ niche opt)
+assert_size!(       UnsafeCell<(&(), &())> , PTR_SIZE * 2);
+assert_size!(Option<UnsafeCell<(&(), &())>>, PTR_SIZE * 3); // (✗ niche opt)
+
+trait Trait {}
+assert_size!(       UnsafeCell<&dyn Trait> , PTR_SIZE * 2);
+assert_size!(Option<UnsafeCell<&dyn Trait>>, PTR_SIZE * 3); // (✗ niche opt)
+
+#[repr(simd)]
+pub struct Vec4<T>([T; 4]);
+
+assert_size!(       UnsafeCell<Vec4<N32>> , 16);
+assert_size!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)

From cdd6bba8f662b25d52a58d5ffebbe5c3eac60220 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 14:23:32 +0000
Subject: [PATCH 14/19] Simplify size checking

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 70 ++++++++-----------
 1 file changed, 31 insertions(+), 39 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 865fc2ae29702..9e80a708f2fd7 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -23,58 +23,50 @@ struct NoNiche<T>(UnsafeCell<T>);
 struct Size<const S: usize>;
 
 // Overwriting the runtime assertion and making it a compile-time assertion
-macro_rules! assert_size {
-    ($a:ty, $b:expr) => {
-        const _: Size::<{$b}> = Size::<{size_of::<$a>()}>;
+macro_rules! assert_size_eq {
+    ($ty:ty, $size:expr) => {
+        const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
+    };
+    ($ty:ty, $size:expr, $optioned_size:expr) => {
+        assert_size_eq!($ty, $size);
+        assert_size_eq!(Option<$ty>, $optioned_size);
+        const _: () = assert!($size == $optioned_size || size_of::<$ty>() < size_of::<Option<$ty>>());
     };
 }
 
 const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
 
-assert_size!(Option<Wrapper<u32>>,     8);
-assert_size!(Option<Wrapper<N32>>,     4); // (✓ niche opt)
-assert_size!(Option<Transparent<u32>>, 8);
-assert_size!(Option<Transparent<N32>>, 4); // (✓ niche opt)
-assert_size!(Option<NoNiche<u32>>,     8);
-assert_size!(Option<NoNiche<N32>>,     8); // (✗ niche opt)
-
-assert_size!(Option<UnsafeCell<u32>>,  8);
-assert_size!(Option<UnsafeCell<N32>>,  8); // (✗ niche opt)
-
-assert_size!(       UnsafeCell<&()> , PTR_SIZE);
-assert_size!(Option<UnsafeCell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
-assert_size!(             Cell<&()> , PTR_SIZE);
-assert_size!(Option<      Cell<&()>>, PTR_SIZE * 2); // (✗ niche opt)
-assert_size!(          RefCell<&()> , PTR_SIZE * 2);
-assert_size!(Option<   RefCell<&()>>, PTR_SIZE * 3); // (✗ niche opt)
-assert_size!(
+assert_size_eq!(Wrapper<u32>,     4, 8);
+assert_size_eq!(Wrapper<N32>,     4, 4); // (✓ niche opt)
+assert_size_eq!(Transparent<u32>, 4, 8);
+assert_size_eq!(Transparent<N32>, 4, 4); // (✓ niche opt)
+assert_size_eq!(NoNiche<u32>,     4, 8);
+assert_size_eq!(NoNiche<N32>,     4, 8);
+
+assert_size_eq!(UnsafeCell<u32>,  4, 8);
+assert_size_eq!(UnsafeCell<N32>,  4, 8);
+
+assert_size_eq!(UnsafeCell<&()> , PTR_SIZE, PTR_SIZE * 2);
+assert_size_eq!(      Cell<&()> , PTR_SIZE, PTR_SIZE * 2);
+assert_size_eq!(   RefCell<&()> , PTR_SIZE * 2, PTR_SIZE * 3);
+assert_size_eq!(
     RwLock<&()>,
-    if cfg!(target_pointer_width = "32") { 16 } else { 24 }
-);
-assert_size!(
-    Option<RwLock<&()>>,
+    if cfg!(target_pointer_width = "32") { 16 } else { 24 },
     if cfg!(target_pointer_width = "32") { 20 } else { 32 }
-); // (✗ niche opt)
-assert_size!(
-    Mutex<&()> ,
-    if cfg!(target_pointer_width = "32") { 12 } else { 16 }
 );
-assert_size!(
-    Option<Mutex<&()>>,
+assert_size_eq!(
+    Mutex<&()> ,
+    if cfg!(target_pointer_width = "32") { 12 } else { 16 },
     if cfg!(target_pointer_width = "32") { 16 } else { 24 }
-); // (✗ niche opt)
+);
 
-assert_size!(       UnsafeCell<&[i32]> , PTR_SIZE * 2);
-assert_size!(Option<UnsafeCell<&[i32]>>, PTR_SIZE * 3); // (✗ niche opt)
-assert_size!(       UnsafeCell<(&(), &())> , PTR_SIZE * 2);
-assert_size!(Option<UnsafeCell<(&(), &())>>, PTR_SIZE * 3); // (✗ niche opt)
+assert_size_eq!(UnsafeCell<&[i32]> , PTR_SIZE * 2, PTR_SIZE * 3);
+assert_size_eq!(UnsafeCell<(&(), &())> , PTR_SIZE * 2, PTR_SIZE * 3);
 
 trait Trait {}
-assert_size!(       UnsafeCell<&dyn Trait> , PTR_SIZE * 2);
-assert_size!(Option<UnsafeCell<&dyn Trait>>, PTR_SIZE * 3); // (✗ niche opt)
+assert_size_eq!(UnsafeCell<&dyn Trait> , PTR_SIZE * 2, PTR_SIZE * 3);
 
 #[repr(simd)]
 pub struct Vec4<T>([T; 4]);
 
-assert_size!(       UnsafeCell<Vec4<N32>> , 16);
-assert_size!(Option<UnsafeCell<Vec4<N32>>>, 32); // (✗ niche opt)
+assert_size_eq!(UnsafeCell<Vec4<N32>> , 16, 32);

From 0318b70514e13d09fd0e9043da4b7c49e0285f75 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 14:35:04 +0000
Subject: [PATCH 15/19] tidy

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 9e80a708f2fd7..7f159887ba1d4 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -30,7 +30,10 @@ macro_rules! assert_size_eq {
     ($ty:ty, $size:expr, $optioned_size:expr) => {
         assert_size_eq!($ty, $size);
         assert_size_eq!(Option<$ty>, $optioned_size);
-        const _: () = assert!($size == $optioned_size || size_of::<$ty>() < size_of::<Option<$ty>>());
+        const _: () = assert!(
+            $size == $optioned_size ||
+            size_of::<$ty>() < size_of::<Option<$ty>>()
+        );
     };
 }
 

From 3338593afd6a010a2ce6799d3bf4bf4c2a252950 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Mon, 11 Jul 2022 15:41:38 +0000
Subject: [PATCH 16/19] Only check relative sizes on platform specific types

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 69 +++++++++----------
 1 file changed, 32 insertions(+), 37 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 7f159887ba1d4..9eed2ad361ce3 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -22,54 +22,49 @@ struct NoNiche<T>(UnsafeCell<T>);
 
 struct Size<const S: usize>;
 
-// Overwriting the runtime assertion and making it a compile-time assertion
-macro_rules! assert_size_eq {
-    ($ty:ty, $size:expr) => {
+macro_rules! check_sizes {
+    (check_one_specific_size: $ty:ty, $size:expr) => {
         const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
     };
     ($ty:ty, $size:expr, $optioned_size:expr) => {
-        assert_size_eq!($ty, $size);
-        assert_size_eq!(Option<$ty>, $optioned_size);
-        const _: () = assert!(
-            $size == $optioned_size ||
-            size_of::<$ty>() < size_of::<Option<$ty>>()
-        );
+        check_sizes!(check_one_specific_size: $ty, $size);
+        check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size);
+        check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty);
+    };
+    ($ty:ty) => {
+        check_sizes!(check_no_niche_opt: true, $ty);
+    };
+    (check_no_niche_opt: $no_niche_opt:expr, $ty:ty) => {
+        const _: () = if $no_niche_opt { assert!(size_of::<$ty>() < size_of::<Option<$ty>>()); };
     };
 }
 
 const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
 
-assert_size_eq!(Wrapper<u32>,     4, 8);
-assert_size_eq!(Wrapper<N32>,     4, 4); // (✓ niche opt)
-assert_size_eq!(Transparent<u32>, 4, 8);
-assert_size_eq!(Transparent<N32>, 4, 4); // (✓ niche opt)
-assert_size_eq!(NoNiche<u32>,     4, 8);
-assert_size_eq!(NoNiche<N32>,     4, 8);
-
-assert_size_eq!(UnsafeCell<u32>,  4, 8);
-assert_size_eq!(UnsafeCell<N32>,  4, 8);
-
-assert_size_eq!(UnsafeCell<&()> , PTR_SIZE, PTR_SIZE * 2);
-assert_size_eq!(      Cell<&()> , PTR_SIZE, PTR_SIZE * 2);
-assert_size_eq!(   RefCell<&()> , PTR_SIZE * 2, PTR_SIZE * 3);
-assert_size_eq!(
-    RwLock<&()>,
-    if cfg!(target_pointer_width = "32") { 16 } else { 24 },
-    if cfg!(target_pointer_width = "32") { 20 } else { 32 }
-);
-assert_size_eq!(
-    Mutex<&()> ,
-    if cfg!(target_pointer_width = "32") { 12 } else { 16 },
-    if cfg!(target_pointer_width = "32") { 16 } else { 24 }
-);
-
-assert_size_eq!(UnsafeCell<&[i32]> , PTR_SIZE * 2, PTR_SIZE * 3);
-assert_size_eq!(UnsafeCell<(&(), &())> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(Wrapper<u32>,     4, 8);
+check_sizes!(Wrapper<N32>,     4, 4); // (✓ niche opt)
+check_sizes!(Transparent<u32>, 4, 8);
+check_sizes!(Transparent<N32>, 4, 4); // (✓ niche opt)
+check_sizes!(NoNiche<u32>,     4, 8);
+check_sizes!(NoNiche<N32>,     4, 8);
+
+check_sizes!(UnsafeCell<u32>,  4, 8);
+check_sizes!(UnsafeCell<N32>,  4, 8);
+
+check_sizes!(UnsafeCell<&()> , PTR_SIZE, PTR_SIZE * 2);
+check_sizes!(      Cell<&()> , PTR_SIZE, PTR_SIZE * 2);
+check_sizes!(   RefCell<&()> , PTR_SIZE * 2, PTR_SIZE * 3);
+
+check_sizes!(RwLock<&()>);
+check_sizes!(Mutex<&()>);
+
+check_sizes!(UnsafeCell<&[i32]> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(UnsafeCell<(&(), &())> , PTR_SIZE * 2, PTR_SIZE * 3);
 
 trait Trait {}
-assert_size_eq!(UnsafeCell<&dyn Trait> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(UnsafeCell<&dyn Trait> , PTR_SIZE * 2, PTR_SIZE * 3);
 
 #[repr(simd)]
 pub struct Vec4<T>([T; 4]);
 
-assert_size_eq!(UnsafeCell<Vec4<N32>> , 16, 32);
+check_sizes!(UnsafeCell<Vec4<N32>> , 16, 32);

From 24e87965ae35843fe340a5104482be1d1f827af7 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 12 Jul 2022 07:22:52 +0000
Subject: [PATCH 17/19] Use some more visible sigils than `,`

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 32 +++++++++----------
 1 file changed, 16 insertions(+), 16 deletions(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index 9eed2ad361ce3..e82eaa38612cd 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -26,7 +26,7 @@ macro_rules! check_sizes {
     (check_one_specific_size: $ty:ty, $size:expr) => {
         const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
     };
-    ($ty:ty, $size:expr, $optioned_size:expr) => {
+    ($ty:ty: $size:expr => $optioned_size:expr) => {
         check_sizes!(check_one_specific_size: $ty, $size);
         check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size);
         check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty);
@@ -41,30 +41,30 @@ macro_rules! check_sizes {
 
 const PTR_SIZE: usize = std::mem::size_of::<*const ()>();
 
-check_sizes!(Wrapper<u32>,     4, 8);
-check_sizes!(Wrapper<N32>,     4, 4); // (✓ niche opt)
-check_sizes!(Transparent<u32>, 4, 8);
-check_sizes!(Transparent<N32>, 4, 4); // (✓ niche opt)
-check_sizes!(NoNiche<u32>,     4, 8);
-check_sizes!(NoNiche<N32>,     4, 8);
+check_sizes!(Wrapper<u32>:     4 => 8);
+check_sizes!(Wrapper<N32>:     4 => 4); // (✓ niche opt)
+check_sizes!(Transparent<u32>: 4 => 8);
+check_sizes!(Transparent<N32>: 4 => 4); // (✓ niche opt)
+check_sizes!(NoNiche<u32>:     4 => 8);
+check_sizes!(NoNiche<N32>:     4 => 8);
 
-check_sizes!(UnsafeCell<u32>,  4, 8);
-check_sizes!(UnsafeCell<N32>,  4, 8);
+check_sizes!(UnsafeCell<u32>:  4 => 8);
+check_sizes!(UnsafeCell<N32>:  4 => 8);
 
-check_sizes!(UnsafeCell<&()> , PTR_SIZE, PTR_SIZE * 2);
-check_sizes!(      Cell<&()> , PTR_SIZE, PTR_SIZE * 2);
-check_sizes!(   RefCell<&()> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2);
+check_sizes!(      Cell<&()>: PTR_SIZE => PTR_SIZE * 2);
+check_sizes!(   RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3);
 
 check_sizes!(RwLock<&()>);
 check_sizes!(Mutex<&()>);
 
-check_sizes!(UnsafeCell<&[i32]> , PTR_SIZE * 2, PTR_SIZE * 3);
-check_sizes!(UnsafeCell<(&(), &())> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(UnsafeCell<&[i32]>: PTR_SIZE * 2 => PTR_SIZE * 3);
+check_sizes!(UnsafeCell<(&(), &())>: PTR_SIZE * 2 => PTR_SIZE * 3);
 
 trait Trait {}
-check_sizes!(UnsafeCell<&dyn Trait> , PTR_SIZE * 2, PTR_SIZE * 3);
+check_sizes!(UnsafeCell<&dyn Trait>: PTR_SIZE * 2 => PTR_SIZE * 3);
 
 #[repr(simd)]
 pub struct Vec4<T>([T; 4]);
 
-check_sizes!(UnsafeCell<Vec4<N32>> , 16, 32);
+check_sizes!(UnsafeCell<Vec4<N32>>: 16 => 32);

From 726919629e0ca3660a41843f9565469e5dd2b2d9 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Tue, 12 Jul 2022 07:29:36 +0000
Subject: [PATCH 18/19] Always check Cell alongside with `UnsafeCell`

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 13 ++++++++++++-
 1 file changed, 12 insertions(+), 1 deletion(-)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index e82eaa38612cd..fce101d7bb173 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -26,11 +26,23 @@ macro_rules! check_sizes {
     (check_one_specific_size: $ty:ty, $size:expr) => {
         const _: Size::<{$size}> = Size::<{size_of::<$ty>()}>;
     };
+    // Any tests run on `UnsafeCell` must be the same for `Cell`
+    (UnsafeCell<$ty:ty>: $size:expr => $optioned_size:expr) => {
+        check_sizes!(Cell<$ty>: $size => $optioned_size);
+        check_sizes!(@actual_check: UnsafeCell<$ty>: $size => $optioned_size);
+    };
     ($ty:ty: $size:expr => $optioned_size:expr) => {
+        check_sizes!(@actual_check: $ty: $size => $optioned_size);
+    };
+    // This branch does the actual checking logic, the `@actual_check` prefix is here to distinguish
+    // it from other branches and not accidentally match any.
+    (@actual_check: $ty:ty: $size:expr => $optioned_size:expr) => {
         check_sizes!(check_one_specific_size: $ty, $size);
         check_sizes!(check_one_specific_size: Option<$ty>, $optioned_size);
         check_sizes!(check_no_niche_opt: $size != $optioned_size, $ty);
     };
+    // only check that there is no niche (size goes up when wrapped in an option),
+    // don't check actual sizes
     ($ty:ty) => {
         check_sizes!(check_no_niche_opt: true, $ty);
     };
@@ -52,7 +64,6 @@ check_sizes!(UnsafeCell<u32>:  4 => 8);
 check_sizes!(UnsafeCell<N32>:  4 => 8);
 
 check_sizes!(UnsafeCell<&()>: PTR_SIZE => PTR_SIZE * 2);
-check_sizes!(      Cell<&()>: PTR_SIZE => PTR_SIZE * 2);
 check_sizes!(   RefCell<&()>: PTR_SIZE * 2 => PTR_SIZE * 3);
 
 check_sizes!(RwLock<&()>);

From 519c07b3ce7f34975aacbe128e55d84411348229 Mon Sep 17 00:00:00 2001
From: Oli Scherer <git-spam-no-reply9815368754983@oli-obk.de>
Date: Wed, 13 Jul 2022 10:11:35 +0000
Subject: [PATCH 19/19] Limit test to x86 targets for reproducability

---
 src/test/ui/layout/unsafe-cell-hides-niche.rs | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/test/ui/layout/unsafe-cell-hides-niche.rs b/src/test/ui/layout/unsafe-cell-hides-niche.rs
index fce101d7bb173..73b32066fadcd 100644
--- a/src/test/ui/layout/unsafe-cell-hides-niche.rs
+++ b/src/test/ui/layout/unsafe-cell-hides-niche.rs
@@ -5,6 +5,7 @@
 
 // check-pass
 // compile-flags: --crate-type=lib
+// only-x86
 
 #![feature(repr_simd)]