@@ -1249,42 +1249,60 @@ impl<T> SizedTypeProperties for T {}
1249
1249
1250
1250
/// Expands to the offset in bytes of a field from the beginning of the given type.
1251
1251
///
1252
- /// Structs, enums, unions and tuples are supported .
1252
+ /// The type may be a `struct`, `enum`, `union`, or tuple .
1253
1253
///
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`].
1255
1258
///
1256
1259
/// 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.
1258
1261
/// Variants themselves do not have an offset.
1259
1262
///
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
1269
1264
///
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.
1273
1269
///
1274
- /// Only [`Sized`] fields are supported, but the container may be unsized:
1275
1270
/// ```
1276
1271
/// # use core::mem;
1272
+ /// # use core::fmt::Debug;
1277
1273
/// #[repr(C)]
1278
- /// pub struct Struct {
1274
+ /// pub struct Struct<T: ?Sized> {
1279
1275
/// a: u8,
1280
- /// b: [u8] ,
1276
+ /// b: T ,
1281
1277
/// }
1282
1278
///
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);
1286
1297
/// ```
1287
1298
///
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
+ ///
1288
1306
/// Note that type layout is, in general, [subject to change and
1289
1307
/// platform-specific](https://doc.rust-lang.org/reference/type-layout.html). If
1290
1308
/// layout stability is required, consider using an [explicit `repr` attribute].
@@ -1358,6 +1376,8 @@ impl<T> SizedTypeProperties for T {}
1358
1376
///
1359
1377
/// assert_eq!(mem::offset_of!(Option<&u8>, Some.0), 0);
1360
1378
/// ```
1379
+ ///
1380
+ /// [dynamically sized]: https://doc.rust-lang.org/reference/dynamically-sized-types.html
1361
1381
#[ stable( feature = "offset_of" , since = "1.77.0" ) ]
1362
1382
#[ allow_internal_unstable( builtin_syntax) ]
1363
1383
pub macro offset_of ( $Container: ty, $( $fields: expr) + $( , ) ?) {
0 commit comments