From 615946db4fc812bff3bb015dfe860c10da4b20c1 Mon Sep 17 00:00:00 2001
From: George Bateman <george.bateman16@gmail.com>
Date: Tue, 5 Dec 2023 22:15:26 +0000
Subject: [PATCH 1/3] Stabilize simple offset_of

---
 .../src/error_codes/E0795.md                  |  4 +-
 compiler/rustc_feature/src/unstable.rs        |  2 +
 compiler/rustc_hir_typeck/src/expr.rs         | 12 ++++
 compiler/rustc_span/src/symbol.rs             |  1 +
 library/core/src/lib.rs                       |  2 +-
 library/core/src/mem/mod.rs                   | 14 ++---
 library/core/tests/lib.rs                     |  1 -
 library/std/src/lib.rs                        |  1 -
 .../feature-gate-offset-of-enum.rs            |  2 +-
 .../feature-gate-offset-of-nested.rs          | 28 ++++++++++
 .../feature-gate-offset-of-nested.stderr      | 55 +++++++++++++++++++
 .../dead-code/offset-of-correct-param-env.rs  |  2 +-
 tests/ui/lint/dead-code/offset-of.rs          |  2 +-
 tests/ui/offset-of/offset-of-arg-count.rs     |  2 -
 tests/ui/offset-of/offset-of-arg-count.stderr | 14 ++---
 tests/ui/offset-of/offset-of-dst-field.rs     |  2 +-
 tests/ui/offset-of/offset-of-enum.rs          |  2 +-
 tests/ui/offset-of/offset-of-inference.rs     |  2 -
 tests/ui/offset-of/offset-of-inference.stderr |  2 +-
 tests/ui/offset-of/offset-of-must-use.rs      |  1 -
 tests/ui/offset-of/offset-of-must-use.stderr  |  4 +-
 tests/ui/offset-of/offset-of-output-type.rs   |  2 -
 .../ui/offset-of/offset-of-output-type.stderr | 12 ++--
 tests/ui/offset-of/offset-of-private.rs       |  2 +-
 tests/ui/offset-of/offset-of-self.rs          |  2 +-
 tests/ui/offset-of/offset-of-tuple-nested.rs  |  2 +-
 tests/ui/offset-of/offset-of-tuple.rs         |  2 +-
 tests/ui/offset-of/offset-of-unsized.rs       |  2 -
 .../offset-of-unstable-with-feature.rs        |  2 +-
 tests/ui/offset-of/offset-of-unstable.rs      |  2 +-
 30 files changed, 134 insertions(+), 49 deletions(-)
 create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.rs
 create mode 100644 tests/ui/feature-gates/feature-gate-offset-of-nested.stderr

diff --git a/compiler/rustc_error_codes/src/error_codes/E0795.md b/compiler/rustc_error_codes/src/error_codes/E0795.md
index 20f51441c2911..ad77d72c913a8 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0795.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0795.md
@@ -3,7 +3,7 @@ Invalid argument for the `offset_of!` macro.
 Erroneous code example:
 
 ```compile_fail,E0795
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 let x = std::mem::offset_of!(Option<u8>, Some);
 ```
