# Reading notes: RFC 3318, Field Projection Link to document: https://github.com/y86-dev/rfcs/blob/field-projection/text/3318-field-projection.md ###### tags: `reading-club` Leave questions, observations, discussion topics below. --- ## Topic name: prompt --- ## Composability (might be addressed in RFC text, not yet sure) pnkfelix: Can the projections described here be composed with themselves, such that e.g. `&MaybeUninit<Cell<Struct>>` can be projectred to `&MaybeUninit<Cell<Field>>`? Or does this only go "one level deep" ? vincenzopalazzo: this is unclear also to me, and it is unclear also how the solution proposed in the RFC works at implementation level https://github.com/y86-dev/rfcs/blob/field-projection/text/3318-field-projection.md#reference-level-explanation and "Supported pointers" Distinction between `P` pointer types and `Wrapper` types (both happen to include `Pin`) tmandry: Don't see a reason why not I guess ## How to express non-magic-projecting access? (might be addressed in RFC text, not yet sure) pnkfelix: If one of the types in question already a struct, do we need to continue to support the previous access? If so, how is that expressed ... via a new operator? Or by some thing analogous to UFCS, but now for field access rather than method calls? (E.g. how does one express what would today be denoted by `.inner` for a given `#[repr(transparent)]` type) pnkfelix: I could imagine support for the previous kind of access might still be expressable via `match`... oh lets ask about that too ... Update: RFC as written does not allow for the old semantics to be expressed via `let` and presumably via `match` either, see below pnkfelix: Maybe the intention is that you can get access to the original fields by first turning your `&Wrapper` into a `*const Wrapper` and then the `.`-projection operator acts on the `Wrapper` type, not on the projected type? Field access has higher priority than projection: https://github.com/y86-dev/rfcs/blob/field-projection/text/3318-field-projection.md#deref-and-derefmut pnkfelix: But then if I try to access some field `inner` (and that's in `Pin`) then we have privacy-dependent name resolution? Maybe we want/have this anyway. tmandry: Probably should be called out in the RFC. ## does this impact `match`/`let` semantics (answer: yes) Update: The intention *is* that this will affect bindings; `let` is demonstrated in the RFC text, and presumably `match` is affected as well. pnkfelix: I can understand how `foo.field` ends up projecting out the internals of `field` within `foo`. But does that also mean that this is impacted: ```rust= let foo: &Cell<Struct> = ...; match foo { Struct { field } => ... // does this *start working*, where `field` now has type `&Cell<Field>` ? } ``` https://github.com/y86-dev/rfcs/blob/field-projection/text/3318-field-projection.md#bindings pnkfelix: "Enum bindings cannot be supported with the wrappers MaybeUninit\<T> and Cell\<T>". What's the actual constraint here? eholk: They don't explain what to do about the UB here. pnkfelix: Seems like you get clear benefits from `.` and (things you can put on rhs of a let), don't know why they attempted to do matches in the first go-round. pnkfelix: Seems simplest to punt, but then again, maybe it's so valuable to match on an enum etc that we should work it out. ## Implementation details (vincenzopalazzo) Why project one filed if you can prepare the code to project with an infinite struct filed? The code could be ```rust #[project(Pin)] struct MyStruct { buf: [u8; 64], ptr: *const u8, _pin: PhantomPinned, } // gen by the macros trait ProjectPinForMyStruct { fn buf_as_pin(&self) -> Pin<[u8; 64]>; // not sure that compile :) fn ptr_as_pin(&self) -> Pin<....> } impl ProjectPinForMyStruct for MyStruct { fn buf_as_pin(&self) -> Pin<[u8; 64]>; // not sure that compile :) fn ptr_as_pin(&self) -> Pin<....> ... so on } ``` pnkfelix: (Something about disjoint fields, sorry bad notes) eholk: It also talks about [Arc projection](https://github.com/y86-dev/rfcs/blob/field-projection/text/3318-field-projection.md#out-of-scope-arc-projection) ## Relation to dyn* tmandry: The `NoMetadataPtr` trait and some operations proposed for projection look kind of like `dyn*` if you squint. Is there some kind of relationship here or is that just surface-level resemblance? eholk: I was wondering the same thing. pnkfelix: dyn* is not google-able :) eholk: I almost called in `dyn⭐` when I was making the parsing change tmandry: `dyn* Future` is pointer+vtable-sized object that implements `Future`; has a conversion trait like `IntoRawPointer` that looks just like `NoMetadataPtr`. tmandry: One possible difference is that `dyn*` _can_ represent `Box` (pnkfelix: also `Arc`) and ownership, whereas this is about borrowed data exclusively pnkfelix: More utility for this is projection of field where you erase the knowledge of original struct? tmandry: I guess I don't see a reason why they can't be the same trait. eholk: If you squint, dyn* might be able to represent a lot of these projection.