-
Notifications
You must be signed in to change notification settings - Fork 65
Propose goal: Field Projections #329
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
c054115
4a6db0e
679269c
b44cdc8
2f6a5d4
9f3b9b3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
# Design a language feature to solve Field Projections | ||
|
||
| Metadata | | | ||
|:-----------------|----------------------------------------------------------------------------------| | ||
| Point of contact | @BennoLossin | | ||
| Teams | <!-- TEAMS WITH ASKS --> | | ||
| Task owners | <!-- TASK OWNERS --> | | ||
| Status | Proposed | | ||
| Tracking issue | | | ||
| Zulip channel | N/A | | ||
|
||
## Summary | ||
|
||
Figure out the best design for field projections. Update the existing [Field Projections RFC] or | ||
author a new one and implement it for use in nightly via a lang experiment. | ||
|
||
[Field Projections RFC]: https://github.com/rust-lang/rfcs/pull/3735 | ||
|
||
## Motivation | ||
|
||
Rust makes extensive use of smart pointers (`Box<T>`, `Rc<T>`, `Arc<T>`), modified references (`&mut | ||
MaybeUninit<T>`, `Pin<&mut T>`) and custom pointer types (`NonNull<T>`). | ||
|
||
Some of these types implement the `Deref[Mut]` trait(s) allowing one to access fields of the type | ||
`T`. But not all of them can implement it due to various reasons. However, they often *can* support | ||
operations that "index" into the fields of the type `T`. For example `&mut MaybeUninit<Struct>` | ||
conceptually has fields of type `&mut MaybeUninit<Field>`. | ||
|
||
### The status quo | ||
|
||
Rust has a lot of container types that make it difficult to directly interact with fields of structs | ||
that they wrap. For example: | ||
- `MaybeUninit<T>`, | ||
- `UnsafeCell<T>`, | ||
- `Cell<T>` | ||
|
||
It also has several pointer-like types that could support a natural pointer-to-field operation. For | ||
example: | ||
- `NonNull<T>`, | ||
- `*const T` / `*mut T`, | ||
- `cell::Ref<'_, T>` / `cell::RefMut<'_, T>` | ||
|
||
Additionally, there is `Pin<&mut T>`, which already has a well-established name for this operation: | ||
pin-projections. The ecosystem provides several crates to add this operation to the struct itself. | ||
|
||
#### Custom types | ||
|
||
A plethora of types making use of field projections are found in the context of Rust for Linux. | ||
Therefore they might -- with high probability -- come up in other embedded projects too. | ||
|
||
- `VolatilePtr<'a, T>` like `*mut T`, but with a lifetime & all accesses to the pointer are | ||
volatile. | ||
- `Ptr<'a, T>` like a `&'a T` but without certain rust guarantees (most likely `&'a UnsafePinned<T>` | ||
under the hood). | ||
- `RcuMutex<T>` a safe abstraction for RCU (a special synchronization primitive in the kernel) | ||
working together with a `Mutex<T>` to synchronize accesses to data (this requires complex | ||
projections, only allowing certain fields to be projected). | ||
- `SeqLockRef<'_, T>` | ||
- `AtomicPtr<T>` where `T` is a small enough type composed of integers. | ||
- `UserPtr<T>` a pointer into userspace | ||
|
||
Additionally, Rust for Linux could take advantage of field information present in the current | ||
proposal. Essentially answering the question "does this type have a field of type X at offset Y?" | ||
via traits. | ||
Comment on lines
+62
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you take a look at #311 for this and let me know your thoughts? Do you think we can unify the proposals? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I read through the goal, but didn't understand what exactly the solution is going to be (which is probably because nobody knows that :) so I can't say for sure that it will cover our use-case. Our use-case is something that would be covered by reflection as I would understand it. One of our use-cases is detecting if a field of a struct is a specific type (for the details see here). The current idea for field projection will still have field traits, so it would enable using traits for field inspection. We might want to do something different, but I don't know how that would look like. |
||
|
||
Note that the projections listed above are also very important to Rust for Linux. Virtually all | ||
types are pinned in the kernel, so `Pin<&mut T>` comes up a lot in drivers. We're also handling raw | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Note that this is something we might add special syntax for, as part of pin ergonomics. See the design sketch at the top of rust-lang/rust#130494 (the third bullet in particular) and let me know if it matches your expectations. It would be nice if we could describe both this and regular deref projection in terms of this more general feature. Though I can see there being downsides to that, if there are cases where sometimes you want to go through Deref and sometimes you want to project.. do any come to mind for you? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah that matches my expectation (modulo the differing design idea of what directs the projection (field type vs field property)). I think we can model them using the field projection design that I currently have in mind (and also any other that I would consider useful). But this would require negative trait bounds & that compiler allows you to implement a trait for
I have one problem in mind when making all |
||
pointers very often where we could use `NonNull<T>` instead if they had better field access. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe raw pointers would benefit from the syntax too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. indeed, though they already are much more ergonomic than |
||
|
||
#### Current proposals | ||
|
||
In addition to [Field Projections RFC v2] already mentioned above, there is a [newer | ||
proposal](https://hackmd.io/@BennoLossin/HkMBy6Hzlx) that improves upon it. | ||
|
||
For historical context, there also is the [Field Projections RFC v1]. | ||
|
||
[Field Projections RFC v1]: https://github.com/rust-lang/rfcs/pull/3318 | ||
[Field Projections RFC v2]: https://github.com/rust-lang/rfcs/pull/3735 | ||
|
||
### The next 6 months | ||
|
||
Have design meetings with the relevant parties & update the existing or write a new RFC. | ||
|
||
### The "shiny future" we are working towards | ||
|
||
Have field projections available in stable Rust. | ||
|
||
## Design axioms | ||
|
||
- **Effortless Syntax.** Using field projections in a non-generic context should look very similar | ||
to normal field accesses. | ||
- **Broad Solution.** Field projections should be very general and solve complex projection problems | ||
such as pin-projections and `RcuMutex<T>`. | ||
|
||
## Ownership and team asks | ||
|
||
| Task | Owner(s) or team(s) | Notes | | ||
|----------------------|-------------------------------------|---------------------------------------------------------------------| | ||
| Design meeting | ![Team][] [lang] | Possibly more than one required as well as discussions on zulip. | | ||
| Lang-team experiment | ![Team][] [lang] | @dingxiangfei2009, @BennoLossin | | ||
| Author RFC | @BennoLossin | | | ||
| Lang-team champion | ![Team][] [lang] | *Champion Needed* | | ||
| RFC secondary review | ![Team][] [types] | might be a good idea? | | ||
| RFC decision | ![Team][] [lang] | | | ||
|
||
|
||
## Frequently asked questions | ||
|
Uh oh!
There was an error while loading. Please reload this page.