@@ -270,6 +270,9 @@ considered:
270270 formats or binary serialization formats that contain descriptions of the
271271 field offsets for the record types they contain, etc.
272272
273+ It is also useful for implementing field projection as a library feature, as
274+ in cases like [ ` field-offset ` ] [ fieldoffset ] .
275+
2732763 . Require that all fields of ` $Container ` be visible at the invocation site,
274277 rather than just requiring that ` $field ` is.
275278
@@ -308,6 +311,26 @@ considered:
308311 Additionally, this does not generalize as well to some of the extensions in
309312 future work.
310313
314+ 8 . Expose a high level type-safe API instead, where ` offset_of ` returns a type
315+ with phantom parameters for container and field (for example, see the
316+ [ ` field-offset ` ] [ fieldoffset ] crate, and the notes on it in the Prior Art
317+ section below):
318+
319+ This is not pursued for a few reasons:
320+
321+ 1 . Field projection is just one of several use cases for getting the offset
322+ to a field, rather than the only one, or even the most common one. While
323+ the other uses could be supported by a function which returns the
324+ ` usize ` , it seems better to push this kind of thing into the ecosystem.
325+
326+ 2 . Add this to the stdlib risks conflicting with or restricting our ability
327+ to add a lang feature for field projection and/or pointer-to-member
328+ functionality.
329+
330+ None of those are deal-breakers, but it seems better to keep this simple and
331+ limited. Such a type-safe API can be implemented on top of a ` offset_of! `
332+ which returns integers.
333+
311334# Prior art
312335[ prior-art ] : #prior-art
313336
@@ -349,9 +372,20 @@ popular, and provide this functionality in different ways.
349372
350373 It does not support use during constant evaluation.
351374
375+ - The [ ` field-offset ` ] [ fieldoffset ] crate provides a higher level type-safe API
376+ for field offsets similar to the pointer-to-member functionality in C++. It
377+ uses ` memoffset ` to implement ` offset_of! ` .
378+
379+ Calling ` field_offset::offset_of! ` returns a ` FieldOffset<Field, Container> `
380+ structure, which transparently wraps ` usize ` and while providing phantom
381+ annotations to ensure it is used with the correct container and field type.
382+ It uses this to provide some generic field projection functionality, mostly
383+ around ` Pin ` .
384+
352385[ memoffset ] : https://crates.io/crates/memoffset/0.6.5
353386[ bmuckcrate ] : https://crates.io/crates/bytemuck/1.12.1
354387[ bmuckoffset ] : https://docs.rs/bytemuck/1.12.1/bytemuck/macro.offset_of.html
388+ [ fieldoffset ] : https://crates.io/crates/field-offset/0.3.4
355389
356390## Prior Art: Languages
357391
@@ -519,15 +553,19 @@ The only case where we currently do *not* know the offset of a field statically
519553is when the user has requested the offset of the unsized field, and the unsized
520554field is a trait object.
521555
522- There are valid reasons to want to get the offset of:
556+ It's possible for us to provide the offset of for:
557+
5235581 . The fields before the unsized field, as in ` offset_of!((i32, dyn Send), 0) ` .
524- 2 . The unsized field if it's a ` [T] ` , ` str ` , or other case where the offset does
525- not depend on reading the metadata, as in ` offset_of!((i32, [u16]), 1) ` .
526559
527- Allowing these is somewhat inconsistent with ` align_of ` , which could provide the
528- alignment in some cases, but forbids it for all ` ?Sized ` types (admittedly,
529- allowing ` align_of::<[T]>() ` is not particularly compelling, as it's always the
530- same as ` align_of::<T>() ` ).
560+ 2 . The unsized field itself if it is a type which whose offset is known without
561+ reading the metadata, such as ` [T] ` , ` str ` , and types that end with them, as
562+ in ` offset_of!((i32, [u16]), 1) ` , or ` offset_of!((u16, (i64, str)), 2) ` .
563+
564+ Allowing these is somewhat inconsistent with ` core::mem::align_of ` , which could
565+ provide the alignment in some cases such as slices, but instead you must use
566+ ` core::mem::align_of_val ` for all ` ?Sized ` types (admittedly, allowing
567+ ` align_of::<[T]>() ` is perhaps not very compelling, as it's always the same as
568+ ` align_of::<T>() ` ).
531569
532570Either way, it's trivially backwards compatible for us to eventually start
533571allowing these, and for the trailing slice/str case, it seems difficult to pin
0 commit comments