@@ -1249,42 +1249,60 @@ impl<T> SizedTypeProperties for T {}
12491249
12501250/// Expands to the offset in bytes of a field from the beginning of the given type.
12511251///
1252- /// Structs, enums, unions and tuples are supported .
1252+ /// The type may be a `struct`, `enum`, `union`, or tuple .
12531253///
1254- /// Nested field accesses may be used, but not array indexes.
1254+ /// The field may be a nested field (`field1.field2`), but not an array index.
1255+ /// The field must be visible to the call site.
1256+ ///
1257+ /// The offset is returned as a [`usize`].
12551258///
12561259/// If the nightly-only feature `offset_of_enum` is enabled,
1257- /// variants may be traversed as if they were fields.
1260+ /// `enum` variants may be traversed as if they were fields.
12581261/// Variants themselves do not have an offset.
12591262///
1260- /// Visibility is respected - all types and fields must be visible to the call site:
1261- ///
1262- /// ```
1263- /// mod nested {
1264- /// #[repr(C)]
1265- /// pub struct Struct {
1266- /// private: u8,
1267- /// }
1268- /// }
1263+ /// # Offsets of, and in, dynamically sized types
12691264///
1270- /// // assert_eq!(mem::offset_of!(nested::Struct, private), 0);
1271- /// // ^^^ error[E0616]: field `private` of struct `Struct` is private
1272- /// ```
1265+ /// The field’s type must be [`Sized`], but it may be located in a [dynamically sized] container.
1266+ /// If the field type is dynamically sized, then you cannot use `offset_of!` (since the field's
1267+ /// alignment, and therefore its offset, may also be dynamic) and must take the offset from an
1268+ /// actual pointer to the container instead.
12731269///
1274- /// Only [`Sized`] fields are supported, but the container may be unsized:
12751270/// ```
12761271/// # use core::mem;
1272+ /// # use core::fmt::Debug;
12771273/// #[repr(C)]
1278- /// pub struct Struct {
1274+ /// pub struct Struct<T: ?Sized> {
12791275/// a: u8,
1280- /// b: [u8] ,
1276+ /// b: T ,
12811277/// }
12821278///
1283- /// assert_eq!(mem::offset_of!(Struct, a), 0); // OK
1284- /// // assert_eq!(mem::offset_of!(Struct, b), 1);
1285- /// // ^^^ error[E0277]: doesn't have a size known at compile-time
1279+ /// #[derive(Debug)]
1280+ /// #[repr(C, align(4))]
1281+ /// struct Align4(u32);
1282+ ///
1283+ /// assert_eq!(mem::offset_of!(Struct<dyn Debug>, a), 0); // OK — Sized field
1284+ /// assert_eq!(mem::offset_of!(Struct<Align4>, b), 4); // OK — not DST
1285+ ///
1286+ /// // assert_eq!(mem::offset_of!(Struct<dyn Debug>, b), 1);
1287+ /// // ^^^ error[E0277]: ... cannot be known at compilation time
1288+ ///
1289+ /// // To obtain the offset of a !Sized field, examine a concrete value
1290+ /// // instead of using offset_of!.
1291+ /// let value: Struct<Align4> = Struct { a: 1, b: Align4(2) };
1292+ /// let ref_unsized: &Struct<dyn Debug> = &value;
1293+ /// let offset_of_b = unsafe {
1294+ /// (&raw const ref_unsized.b).byte_offset_from_unsigned(ref_unsized)
1295+ /// };
1296+ /// assert_eq!(offset_of_b, 4);
12861297/// ```
12871298///
1299+ /// If you need to obtain the offset of a field of a `!Sized` type, then, since the offset may
1300+ /// depend on the particular value being stored (in particular, `dyn Trait` values have a
1301+ /// dynamically-determined alignment), you must retrieve the offset from a specific reference
1302+ /// or pointer, and so you cannot use `offset_of!` to work without one.
1303+ ///
1304+ /// # Layout is subject to change
1305+ ///
12881306/// Note that type layout is, in general, [subject to change and
12891307/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If
12901308/// layout stability is required, consider using an [explicit `repr` attribute].
@@ -1358,6 +1376,8 @@ impl<T> SizedTypeProperties for T {}
13581376///
13591377/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
13601378/// ```
1379+ ///
1380+ /// [dynamically sized]: https://doc.rust-lang.org/reference/dynamically-sized-types.html
13611381#[ stable( feature = "offset_of" , since = "1.77.0" ) ]
13621382#[ allow_internal_unstable( builtin_syntax) ]
13631383pub macro offset_of ( $Container: ty, $( $fields: expr) + $( , ) ?) {
0 commit comments