@@ -1294,13 +1294,63 @@ impl<T> SizedTypeProperties for T {}
1294
1294
///
1295
1295
/// Structs, enums, unions and tuples are supported.
1296
1296
///
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.
1298
1298
///
1299
1299
/// Enum variants may be traversed as if they were fields. Variants themselves do
1300
1300
/// not have an offset.
1301
1301
///
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
+ ///
1302
1318
/// 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
+ /// struct Wrapper<T, U>(T, U);
1332
+ ///
1333
+ /// type A = Wrapper<u8, u8>;
1334
+ /// type B = Wrapper<u8, i8>;
1335
+ ///
1336
+ /// // Not necessarily identical even though `u8` and `i8` have the same layout!
1337
+ /// // assert!(mem::offset_of!(A, 1), mem::offset_of!(B, 1));
1338
+ ///
1339
+ /// #[repr(transparent)]
1340
+ /// struct U8(u8);
1341
+ ///
1342
+ /// type C = Wrapper<u8, U8>;
1343
+ ///
1344
+ /// // Not necessarily identical even though `u8` and `U8` have the same layout!
1345
+ /// // assert!(mem::offset_of!(A, 1), mem::offset_of!(C, 1));
1346
+ ///
1347
+ /// struct Empty<T>(core::marker::PhantomData<T>);
1348
+ ///
1349
+ /// // Not necessarily identical even though `PhantomData` always has the same layout!
1350
+ /// // assert!(mem::offset_of!(Empty<u8>, 0), mem::offset_of!(Empty<i8>, 0));
1351
+ /// ```
1352
+ ///
1353
+ /// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations
1304
1354
///
1305
1355
/// # Examples
1306
1356
///
@@ -1329,6 +1379,17 @@ impl<T> SizedTypeProperties for T {}
1329
1379
///
1330
1380
/// assert_eq!(mem::offset_of!(NestedA, b.0), 0);
1331
1381
///
1382
+ /// #[repr(u8)]
1383
+ /// enum Enum {
1384
+ /// A(u8, u16),
1385
+ /// B { one: u8, two: u16 },
1386
+ /// }
1387
+ ///
1388
+ /// # #[cfg(not(bootstrap))]
1389
+ /// assert_eq!(mem::offset_of!(Enum, A.0), 1);
1390
+ /// # #[cfg(not(bootstrap))]
1391
+ /// assert_eq!(mem::offset_of!(Enum, B.two), 2);
1392
+ ///
1332
1393
/// # #[cfg(not(bootstrap))]
1333
1394
/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
1334
1395
/// ```
0 commit comments