@@ -1294,13 +1294,64 @@ impl<T> SizedTypeProperties for T {}
12941294///
12951295/// Structs, enums, unions and tuples are supported.
12961296///
1297- /// Nested field accesses may be used, but not array indexes like in `C`'s `offsetof` .
1297+ /// Nested field accesses may be used, but not array indexes.
12981298///
12991299/// Enum variants may be traversed as if they were fields. Variants themselves do
13001300/// not have an offset.
13011301///
1302+ /// Visibility is respected - all types and fields must be visible to the call site:
1303+ ///
1304+ /// ```
1305+ /// #![feature(offset_of)]
1306+ ///
1307+ /// mod nested {
1308+ /// #[repr(C)]
1309+ /// pub struct Struct {
1310+ /// private: u8,
1311+ /// }
1312+ /// }
1313+ ///
1314+ /// // assert_eq!(mem::offset_of!(nested::Struct, private), 0);
1315+ /// // ^^^ error[E0616]: field `private` of struct `Struct` is private
1316+ /// ```
1317+ ///
13021318/// Note that type layout is, in general, [subject to change and
1303- /// platform-specific](https://doc.rust-lang.org/reference/type-layout.html).
1319+ /// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If
1320+ /// layout stability is required, consider using an [explicit `repr` attribute].
1321+ ///
1322+ /// Rust guarantees that the offset of a given field within a given type will not
1323+ /// change over the lifetime of the program. However, two different compilations of
1324+ /// the same program may result in different layouts. Also, even within a single
1325+ /// program execution, no guarantees are made about types which are *similar* but
1326+ /// not *identical*, e.g.:
1327+ ///
1328+ /// ```
1329+ /// #![feature(offset_of)]
1330+ ///
1331+ /// use std::mem;
1332+ /// struct Wrapper<T, U>(T, U);
1333+ ///
1334+ /// type A = Wrapper<u8, u8>;
1335+ /// type B = Wrapper<u8, i8>;
1336+ ///
1337+ /// // Not necessarily identical even though `u8` and `i8` have the same layout!
1338+ /// // assert!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));
1339+ ///
1340+ /// #[repr(transparent)]
1341+ /// struct U8(u8);
1342+ ///
1343+ /// type C = Wrapper<u8, U8>;
1344+ ///
1345+ /// // Not necessarily identical even though `u8` and `U8` have the same layout!
1346+ /// // assert!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));
1347+ ///
1348+ /// struct Empty<T>(PhantomData<T>);
1349+ ///
1350+ /// // Not necessarily identical even though `PhantomData` always has the same layout!
1351+ /// // assert!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
1352+ /// ```
1353+ ///
1354+ /// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations
13041355///
13051356/// # Examples
13061357///
@@ -1329,6 +1380,15 @@ impl<T> SizedTypeProperties for T {}
13291380///
13301381/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
13311382///
1383+ /// #[repr(u8)]
1384+ /// enum Enum {
1385+ /// A(u8, u16),
1386+ /// B { one: u8, two: u16 },
1387+ /// }
1388+ ///
1389+ /// assert_eq!(mem::offset_of!(Enum, A.0), 1);
1390+ /// assert_eq!(mem::offset_of!(Enum, B.two), 2);
1391+ ///
13321392/// # #[cfg(not(bootstrap))]
13331393/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
13341394/// ```
0 commit comments