Skip to content

Commit

Permalink
Rollup merge of rust-lang#118799 - GKFX:stabilize-simple-offsetof, r=…
Browse files Browse the repository at this point in the history
…wesleywiser

Stabilize single-field offset_of

This PR stabilizes offset_of for a single field. There has been some further discussion at rust-lang#106655 about whether this is advisable; I'm opening the PR anyway so that the code is available.
  • Loading branch information
matthiaskrgr committed Jan 20, 2024
2 parents 17c95b6 + 7924c9b commit 6f67208
Show file tree
Hide file tree
Showing 35 changed files with 145 additions and 56 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_error_codes/src/error_codes/E0795.md
Original file line number Diff line number Diff line change
Expand Up @@ -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);
```
Expand All @@ -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);
```
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,7 +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(120140)),
/// Allows using `#[optimize(X)]`.
(unstable, optimize_attribute, "1.34.0", Some(54882)),
/// Allows macro attributes on expressions, statements and non-inline modules.
Expand Down
12 changes: 12 additions & 0 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
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();
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,7 @@ symbols! {
offset,
offset_of,
offset_of_enum,
offset_of_nested,
ok_or_else,
omit_gdb_pretty_printer_section,
on,
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -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)]
Expand Down
14 changes: 6 additions & 8 deletions library/core/src/mem/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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>;
Expand Down Expand Up @@ -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)]
Expand Down Expand Up @@ -1396,15 +1394,15 @@ 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
crate::hint::must_use({builtin # offset_of($Container, $($fields)+)})
}

#[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).+ $(,)?) {
Expand Down
2 changes: 1 addition & 1 deletion library/core/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down Expand Up @@ -115,7 +116,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)]
Expand Down
1 change: 0 additions & 1 deletion library/std/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/const_prop/offset_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion tests/mir-opt/dataflow-const-prop/offset_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 0 additions & 1 deletion tests/pretty/offset_of.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
// pp-exact
#![feature(offset_of)]

fn main() { std::mem::offset_of!(std :: ops :: Range < usize >, end); }
2 changes: 1 addition & 1 deletion tests/ui/feature-gates/feature-gate-offset-of-enum.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(offset_of)]
#![feature(offset_of_nested)]

use std::mem::offset_of;

Expand Down
4 changes: 2 additions & 2 deletions tests/ui/feature-gates/feature-gate-offset-of-enum.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

Expand Down
28 changes: 28 additions & 0 deletions tests/ui/feature-gates/feature-gate-offset-of-nested.rs
Original file line number Diff line number Diff line change
@@ -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
}
60 changes: 60 additions & 0 deletions tests/ui/feature-gates/feature-gate-offset-of-nested.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
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 #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
|
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 #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
--> $DIR/feature-gate-offset-of-nested.rs:25:21
|
LL | offset_of!(S, b.0);
| ^
|
= 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
|
LL | offset_of!((S, ()), 0.c);
| ^
|
= 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
|
LL | offset_of!(S, c.t);
| ^
|
= 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

For more information about this error, try `rustc --explain E0658`.
1 change: 0 additions & 1 deletion tests/ui/layout/issue-112048-unsizing-niche.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lint/dead-code/offset-of-correct-param-env.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/lint/dead-code/offset-of.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(offset_of)]
#![feature(offset_of_nested)]
#![deny(dead_code)]

use std::mem::offset_of;
Expand Down
2 changes: 0 additions & 2 deletions tests/ui/offset-of/offset-of-arg-count.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
#![feature(offset_of)]

use std::mem::offset_of;

fn main() {
Expand Down
14 changes: 7 additions & 7 deletions tests/ui/offset-of/offset-of-arg-count.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand All @@ -17,33 +17,33 @@ 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
|
= 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..,);
| ^^^
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/offset-of/offset-of-dst-field.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(offset_of, extern_types)]
#![feature(extern_types)]

use std::mem::offset_of;

Expand Down
2 changes: 1 addition & 1 deletion tests/ui/offset-of/offset-of-enum.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#![feature(offset_of, offset_of_enum)]
#![feature(offset_of_enum, offset_of_nested)]

use std::mem::offset_of;

Expand Down
2 changes: 0 additions & 2 deletions tests/ui/offset-of/offset-of-inference.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
// Test that inference types in `offset_of!` don't ICE.

#![feature(offset_of)]

struct Foo<T> {
x: T,
}
Expand Down
2 changes: 1 addition & 1 deletion tests/ui/offset-of/offset-of-inference.stderr
Original file line number Diff line number Diff line change
@@ -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
Expand Down
Loading

0 comments on commit 6f67208

Please sign in to comment.