diff options
| author | DrMeepster <19316085+DrMeepster@users.noreply.github.com> | 2022-09-11 00:37:49 -0700 |
|---|---|---|
| committer | DrMeepster <19316085+DrMeepster@users.noreply.github.com> | 2023-04-21 02:14:02 -0700 |
| commit | 511e457c4ba88097ee46ef07b7ef80ce4dd4a3c5 (patch) | |
| tree | 9aed1b0210cfd3c784a7c5cc89646b8d9dad5427 /library/core | |
| parent | b92a41c6760801a7128ca0ec69ba4ba9c9194054 (diff) | |
| download | rust-511e457c4ba88097ee46ef07b7ef80ce4dd4a3c5.tar.gz rust-511e457c4ba88097ee46ef07b7ef80ce4dd4a3c5.zip | |
offset_of
Diffstat (limited to 'library/core')
| -rw-r--r-- | library/core/src/mem/mod.rs | 42 | ||||
| -rw-r--r-- | library/core/tests/lib.rs | 1 | ||||
| -rw-r--r-- | library/core/tests/mem.rs | 74 |
3 files changed, 117 insertions, 0 deletions
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 30ec73cabf8..85745334e9f 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1279,3 +1279,45 @@ pub trait SizedTypeProperties: Sized { #[doc(hidden)] #[unstable(feature = "sized_type_properties", issue = "none")] impl<T> SizedTypeProperties for T {} + +/// Expands to the offset in bytes of a field from the beginning of the given type. +/// +/// Only structs, unions and tuples are supported. +/// +/// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof`. +/// +/// Note that the output of this macro is not stable, except for `#[repr(C)]` types. +/// +/// # Examples +/// +/// ``` +/// #![feature(offset_of)] +/// +/// use std::mem; +/// #[repr(C)] +/// struct FieldStruct { +/// first: u8, +/// second: u16, +/// third: u8 +/// } +/// +/// assert_eq!(mem::offset_of!(FieldStruct, first), 0); +/// assert_eq!(mem::offset_of!(FieldStruct, second), 2); +/// assert_eq!(mem::offset_of!(FieldStruct, third), 4); +/// +/// #[repr(C)] +/// struct NestedA { +/// b: NestedB +/// } +/// +/// #[repr(C)] +/// struct NestedB(u8); +/// +/// assert_eq!(mem::offset_of!(NestedA, b.0), 0); +/// ``` +#[unstable(feature = "offset_of", issue = "106655")] +#[rustc_builtin_macro] +#[cfg(not(bootstrap))] +pub macro offset_of($Container:ty, $($fields:tt).+ $(,)?) { + // ...implementation defined... +} diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs index f460da35dd3..84859a54c26 100644 --- a/library/core/tests/lib.rs +++ b/library/core/tests/lib.rs @@ -109,6 +109,7 @@ #![feature(utf8_chunks)] #![feature(is_ascii_octdigit)] #![feature(get_many_mut)] +#![cfg_attr(not(bootstrap), feature(offset_of))] #![deny(unsafe_op_in_unsafe_fn)] #![deny(fuzzy_provenance_casts)] diff --git a/library/core/tests/mem.rs b/library/core/tests/mem.rs index f7740a114e7..c08fc6fd2fb 100644 --- a/library/core/tests/mem.rs +++ b/library/core/tests/mem.rs @@ -364,3 +364,77 @@ fn const_maybe_uninit() { assert_eq!(FIELD_BY_FIELD, Foo { x: 1, y: 2 }); } + +#[test] +#[cfg(not(bootstrap))] +fn offset_of() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + z: Bar, + } + + #[repr(C)] + struct Bar(u8, u8); + + assert_eq!(offset_of!(Foo, x), 0); + assert_eq!(offset_of!(Foo, y), 2); + assert_eq!(offset_of!(Foo, z.0), 4); + assert_eq!(offset_of!(Foo, z.1), 5); + + // Layout of tuples is unstable + assert!(offset_of!((u8, u16), 0) <= size_of::<(u8, u16)>() - 1); + assert!(offset_of!((u8, u16), 1) <= size_of::<(u8, u16)>() - 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn const_offset_of() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + } + + const X_OFFSET: usize = offset_of!(Foo, x); + const Y_OFFSET: usize = offset_of!(Foo, y); + + assert_eq!(X_OFFSET, 0); + assert_eq!(Y_OFFSET, 2); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_without_const_promotion() { + #[repr(C)] + struct Foo<SuppressConstPromotion> { + x: u8, + y: u16, + _scp: SuppressConstPromotion, + } + + // Normally, offset_of is always const promoted. + // The generic parameter prevents this from happening. + // This is needed to test the codegen impl of offset_of + fn inner<SuppressConstPromotion>() { + assert_eq!(offset_of!(Foo<SuppressConstPromotion>, x), 0); + assert_eq!(offset_of!(Foo<SuppressConstPromotion>, y), 2); + } + + inner::<()>(); +} + +#[test] +#[cfg(not(bootstrap))] +fn offset_of_dst() { + #[repr(C)] + struct Foo { + x: u8, + y: u16, + slice: [u8], + } + + assert_eq!(offset_of!(Foo, x), 0); + assert_eq!(offset_of!(Foo, y), 2); +} |
