The Rust project is currently working towards a slate of 17 project goals, with 7 of them designated as Flagship Goals. This post provides selected updates on our progress towards these goals (or, in some cases, lack thereof). The full details for any particular goal are available in its associated tracking issue on the rust-project-goals repository.
Flagship goals
"Beyond the `&`"
Progress | |
Point of contact | |
Champions | compiler (Oliver Scherer), lang (TC) |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | |
Task owners |
1 detailed update available.
Key Developments
- coordinating with
#![feature(pin_ergonomics)]
(https://github.com/rust-lang/rust/issues/130494) to ensure compatibility between the two features (allow custom pin projections to be the same as the ones for&pin mut T
) - identified connection to auto reborrowing
- https://github.com/rust-lang/rust-project-goals/issues/399
- https://github.com/rust-lang/rust/issues/145612
- held a design meeting
- very positive feedback from the language team
- approved lang experiment
- got a vibe check on design axioms
- created a new Zulip channel #t-lang/custom-refs for all new features needed to make custom references more similar to
&T
/&mut T
such as field projections, auto reborrowing and more - created the tracking issue for
#![feature(field_projections)]
- opened https://github.com/rust-lang/rust/pull/146307 to implement field representing types (FRTs) in the compiler
Next Steps
- Get https://github.com/rust-lang/rust/pull/146307 reviewed & merged
Help Wanted
- When the PR for FRTs lands, try out the feature & provide feedback on FRTs
- if possible using the field-projection crate and provide feedback on projections
Internal Design Updates
Shared & Exclusive Projections
We want users to be able to have two different types of projections analogous to &T
and &mut T
. Each field can be projected independently and a single field can only be projected multiple times in a shared way. The current design uses two different traits to model this. The two traits are almost identical, except for their safety documentation.
We were thinking if it is possible to unify them into a single trait and have coercions similar to autoreborrowing that would allow the borrow checker to change the behavior depending on which type is projected.
Syntax
There are lots of different possibilities for which syntax we can choose, here are a couple options: [Devon Peticolas][]->f
/[Andrea D'Angelo][] x->f
, [Devon Peticolas][].f
/[Andrea D'Angelo][] x.f
, x.[Fatih Kadir Akın][]
/x.mut[Fatih Kadir Akın][]
, x.ref.[Fatih Kadir Akın][]
/x.[Fatih Kadir Akın][]
. Also many alternatives for the sigils used: x[Fatih Kadir Akın][]
, x~f
, x.@.f
.
We have yet to decide on a direction we want to go in. If we are able to merge the two project traits, we can also settle on a single syntax which would be great.
Splitting Projections into Containers & Pointers
There are two categories of projections: Containers and Pointers:
- Containers are types like
MaybeUninit<T>
,Cell<T>
,UnsafeCell<T>
,ManuallyDrop<T>
. They arerepr(transparent)
and apply themselves to each field, soMaybeUninit<MyStruct>
has a field of typeMaybeUninit<MyField>
(ifMyStruct
has a field of typeMyField
). - Pointers are types like
&T
,&mut T
,cell::Ref[Mut]<'_, T>
,*const T
/*mut T
,NonNull<T>
. They support projectingPointer<'_, Struct>
toPointer<'_, Field>
.
In the current design, these two classes of projections are unified by just implementing Pointer<'_, Container<Struct>> -> Pointer<'_, Container<Field>>
manually for the common use-cases (for example &mut MaybeUninit<Struct> -> &mut MaybeUninit<Field>
). However this means that things like &Cell<MaybeUninit<Struct>>
doesn't have native projections unless we explicitly implement them.
We could try to go for a design that has two different ways to implement projections -- one for containers and one for pointers. But this has the following issues:
- there are two ways to implement projections, which means that some people will get confused which one they should use.
- making projections through multiple container types work out of the box is great, however this means that when defining a new container type and making it available for projections, one needs to consider all other container types and swear coherence with them. If we instead have an explicit way to opt in to projections through multiple container types, the implementer of that trait only has to reason about the types involved in that operation.
- so to rephrase, the current design allows more container types that users actually use to be projected whereas the split design allows arbitrary nestings of container types to be projected while disallowing certain types to be considered container types.
- The same problem exists for allowing all container types to be projected by pointer types, if I define a new pointer type I again need to reason about all container types and if it's sound to project them.
We might be able to come up with a sensible definition of "container type" which then resolves these issues, but further investigation is required.
Projections for &Custom<U>
We want to be able to have both a blanket impl<T, F: Field<Base = T>> Project<F> for &T
as well as allow people to have custom projections on &Custom<U>
. The motivating example for custom projections is the Rust-for-Linux Mutex
that wants these projections for safe RCU abstractions.
During the design meeting, it was suggested we could add a generic to Project
that only the compiler is allowed to insert, this would allow disambiguation between the two impls. We have now found an alternative approach that requires less specific compiler magic:
- Add a new marker trait
ProjectableBase
that's implemented for all types by default. - People can opt out of implementing it by writing
impl !ProjectableBase for MyStruct;
(needs negative impls for marker traits). - We add
where T: ProjectableBase
to theimpl Project for &T
. - The compiler needs to consider the negative impls in the overlap check for users to be able to write their own
impl<U, F> Project<F> for &Custom<U> where ...
(needs negative impl overlap reasoning)
We probably want negative impls for marker traits as well as improved overlap reasoning for different reasons too, so it is probably fine to depend on them here.
enum
support
enum
and union
shouldn't be available for projections by default, take for example &Cell<Enum>
, if we project to a variant, someone else could overwrite the value with a different variant, invalidating our &Cell<Field>
. This also needs a new trait, probably AlwaysActiveField
(needs more name bikeshedding, but too early for that) that marks fields in structs and tuples.
To properly project an enum
, we need:
- a new
CanProjectEnum
(TBB) trait that provides a way to read the discriminant that's currently inhabiting the value.- it also needs to guarantee that the discriminant doesn't change while fields are being projected (this rules out implementing it for
&Cell
)
- it also needs to guarantee that the discriminant doesn't change while fields are being projected (this rules out implementing it for
- a new
match
operator that will project all mentioned fields (for&Enum
this already is the behavior formatch
)
Field Representing Types (FRTs)
While implementing https://github.com/rust-lang/rust/pull/146307 we identified the following problems/design decisions:
- a FRT is considered local to the orphan check when each container base type involved in the field path is local or a tuple (see the top comment on the PR for more infos)
- FRTs cannot implement
Drop
- the
Field
trait is not user-implementable - types with fields that are dynamically sized don't have a statically known offset, which complicates the
UnalignedField
trait,
I decided to simplify the first implementation of FRTs and restrict them to sized structs and tuples. It also doesn't support packed structs. Future PRs will add support for enums, unions and packed structs as well as dynamically sized types.
Progress | |
Point of contact | |
Champions | |
Task owners |
No detailed updates available.
"Higher-level Rust"
Progress | |
Point of contact | |
Champions | |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett) |
Task owners |
1 detailed update available.
Key developments:
- Overall polish
- https://github.com/rust-lang/rust/pull/145751
- https://github.com/rust-lang/rust/pull/145754
- https://github.com/rust-lang/rust/pull/146106
- https://github.com/rust-lang/rust/pull/146137
- https://github.com/rust-lang/rust/pull/146211
- https://github.com/rust-lang/rust/pull/146340
- https://github.com/rust-lang/rust/pull/145568
- https://github.com/rust-lang/cargo/pull/15878
- https://github.com/rust-lang/cargo/pull/15886
- https://github.com/rust-lang/cargo/pull/15899
- https://github.com/rust-lang/cargo/pull/15914
- https://github.com/rust-lang/cargo/pull/15927
- https://github.com/rust-lang/cargo/pull/15939
- https://github.com/rust-lang/cargo/pull/15952
- https://github.com/rust-lang/cargo/pull/15972
- https://github.com/rust-lang/cargo/pull/15975
- rustfmt work
- https://github.com/rust-lang/rust/pull/145617
- https://github.com/rust-lang/rust/pull/145766
- Reference work
- https://github.com/rust-lang/reference/pull/1974
"Unblocking dormant traits"
Progress | |
Point of contact | |
Champions | |
Task owners | Taylor Cramer, Taylor Cramer & others |
1 detailed update available.
Current status: there is an RFC for auto impl
supertraits that has received some discussion and updates (thank you, Ding Xiang Fei!).
The major open questions currently are:
Syntax
The current RFC proposes:
#![allow(unused)] fn main() { trait Subtrait: Supertrait { auto impl Supertrait { // Supertrait items defined in terms of Subtrait items, if any } } }
Additionally, there is an open question around the syntax of auto impl
for unsafe supertraits. The current proposal is to require unsafe auto impl Supertrait
.
Whether to require impls to opt-out of auto impl
s
The current RFC proposes that
for MyType. extern impl Supertrait; }#![allow(unused)] fn main() { impl Supertrait for MyType {}
impl Subtrait for MyType { // Required in order to manually write
Supertrait }
This makes it explicit via opt-out whether an auto impl
is being applied. However, this is in conflict with the goal of allowing auto impl
s to be added to existing trait hierarchies. The RFC proposes to resolve this via a temporary attribute which triggers a warning. See my comment here.
Note that properly resolving whether or not to apply an auto impl
requires coherence-like analysis.
Progress | |
Point of contact | |
Champions | |
Task owners | Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts |
No detailed updates available.
Goals looking for help
Other goal updates
Progress | |
Point of contact | |
Champions | compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay) |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur) |
Task owners | Pete LeVasseur, Contributors from Ferrous Systems and others TBD, |
No detailed updates available.
Progress | |
Point of contact | |
Champions | |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | compiler (Manuel Drehwald), lang (TC) |
Task owners | Manuel Drehwald, LLVM offload/GPU contributors |
No detailed updates available.
Progress | |
Point of contact | |
Champions | lang (Josh Triplett), lang-docs (TC) |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | |
Task owners |
No detailed updates available.
Progress | |
Point of contact | |
Champions | compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett) |
Task owners | oli-obk |
No detailed updates available.
Progress | |
Point of contact | |
Champions | compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras) |
Task owners |
1 detailed update available.
Niko Matsakis I think your script is broken
Progress | |
Point of contact | |
Champions | |
Task owners |