Skip to content

Commit 6901197

Browse files
committed
Auto merge of rust-lang#148151 - cjgillot:no-offset-of, r=scottmcm
Replace OffsetOf by an actual sum of calls to intrinsic. This PR changes the way we compute the value of the `offset_of!` macro in MIR. The current implementation uses a dedicated MIR rvalue. This PR proposes to replace it by an inline constant which sums calls to a new intrinsic `offset_of(variant index, field index)`. The desugaring is done at THIR building time, easier that doing it on MIR. The new intrinsic is only meant to be used by const-eval. LLVM codegen will refuse to generate code for it. We replace: ```rust a = offset_of!(T, Variant1.Field1.Variant2.Field2); ``` By: ```rust a = const {constant#n}; {constant#n}: usize = { _1 = offset_of::<T>(index of Variant1, index of Field1); _2 = offset_of::<U>(index of Variant2, index of Field2); // Where T::Variant1::Field1 has type U _0 = _1 + _2 } ``` The second commit modifies intrinsic const checking to take `allow_internal_unstable` into account. The new intrinsic should only be called from stable `offset_of!` macro. The intrinsic itself is unstable, const-unstable, but `rustc_intrinsic_const_stable_indirect`. Fixes rust-lang#123959 Fixes rust-lang#125680 Fixes rust-lang#129425 Fixes rust-lang#136175 r? `@ghost`
2 parents f381402 + c3a864f commit 6901197

File tree

2 files changed

+22
-2
lines changed

2 files changed

+22
-2
lines changed

core/src/intrinsics/mod.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,6 +2791,26 @@ pub const fn size_of<T>() -> usize;
27912791
#[rustc_intrinsic]
27922792
pub const fn align_of<T>() -> usize;
27932793

2794+
/// The offset of a field inside a type.
2795+
///
2796+
/// Note that, unlike most intrinsics, this is safe to call;
2797+
/// it does not require an `unsafe` block.
2798+
/// Therefore, implementations must not require the user to uphold
2799+
/// any safety invariants.
2800+
///
2801+
/// This intrinsic can only be evaluated at compile-time, and should only appear in
2802+
/// constants or inline const blocks.
2803+
///
2804+
/// The stabilized version of this intrinsic is [`core::mem::offset_of`].
2805+
/// This intrinsic is also a lang item so `offset_of!` can desugar to calls to it.
2806+
#[rustc_nounwind]
2807+
#[unstable(feature = "core_intrinsics", issue = "none")]
2808+
#[rustc_const_unstable(feature = "core_intrinsics", issue = "none")]
2809+
#[rustc_intrinsic_const_stable_indirect]
2810+
#[rustc_intrinsic]
2811+
#[lang = "offset_of"]
2812+
pub const fn offset_of<T: PointeeSized>(variant: u32, field: u32) -> usize;
2813+
27942814
/// Returns the number of variants of the type `T` cast to a `usize`;
27952815
/// if `T` has no variants, returns `0`. Uninhabited variants will be counted.
27962816
///

core/src/mem/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,10 +1424,10 @@ impl<T> SizedTypeProperties for T {}
14241424
/// [`offset_of_enum`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-enum.html
14251425
/// [`offset_of_slice`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-slice.html
14261426
#[stable(feature = "offset_of", since = "1.77.0")]
1427-
#[allow_internal_unstable(builtin_syntax)]
1427+
#[allow_internal_unstable(builtin_syntax, core_intrinsics)]
14281428
pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) {
14291429
// The `{}` is for better error messages
1430-
{builtin # offset_of($Container, $($fields)+)}
1430+
const {builtin # offset_of($Container, $($fields)+)}
14311431
}
14321432

14331433
/// Create a fresh instance of the inhabited ZST type `T`.

0 commit comments

Comments
 (0)