@@ -270,6 +270,9 @@ considered:
270
270
formats or binary serialization formats that contain descriptions of the
271
271
field offsets for the record types they contain, etc.
272
272
273
+ It is also useful for implementing field projection as a library feature, as
274
+ in cases like [ ` field-offset ` ] [ fieldoffset ] .
275
+
273
276
3 . Require that all fields of ` $Container ` be visible at the invocation site,
274
277
rather than just requiring that ` $field ` is.
275
278
@@ -308,6 +311,26 @@ considered:
308
311
Additionally, this does not generalize as well to some of the extensions in
309
312
future work.
310
313
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
+
311
334
# Prior art
312
335
[ prior-art ] : #prior-art
313
336
@@ -349,9 +372,20 @@ popular, and provide this functionality in different ways.
349
372
350
373
It does not support use during constant evaluation.
351
374
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
+
352
385
[ memoffset ] : https://crates.io/crates/memoffset/0.6.5
353
386
[ bmuckcrate ] : https://crates.io/crates/bytemuck/1.12.1
354
387
[ bmuckoffset ] : https://docs.rs/bytemuck/1.12.1/bytemuck/macro.offset_of.html
388
+ [ fieldoffset ] : https://crates.io/crates/field-offset/0.3.4
355
389
356
390
## Prior Art: Languages
357
391
@@ -519,15 +553,19 @@ The only case where we currently do *not* know the offset of a field statically
519
553
is when the user has requested the offset of the unsized field, and the unsized
520
554
field is a trait object.
521
555
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
+
523
558
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) ` .
526
559
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>() ` ).
531
569
532
570
Either way, it's trivially backwards compatible for us to eventually start
533
571
allowing these, and for the trailing slice/str case, it seems difficult to pin
0 commit comments