@@ -16,7 +16,7 @@ The offset of the contained `u8` in the `Option<u8>` can be found by specifying
 the field name `0`:
 
 ```
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 let x: usize = std::mem::offset_of!(Option<u8>, Some.0);
 ```
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 2f2b551e6ecf7..c512ccc90db5c 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -550,6 +550,8 @@ declare_features! (
     (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
     /// Allows using enums in offset_of!
     (unstable, offset_of_enum, "1.75.0", Some(106655)),
+    /// Allows using multiple nested field accesses in offset_of!
+    (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(106655)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 4b1ad28f0941d..242e8dc95e23c 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3246,6 +3246,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> Ty<'tcx> {
         let container = self.to_ty(container).normalized;
 
+        if let Some(ident_2) = fields.get(1)
+            && !self.tcx.features().offset_of_nested
+        {
+            rustc_session::parse::feature_err(
+                &self.tcx.sess.parse_sess,
+                sym::offset_of_nested,
+                ident_2.span,
+                "only a single ident or integer is stable as the field in offset_of",
+            )
+            .emit();
+        }
+
         let mut field_indices = Vec::with_capacity(fields.len());
         let mut current_container = container;
         let mut fields = fields.into_iter();
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 44795022cbab3..7b0138d50baed 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1153,6 +1153,7 @@ symbols! {
         offset,
         offset_of,
         offset_of_enum,
+        offset_of_nested,
         ok_or_else,
         omit_gdb_pretty_printer_section,
         on,
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 1a8f245c8be30..81bf6f28693f1 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -111,6 +111,7 @@
 //
 // Library features:
 // tidy-alphabetical-start
+#![cfg_attr(not(bootstrap), feature(offset_of_nested))]
 #![feature(char_indices_offset)]
 #![feature(const_align_of_val)]
 #![feature(const_align_of_val_raw)]
@@ -176,7 +177,6 @@
 #![feature(isqrt)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(non_null_convenience)]
-#![feature(offset_of)]
 #![feature(offset_of_enum)]
 #![feature(panic_internals)]
 #![feature(ptr_alignment_type)]
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 407954001e4ce..f04ccce40f109 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -1303,11 +1303,12 @@ impl<T> SizedTypeProperties for T {}
 /// Enum variants may be traversed as if they were fields. Variants themselves do
 /// not have an offset.
 ///
+/// However, on stable only a single field name is supported, which blocks the use of
+/// enum support.
+///
 /// Visibility is respected - all types and fields must be visible to the call site:
 ///
 /// ```
-/// #![feature(offset_of)]
-///
 /// mod nested {
 ///     #[repr(C)]
 ///     pub struct Struct {
@@ -1330,8 +1331,6 @@ impl<T> SizedTypeProperties for T {}
 /// not *identical*, e.g.:
 ///
 /// ```
-/// #![feature(offset_of)]
-///
 /// struct Wrapper<T, U>(T, U);
 ///
 /// type A = Wrapper<u8, u8>;
@@ -1359,8 +1358,7 @@ impl<T> SizedTypeProperties for T {}
 /// # Examples
 ///
 /// ```
-/// #![feature(offset_of)]
-/// # #![feature(offset_of_enum)]
+/// #![feature(offset_of_enum, offset_of_nested)]
 ///
 /// use std::mem;
 /// #[repr(C)]
@@ -1396,7 +1394,7 @@ impl<T> SizedTypeProperties for T {}
 /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
 /// ```
 #[cfg(not(bootstrap))]
-#[unstable(feature = "offset_of", issue = "106655")]
+#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")]
 #[allow_internal_unstable(builtin_syntax, hint_must_use)]
 pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
     // The `{}` is for better error messages
@@ -1404,7 +1402,7 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
 }
 
 #[cfg(bootstrap)]
-#[unstable(feature = "offset_of", issue = "106655")]
+#[stable(feature = "offset_of", since = "CURRENT_RUSTC_VERSION")]
 #[allow_internal_unstable(builtin_syntax, hint_must_use)]
 #[allow(missing_docs)]
 pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) {
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 8604d41eb6860..02af3e6f9476a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -115,7 +115,6 @@
 #![feature(utf8_chunks)]
 #![feature(is_ascii_octdigit)]
 #![feature(get_many_mut)]
-#![feature(offset_of)]
 #![feature(iter_map_windows)]
 #![allow(internal_features)]
 #![deny(unsafe_op_in_unsafe_fn)]
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 7a8d9d0ceeca6..4b33ad5dfe092 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -329,7 +329,6 @@
 #![feature(maybe_uninit_slice)]
 #![feature(maybe_uninit_uninit_array)]
 #![feature(maybe_uninit_write_slice)]
-#![feature(offset_of)]
 #![feature(panic_can_unwind)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
index e19dcf9f6a54c..1f2f7ee1e1919 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.rs b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs
new file mode 100644
index 0000000000000..c4eb4720fde5e
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.rs
@@ -0,0 +1,28 @@
+#![feature(offset_of_enum)]
+
+use std::mem::offset_of;
+
+struct S {
+    a: u8,
+    b: (u8, u8),
+    c: T,
+}
+
+struct T {
+    t: &'static str,
+}
+
+enum Alpha {
+    One(u8),
+    Two(u8),
+}
+
+fn main() {
+    offset_of!(Alpha, Two.0); //~ ERROR only a single ident or integer is stable as the field in offset_of
+    offset_of!(S, a);
+    offset_of!((u8, S), 1);
+    offset_of!((u32, (S, T)), 1.1); //~ ERROR only a single ident or integer is stable as the field in offset_of
+    offset_of!(S, b.0); //~ ERROR only a single ident or integer is stable as the field in offset_of
+    offset_of!((S, ()), 0.c); //~ ERROR only a single ident or integer is stable as the field in offset_of
+    offset_of!(S, c.t); //~ ERROR only a single ident or integer is stable as the field in offset_of
+}
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
new file mode 100644
index 0000000000000..ebc251fd66307
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
@@ -0,0 +1,55 @@
+error[E0658]: only a single ident or integer is stable as the field in offset_of
+  --> $DIR/feature-gate-offset-of-nested.rs:21:27
+   |
+LL |     offset_of!(Alpha, Two.0);
+   |                           ^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+
+error[E0658]: only a single ident or integer is stable as the field in offset_of
+  --> $DIR/feature-gate-offset-of-nested.rs:24:33
+   |
+LL |       offset_of!((u32, (S, T)), 1.1);
+   |  _____----------------------------^-
+   | |     |
+   | |     in this macro invocation
+LL | |     offset_of!(S, b.0);
+LL | |     offset_of!((S, ()), 0.c);
+LL | |     offset_of!(S, c.t);
+...  |
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0658]: only a single ident or integer is stable as the field in offset_of
+  --> $DIR/feature-gate-offset-of-nested.rs:25:21
+   |
+LL |     offset_of!(S, b.0);
+   |                     ^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+
+error[E0658]: only a single ident or integer is stable as the field in offset_of
+  --> $DIR/feature-gate-offset-of-nested.rs:26:27
+   |
+LL |     offset_of!((S, ()), 0.c);
+   |                           ^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+
+error[E0658]: only a single ident or integer is stable as the field in offset_of
+  --> $DIR/feature-gate-offset-of-nested.rs:27:21
+   |
+LL |     offset_of!(S, c.t);
+   |                     ^
+   |
+   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
index 2c6fcef250049..ae81a2524396c 100644
--- a/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
+++ b/tests/ui/lint/dead-code/offset-of-correct-param-env.rs
@@ -1,6 +1,6 @@
 // check-pass
 
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 #![deny(dead_code)]
 
 // This struct contains a projection that can only be normalized after getting the field type.
diff --git a/tests/ui/lint/dead-code/offset-of.rs b/tests/ui/lint/dead-code/offset-of.rs
index da91de3862fc8..5269426d2ff3a 100644
--- a/tests/ui/lint/dead-code/offset-of.rs
+++ b/tests/ui/lint/dead-code/offset-of.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 #![deny(dead_code)]
 
 use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-arg-count.rs b/tests/ui/offset-of/offset-of-arg-count.rs
index 7b92698c25e8a..c86e61a61a725 100644
--- a/tests/ui/offset-of/offset-of-arg-count.rs
+++ b/tests/ui/offset-of/offset-of-arg-count.rs
@@ -1,5 +1,3 @@
-#![feature(offset_of)]
-
 use std::mem::offset_of;
 
 fn main() {
diff --git a/tests/ui/offset-of/offset-of-arg-count.stderr b/tests/ui/offset-of/offset-of-arg-count.stderr
index af0d42de30d60..4cb24b3d034b6 100644
--- a/tests/ui/offset-of/offset-of-arg-count.stderr
+++ b/tests/ui/offset-of/offset-of-arg-count.stderr
@@ -1,5 +1,5 @@
 error: unexpected end of macro invocation
-  --> $DIR/offset-of-arg-count.rs:6:34
+  --> $DIR/offset-of-arg-count.rs:4:34
    |
 LL |     offset_of!(NotEnoughArguments);
    |                                  ^ missing tokens in macro arguments
@@ -8,7 +8,7 @@ note: while trying to match `,`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
 
 error: unexpected end of macro invocation
-  --> $DIR/offset-of-arg-count.rs:7:45
+  --> $DIR/offset-of-arg-count.rs:5:45
    |
 LL |     offset_of!(NotEnoughArgumentsWithAComma, );
    |                                             ^ missing tokens in macro arguments
@@ -17,7 +17,7 @@ note: while trying to match meta-variable `$fields:expr`
   --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
 
 error: no rules expected the token `too`
-  --> $DIR/offset-of-arg-count.rs:8:34
+  --> $DIR/offset-of-arg-count.rs:6:34
    |
 LL |     offset_of!(Container, field, too many arguments);
    |                                  ^^^ no rules expected this token in macro call
@@ -25,25 +25,25 @@ LL |     offset_of!(Container, field, too many arguments);
    = note: while trying to match sequence end
 
 error: unexpected token: `)`
-  --> $DIR/offset-of-arg-count.rs:11:21
+  --> $DIR/offset-of-arg-count.rs:9:21
    |
 LL |     offset_of!(S, f.);
    |                     ^
 
 error: unexpected token: `,`
-  --> $DIR/offset-of-arg-count.rs:12:21
+  --> $DIR/offset-of-arg-count.rs:10:21
    |
 LL |     offset_of!(S, f.,);
    |                     ^
 
 error: offset_of expects dot-separated field and variant names
-  --> $DIR/offset-of-arg-count.rs:13:19
+  --> $DIR/offset-of-arg-count.rs:11:19
    |
 LL |     offset_of!(S, f..);
    |                   ^^^
 
 error: offset_of expects dot-separated field and variant names
-  --> $DIR/offset-of-arg-count.rs:14:19
+  --> $DIR/offset-of-arg-count.rs:12:19
    |
 LL |     offset_of!(S, f..,);
    |                   ^^^
diff --git a/tests/ui/offset-of/offset-of-dst-field.rs b/tests/ui/offset-of/offset-of-dst-field.rs
index e393b159e64d5..016ebfadd1420 100644
--- a/tests/ui/offset-of/offset-of-dst-field.rs
+++ b/tests/ui/offset-of/offset-of-dst-field.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of, extern_types)]
+#![feature(extern_types)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-enum.rs b/tests/ui/offset-of/offset-of-enum.rs
index a2d6aace47da1..cb2f04786ac5c 100644
--- a/tests/ui/offset-of/offset-of-enum.rs
+++ b/tests/ui/offset-of/offset-of-enum.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-inference.rs b/tests/ui/offset-of/offset-of-inference.rs
index ba87574eae047..1b1ae25e1ee65 100644
--- a/tests/ui/offset-of/offset-of-inference.rs
+++ b/tests/ui/offset-of/offset-of-inference.rs
@@ -1,7 +1,5 @@
 // Test that inference types in `offset_of!` don't ICE.
 
-#![feature(offset_of)]
-
 struct Foo<T> {
     x: T,
 }
diff --git a/tests/ui/offset-of/offset-of-inference.stderr b/tests/ui/offset-of/offset-of-inference.stderr
index 1845822f11db1..8bd104ed7e277 100644
--- a/tests/ui/offset-of/offset-of-inference.stderr
+++ b/tests/ui/offset-of/offset-of-inference.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/offset-of-inference.rs:10:35
+  --> $DIR/offset-of-inference.rs:8:35
    |
 LL |     let _ = core::mem::offset_of!(Foo<_>, x);
    |                                   ^^^^^^ cannot infer type
diff --git a/tests/ui/offset-of/offset-of-must-use.rs b/tests/ui/offset-of/offset-of-must-use.rs
index e30145d7a2fe3..e4b092fcedf3b 100644
--- a/tests/ui/offset-of/offset-of-must-use.rs
+++ b/tests/ui/offset-of/offset-of-must-use.rs
@@ -1,6 +1,5 @@
 // check-pass
 
-#![feature(offset_of)]
 #![warn(unused)]
 
 fn main() {
diff --git a/tests/ui/offset-of/offset-of-must-use.stderr b/tests/ui/offset-of/offset-of-must-use.stderr
index 5fe387a72553c..b6d88e098d00c 100644
--- a/tests/ui/offset-of/offset-of-must-use.stderr
+++ b/tests/ui/offset-of/offset-of-must-use.stderr
@@ -1,11 +1,11 @@
 warning: unused return value of `must_use` that must be used
-  --> $DIR/offset-of-must-use.rs:7:5
+  --> $DIR/offset-of-must-use.rs:6:5
    |
 LL |     core::mem::offset_of!((String,), 0);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/offset-of-must-use.rs:4:9
+  --> $DIR/offset-of-must-use.rs:3:9
    |
 LL | #![warn(unused)]
    |         ^^^^^^
diff --git a/tests/ui/offset-of/offset-of-output-type.rs b/tests/ui/offset-of/offset-of-output-type.rs
index 50c2e93841f9f..76a33154ba3d1 100644
--- a/tests/ui/offset-of/offset-of-output-type.rs
+++ b/tests/ui/offset-of/offset-of-output-type.rs
@@ -1,5 +1,3 @@
-#![feature(offset_of)]
-
 use std::mem::offset_of;
 
 struct S {
diff --git a/tests/ui/offset-of/offset-of-output-type.stderr b/tests/ui/offset-of/offset-of-output-type.stderr
index 233d49876436a..34ad931d0caac 100644
--- a/tests/ui/offset-of/offset-of-output-type.stderr
+++ b/tests/ui/offset-of/offset-of-output-type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:12:17
+  --> $DIR/offset-of-output-type.rs:10:17
    |
 LL |     let _: u8 = offset_of!(S, v);
    |                 ^^^^^^^^^^^^^^^^ expected `u8`, found `usize`
@@ -7,7 +7,7 @@ LL |     let _: u8 = offset_of!(S, v);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:13:18
+  --> $DIR/offset-of-output-type.rs:11:18
    |
 LL |     let _: u16 = offset_of!(S, v);
    |                  ^^^^^^^^^^^^^^^^ expected `u16`, found `usize`
@@ -15,7 +15,7 @@ LL |     let _: u16 = offset_of!(S, v);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:14:18
+  --> $DIR/offset-of-output-type.rs:12:18
    |
 LL |     let _: u32 = offset_of!(S, v);
    |                  ^^^^^^^^^^^^^^^^ expected `u32`, found `usize`
@@ -23,7 +23,7 @@ LL |     let _: u32 = offset_of!(S, v);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:15:18
+  --> $DIR/offset-of-output-type.rs:13:18
    |
 LL |     let _: u64 = offset_of!(S, v);
    |                  ^^^^^^^^^^^^^^^^ expected `u64`, found `usize`
@@ -31,7 +31,7 @@ LL |     let _: u64 = offset_of!(S, v);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:16:20
+  --> $DIR/offset-of-output-type.rs:14:20
    |
 LL |     let _: isize = offset_of!(S, v);
    |                    ^^^^^^^^^^^^^^^^ expected `isize`, found `usize`
@@ -39,7 +39,7 @@ LL |     let _: isize = offset_of!(S, v);
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0308]: mismatched types
-  --> $DIR/offset-of-output-type.rs:19:5
+  --> $DIR/offset-of-output-type.rs:17:5
    |
 LL | fn main() {
    |          - expected `()` because of default return type
diff --git a/tests/ui/offset-of/offset-of-private.rs b/tests/ui/offset-of/offset-of-private.rs
index b7affdb794395..1c326b5c79a5e 100644
--- a/tests/ui/offset-of/offset-of-private.rs
+++ b/tests/ui/offset-of/offset-of-private.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-self.rs b/tests/ui/offset-of/offset-of-self.rs
index 04dcaf7c0a6b6..1558e13b53095 100644
--- a/tests/ui/offset-of/offset-of-self.rs
+++ b/tests/ui/offset-of/offset-of-self.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-tuple-nested.rs b/tests/ui/offset-of/offset-of-tuple-nested.rs
index 59b02e3c5c433..212176b24271a 100644
--- a/tests/ui/offset-of/offset-of-tuple-nested.rs
+++ b/tests/ui/offset-of/offset-of-tuple-nested.rs
@@ -2,7 +2,7 @@
 // Test for issue #112204 -- make sure this goes through the entire compilation pipeline,
 // similar to why `offset-of-unsized.rs` is also build-pass
 
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-tuple.rs b/tests/ui/offset-of/offset-of-tuple.rs
index b6fc1e32229a1..75ba8d77f2fbd 100644
--- a/tests/ui/offset-of/offset-of-tuple.rs
+++ b/tests/ui/offset-of/offset-of-tuple.rs
@@ -1,4 +1,4 @@
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 #![feature(builtin_syntax)]
 
 use std::mem::offset_of;
diff --git a/tests/ui/offset-of/offset-of-unsized.rs b/tests/ui/offset-of/offset-of-unsized.rs
index 49c8328da5c55..b70529ed7b85e 100644
--- a/tests/ui/offset-of/offset-of-unsized.rs
+++ b/tests/ui/offset-of/offset-of-unsized.rs
@@ -2,8 +2,6 @@
 // regression test for #112051, not in `offset-of-dst` as the issue is in codegen,
 // and isn't triggered in the presence of typeck errors
 
-#![feature(offset_of)]
-
 struct S<T: ?Sized> {
     a: u64,
     b: T,
diff --git a/tests/ui/offset-of/offset-of-unstable-with-feature.rs b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
index 7d2eb46c056eb..be275564a0a4f 100644
--- a/tests/ui/offset-of/offset-of-unstable-with-feature.rs
+++ b/tests/ui/offset-of/offset-of-unstable-with-feature.rs
@@ -1,7 +1,7 @@
 // check-pass
 // aux-build:offset-of-staged-api.rs
 
-#![feature(offset_of, unstable_test_feature)]
+#![feature(offset_of_nested, unstable_test_feature)]
 
 use std::mem::offset_of;
 
diff --git a/tests/ui/offset-of/offset-of-unstable.rs b/tests/ui/offset-of/offset-of-unstable.rs
index 1e19f2091f29f..da0882abd2286 100644
--- a/tests/ui/offset-of/offset-of-unstable.rs
+++ b/tests/ui/offset-of/offset-of-unstable.rs
@@ -1,6 +1,6 @@
 // aux-build:offset-of-staged-api.rs
 
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 
 use std::mem::offset_of;
 

From 803b810eac520c11c7f1ea0a81af535ee9bddd61 Mon Sep 17 00:00:00 2001
From: George Bateman <george.bateman16@gmail.com>
Date: Fri, 5 Jan 2024 21:25:01 +0000
Subject: [PATCH 2/3] Remove feature(offset_of) from tests

---
 library/core/tests/lib.rs                      | 1 +
 tests/mir-opt/const_prop/offset_of.rs          | 2 +-
 tests/mir-opt/dataflow-const-prop/offset_of.rs | 2 +-
 tests/pretty/offset_of.rs                      | 1 -
 tests/ui/layout/issue-112048-unsizing-niche.rs | 1 -
 5 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 02af3e6f9476a..13fb97fdc7f3e 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -59,6 +59,7 @@
 #![feature(noop_waker)]
 #![feature(numfmt)]
 #![feature(num_midpoint)]
+#![cfg_attr(not(bootstrap), feature(offset_of_nested))]
 #![feature(isqrt)]
 #![feature(step_trait)]
 #![feature(str_internals)]
diff --git a/tests/mir-opt/const_prop/offset_of.rs b/tests/mir-opt/const_prop/offset_of.rs
index 43ecbbed186f6..f15d15bfcb268 100644
--- a/tests/mir-opt/const_prop/offset_of.rs
+++ b/tests/mir-opt/const_prop/offset_of.rs
@@ -2,7 +2,7 @@
 // unit-test: GVN
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-#![feature(offset_of, offset_of_enum)]
+#![feature(offset_of_enum, offset_of_nested)]
 
 use std::marker::PhantomData;
 use std::mem::offset_of;
diff --git a/tests/mir-opt/dataflow-const-prop/offset_of.rs b/tests/mir-opt/dataflow-const-prop/offset_of.rs
index e71b3f59ecab3..c1be691025805 100644
--- a/tests/mir-opt/dataflow-const-prop/offset_of.rs
+++ b/tests/mir-opt/dataflow-const-prop/offset_of.rs
@@ -2,7 +2,7 @@
 // unit-test: DataflowConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 
-#![feature(offset_of)]
+#![feature(offset_of_nested)]
 
 use std::marker::PhantomData;
 use std::mem::offset_of;
diff --git a/tests/pretty/offset_of.rs b/tests/pretty/offset_of.rs
index e1783432857e2..1307c335ad322 100644
--- a/tests/pretty/offset_of.rs
+++ b/tests/pretty/offset_of.rs
@@ -1,4 +1,3 @@
 // pp-exact
-#![feature(offset_of)]
 
 fn main() { std::mem::offset_of!(std :: ops :: Range < usize >, end); }
diff --git a/tests/ui/layout/issue-112048-unsizing-niche.rs b/tests/ui/layout/issue-112048-unsizing-niche.rs
index 23588ba36ee59..e59e063df99be 100644
--- a/tests/ui/layout/issue-112048-unsizing-niche.rs
+++ b/tests/ui/layout/issue-112048-unsizing-niche.rs
@@ -2,7 +2,6 @@
 
 // Check that unsizing does not change which field is considered for niche layout.
 
-#![feature(offset_of)]
 #![allow(dead_code)]
 
 #[derive(Clone)]

From 7924c9bcdfa0ec5980474ac680439d7fc2a4690f Mon Sep 17 00:00:00 2001
From: George Bateman <george.bateman16@gmail.com>
Date: Fri, 19 Jan 2024 20:29:40 +0000
Subject: [PATCH 3/3] Split remaining offset_of features into new tracking
 issues

---
 compiler/rustc_feature/src/unstable.rs            |  4 ++--
 compiler/rustc_hir_typeck/src/expr.rs             |  2 +-
 .../feature-gate-offset-of-enum.stderr            |  4 ++--
 .../feature-gate-offset-of-nested.stderr          | 15 ++++++++++-----
 4 files changed, 15 insertions(+), 10 deletions(-)

diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index c512ccc90db5c..371b651f5e857 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -549,9 +549,9 @@ declare_features! (
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
     (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
     /// Allows using enums in offset_of!
-    (unstable, offset_of_enum, "1.75.0", Some(106655)),
+    (unstable, offset_of_enum, "1.75.0", Some(120141)),
     /// Allows using multiple nested field accesses in offset_of!
-    (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(106655)),
+    (unstable, offset_of_nested, "CURRENT_RUSTC_VERSION", Some(120140)),
     /// Allows using `#[optimize(X)]`.
     (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 242e8dc95e23c..33d7ba6268a20 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -3250,7 +3250,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && !self.tcx.features().offset_of_nested
         {
             rustc_session::parse::feature_err(
-                &self.tcx.sess.parse_sess,
+                &self.tcx.sess,
                 sym::offset_of_nested,
                 ident_2.span,
                 "only a single ident or integer is stable as the field in offset_of",
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
index 02ee54e8607ac..fc7dd7923f7a8 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
+++ b/tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
@@ -13,7 +13,7 @@ error[E0658]: using enums in offset_of is experimental
 LL |     offset_of!(Alpha, One);
    |                       ^^^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120141 <https://github.com/rust-lang/rust/issues/120141> for more information
    = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
@@ -29,7 +29,7 @@ error[E0658]: using enums in offset_of is experimental
 LL |     offset_of!(Alpha, Two.0);
    |                       ^^^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120141 <https://github.com/rust-lang/rust/issues/120141> for more information
    = help: add `#![feature(offset_of_enum)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
diff --git a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
index ebc251fd66307..f367fc9fa0dd4 100644
--- a/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
+++ b/tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
@@ -4,8 +4,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of
 LL |     offset_of!(Alpha, Two.0);
    |                           ^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
    = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: only a single ident or integer is stable as the field in offset_of
   --> $DIR/feature-gate-offset-of-nested.rs:24:33
@@ -19,8 +20,9 @@ LL | |     offset_of!((S, ()), 0.c);
 LL | |     offset_of!(S, c.t);
 ...  |
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
    = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: this error originates in the macro `offset_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0658]: only a single ident or integer is stable as the field in offset_of
@@ -29,8 +31,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of
 LL |     offset_of!(S, b.0);
    |                     ^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
    = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: only a single ident or integer is stable as the field in offset_of
   --> $DIR/feature-gate-offset-of-nested.rs:26:27
@@ -38,8 +41,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of
 LL |     offset_of!((S, ()), 0.c);
    |                           ^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
    = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: only a single ident or integer is stable as the field in offset_of
   --> $DIR/feature-gate-offset-of-nested.rs:27:21
@@ -47,8 +51,9 @@ error[E0658]: only a single ident or integer is stable as the field in offset_of
 LL |     offset_of!(S, c.t);
    |                     ^
    |
-   = note: see issue #106655 <https://github.com/rust-lang/rust/issues/106655> for more information
+   = note: see issue #120140 <https://github.com/rust-lang/rust/issues/120140> for more information
    = help: add `#![feature(offset_of_nested)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error: aborting due to 5 previous errors