@@ -1254,42 +1254,56 @@ impl<T> SizedTypeProperties for T {}
12541254
12551255/// Expands to the offset in bytes of a field from the beginning of the given type. 
12561256/// 
1257- /// Structs, enums, unions and tuples are supported . 
1257+ /// The type may be a `struct`, `enum`, `union`, or tuple . 
12581258/// 
1259- /// Nested field accesses may be used, but not array indexes. 
1259+ /// The field may be a nested field (`field1.field2`), but not an array index. 
1260+ /// The field must be visible to the call site. 
12601261/// 
1261- /// If the nightly-only feature `offset_of_enum` is enabled, 
1262- /// variants may be traversed as if they were fields. 
1263- /// Variants themselves do not have an offset. 
1262+ /// The offset is returned as a [`usize`]. 
12641263/// 
1265- /// Visibility is respected - all types  and fields must be visible to the call site:  
1264+ /// # Offsets of,  and in, dynamically sized types  
12661265/// 
1267- /// ``` 
1268- /// mod nested { 
1269- ///     #[repr(C)] 
1270- ///     pub struct Struct { 
1271- ///         private: u8, 
1272- ///     } 
1273- /// } 
1266+ /// The field’s type must be [`Sized`], but it may be located in a [dynamically sized] container. 
1267+ /// If the field type is dynamically sized, then you cannot use `offset_of!` (since the field's 
1268+ /// alignment, and therefore its offset, may also be dynamic) and must take the offset from an 
1269+ /// actual pointer to the container instead. 
12741270/// 
1275- /// // assert_eq!(mem::offset_of!(nested::Struct, private), 0); 
1276- /// // ^^^ error[E0616]: field `private` of struct `Struct` is private 
1277- /// ``` 
1278- /// 
1279- /// Only [`Sized`] fields are supported, but the container may be unsized: 
12801271/// ``` 
12811272/// # use core::mem; 
1273+ /// # use core::fmt::Debug; 
12821274/// #[repr(C)] 
1283- /// pub struct Struct { 
1275+ /// pub struct Struct<T: ?Sized>  { 
12841276///     a: u8, 
1285- ///     b: [u8] , 
1277+ ///     b: T , 
12861278/// } 
12871279/// 
1288- /// assert_eq!(mem::offset_of!(Struct, a), 0); // OK 
1289- /// // assert_eq!(mem::offset_of!(Struct, b), 1); 
1290- /// // ^^^ error[E0277]: doesn't have a size known at compile-time 
1280+ /// #[derive(Debug)] 
1281+ /// #[repr(C, align(4))] 
1282+ /// struct Align4(u32); 
1283+ /// 
1284+ /// assert_eq!(mem::offset_of!(Struct<dyn Debug>, a), 0); // OK — Sized field 
1285+ /// assert_eq!(mem::offset_of!(Struct<Align4>, b), 4); // OK — not DST 
1286+ /// 
1287+ /// // assert_eq!(mem::offset_of!(Struct<dyn Debug>, b), 1); 
1288+ /// // ^^^ error[E0277]: ... cannot be known at compilation time 
1289+ /// 
1290+ /// // To obtain the offset of a !Sized field, examine a concrete value 
1291+ /// // instead of using offset_of!. 
1292+ /// let value: Struct<Align4> = Struct { a: 1, b: Align4(2) }; 
1293+ /// let ref_unsized: &Struct<dyn Debug> = &value; 
1294+ /// let offset_of_b = unsafe { 
1295+ ///     (&raw const ref_unsized.b).byte_offset_from_unsigned(ref_unsized) 
1296+ /// }; 
1297+ /// assert_eq!(offset_of_b, 4); 
12911298/// ``` 
12921299/// 
1300+ /// If you need to obtain the offset of a field of a `!Sized` type, then, since the offset may 
1301+ /// depend on the particular value being stored (in particular, `dyn Trait` values have a 
1302+ /// dynamically-determined alignment), you must retrieve the offset from a specific reference 
1303+ /// or pointer, and so you cannot use `offset_of!` to work without one. 
1304+ /// 
1305+ /// # Layout is subject to change 
1306+ /// 
12931307/// Note that type layout is, in general, [subject to change and 
12941308/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If 
12951309/// layout stability is required, consider using an [explicit `repr` attribute]. 
@@ -1325,11 +1339,16 @@ impl<T> SizedTypeProperties for T {}
13251339/// 
13261340/// [explicit `repr` attribute]: https://doc.rust-lang.org/reference/type-layout.html#representations 
13271341/// 
1342+ /// # Unstable features 
1343+ /// 
1344+ /// The following unstable features expand the functionality of `offset_of!`: 
1345+ /// 
1346+ /// * [`offset_of_enum`] — allows `enum` variants to be traversed as if they were fields. 
1347+ /// * [`offset_of_slice`] — allows getting the offset of a field of type `[T]`. 
1348+ /// 
13281349/// # Examples 
13291350/// 
13301351/// ``` 
1331- /// #![feature(offset_of_enum)] 
1332- /// 
13331352/// use std::mem; 
13341353/// #[repr(C)] 
13351354/// struct FieldStruct { 
@@ -1351,18 +1370,11 @@ impl<T> SizedTypeProperties for T {}
13511370/// struct NestedB(u8); 
13521371/// 
13531372/// assert_eq!(mem::offset_of!(NestedA, b.0), 0); 
1354- /// 
1355- /// #[repr(u8)] 
1356- /// enum Enum { 
1357- ///     A(u8, u16), 
1358- ///     B { one: u8, two: u16 }, 
1359- /// } 
1360- /// 
1361- /// assert_eq!(mem::offset_of!(Enum, A.0), 1); 
1362- /// assert_eq!(mem::offset_of!(Enum, B.two), 2); 
1363- /// 
1364- /// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0); 
13651373/// ``` 
1374+ /// 
1375+ /// [dynamically sized]: https://doc.rust-lang.org/reference/dynamically-sized-types.html 
1376+ /// [`offset_of_enum`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-enum.html 
1377+ /// [`offset_of_slice`]: https://doc.rust-lang.org/nightly/unstable-book/language-features/offset-of-slice.html 
13661378#[ stable( feature = "offset_of" ,  since = "1.77.0" ) ]  
13671379#[ allow_internal_unstable( builtin_syntax) ]  
13681380pub  macro offset_of ( $Container: ty,  $( $fields: expr) + $( , ) ?)  { 
0 commit comments