Skip to content

Commit cdafbed

Browse files
committed
Mention field-offset, reword parts of the future work around unsized types
1 parent 0afa52a commit cdafbed

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

text/0000-offset_of.md

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
273276
3. 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
519553
is when the user has requested the offset of the unsized field, and the unsized
520554
field 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+
523558
1. 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

532570
Either way, it's trivially backwards compatible for us to eventually start
533571
allowing these, and for the trailing slice/str case, it seems difficult to pin

0 commit comments

Comments
 (0)