diff --git a/content/Project-Goals-2025-November-Update.md b/content/Project-Goals-2025-November-Update.md new file mode 100644 index 000000000..5ec1c3efc --- /dev/null +++ b/content/Project-Goals-2025-November-Update.md @@ -0,0 +1,2874 @@ ++++ +path = "9999/12/31/Project-Goals-2025-November-Update.md" +title = "Project goals update — November 2025" +authors = ["Tomas Sedovic"] + +[extra] +team = "the Goals team" +team_url = "https://www.rust-lang.org/governance/teams/launching-pad#team-goals" ++++ + +The Rust project is currently working towards a [slate of 41 project goals](https://rust-lang.github.io/rust-project-goals/2025h2/goals.html), with 13 of them designated as [Flagship Goals](https://rust-lang.github.io/rust-project-goals/2025h2/goals.html#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](https://github.com/rust-lang/rust-project-goals/issues?q=is%3Aissue%20state%3Aopen%20label%3AC-tracking-issue). + +## Flagship goals + + +### "Beyond the `&`" + +
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +compiler (Oliver Scherer), lang (TC) + |
+
| Task owners | ++ | +
1 detailed update available.
+ +Status update:
+&pin const|mut T types, merged.&pin pattern and ref pin mut binding mode, merged.Drop::pin_drop, waiting for review (new updates since the last review).
+src/docs/book submodule, but the top repo and the sub repo must be changed together to pass the CI tests in both repos. It's because a default body is added to Drop::drop and it becomes a provided method instead of a required method in rustdoc. Is there any way to avoid that? (Possibly keep rustdoc treating Drop::drop as a required method?)&pin const|mut T and &{mut} T, waiting for review (fresh).| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
We have made lot's of progress with the novel place-based proposal made by @Nadrieril. Since the last update, he released his idea as a blog post and have had an immense amount of discussions on Zulip. There are still many open questions and problems left to solve. If you have any ideas, feel free to share them on Zulip.
+At the beginning of this month, we explored moving projections and &own. We also looked into reducing the number of projection traits.
The PR https://github.com/rust-lang/rust/pull/146307 has been stale for this month, but will be picked up again in December.
+3 detailed updates available.
+ +&ownMoving projections are a third kind of projection that already exists in Rust today for Box as well as any local variable holding a struct. While we won't be including it in an MVP, we still want to make sure that we can extend the language with moving projections. Here is an example with Box:
fn destructure_box(mut b: Box<Struct>) -> Box<Struct> {
+ let f1 = b.f1;
+ b.f1 = F1::new();
+ b
+}
+
+This projection moves the field out of the box, invalidating it in the process. To make it valid again, a new value has to be moved in for that field. Alternatively, the partially valid box can be dropped, this will drop all other fields of Struct and then deallocate the Box. Note that this last property is implemented by compiler magic today and moving projections would allow this special behavior for Box to be a library implementation instead.
To make this kind of projection available for all types, we can make it a proper operation by adding this trait:
+ + +pub unsafe trait ProjectMove: Projectable {
+ type OutputMove<'a, F: Field<Base = Self::Target>>;
+
+ unsafe fn project_move<'a, F: Field<Base = Self::Target>>(
+ this: *mut Self,
+ ) -> Self::OutputMove<'a, F>;
+
+ unsafe fn drop_husk(husk: *mut Self);
+}
+
+Importantly, we also need a drop_husk function which is responsible for cleaning up the "husk" that remains when all fields have been move-projected. In the case of Box, it deallocates the memory. So for Box we could implement this trait like this:
impl<T> ProjectMove for Box<T> {
+ type OutputMove<'a, F: Field<Base = T>> = F::Type;
+
+ unsafe fn project_move<'a, F: Field<Base = T>>(
+ this: *mut Self,
+ ) -> F::Type {
+ let ptr = unsafe { (*this).0.pointer.as_ptr() };
+ ptr::read(unsafe {
+ <*const T as Project>::project::<'a, F>(&raw const ptr)
+ })
+ }
+
+ unsafe fn drop_husk(husk: *mut Self) {
+ // this is exactly the code run by `Box::drop` today, as the compiler
+ // drops the `T` before `Box::drop` is run.
+ let ptr = (*husk).0;
+ unsafe {
+ let layout = Layout::for_value_raw(ptr.as_ptr());
+ if layout.size() != 0 {
+ (*husk).1.deallocate(From::from(ptr.cast()), layout);
+ }
+ }
+ }
+}
+
+To support moving back into a value we have two options:
+ProjectMoveBack trait that declares an operation which accepts a value that is moved back into the projected one, or&own references.Until now, we have explored the second option, because there are lot's of other applications for &own.
&own ReferencesA small interlude on &own references.
An &'a own T is a special kind of exclusive reference that owns the value it points to. This means that if you drop an &own T, you also drop the pointee. You can obtain an &own T by constructing it directly to local variable &own my_local or by deriving it from an existing &own via field projections. Smart pointers generally also allow creating &own T from &own SmartPtr<T>.
One important difference to &mut T is that &own is not only temporally unique (i.e. there are no other references to that value not derived from it) but also unique for that value. In other words, one can create at most one &own T to a local variable.
let mut val = Struct { ... };
+let x = &own val; //~ HELP: ownership transferred here
+drop(x);
+let y = &own val; //~ ERROR: cannot own `val` twice
+
+Since the drop(x) statement drops val, the borrow checker must disallow any future access. However, we are allowed to move a value back into the memory of val:
let mut val = Struct { ... };
+let x = &own val;
+drop(x);
+val = Struct { ... };
+let y = &own val;
+
+The lifetime 'a in &'a own T is that of the backing memory. It means that when 'a expires, the memory also is no longer valid (or rather it cannot be proven that it is valid after 'a). For this reason an &'a own T has to be dropped (or forgotten) before 'a expires (since after that it cannot be dropped any more).
&own T itself supports moving projections (another indicator that having them is a good idea). However only for types that don't implement Drop (similar to normal struct destructuring -- there are also talks about lifting this requirement, but no new issues arise from projecting &own).
&own and pinningTo make &pin own T with !(T: Unpin) sound in the face of panics, we have to add drop flags or have unforgettable types. We explored a design using drop flags below; there are separate efforts to experimenting with a Leak/Forget trait ongoing, I think it might be a better solution than drop flags at least for &own.
We need drop flags to ensure the drop guarantee of pinned values. The drop flag will be stored when the original &own is created and it will live on the stack of the function that created it. They are needed for the following scenario:
fn foo() {
+ let x = Struct { ... };
+ bar(&pin own x);
+}
+
+fn bar(x: &pin own Struct) {
+ if random() {
+ std::mem::forget(x);
+ }
+ if random() {
+ panic!()
+ }
+}
+
+Since x is pinned on the stack, it needs to be dropped before foo returns (even if it unwinds). When bar forgets the owned reference, the destructor is not run, if it now panics, the destructor needs to be run in foo. But since it gave away ownership of x to bar, it is possible that bar already dropped x (this is the case when the first random() call returns false). To keep track of this, we need a drop flag in the stack frame of foo that gets set to true when x is dropped.
There are several issues with drop flags:
+&'static own T pointing to non-static values (for example coming from a Box::leak_owned function).Drop&own T and &pin own T, the former can be forgotten and the destructor will not run, the latter can also be forgotten, but the destructor runs regardless.This last point convinces me that we actually want &pin own T: !Leak when T: !Leak; but IIUC, that wouldn't prevent the following code from working:
fn main() {
+ let x = Struct { ... };
+ let x = &pin own x;
+ Box::leak(Box::new(x));
+}
+
+DerefMoveThe DerefMove operation & trait is something that has been discussed in the past (I haven't dug up any discussions on it though). It is the analogous operation of &own to Deref. We need to figure out the hierarchy wrt. Deref and DerefMut, but ignoring that issue for the moment, here is how DerefMove would look like:
trait DerefMove: DropHusk {
+ trait Target: ?Sized;
+
+ fn deref_move(&own self) -> &own Self::Target;
+}
+
+Note the super trait requirement DropHusk -- it provides a special drop operation for Self when the &own Self::Target reference has been dropped. Box<T> for example would deallocate the backing memory via DropHusk. Its definition looks like this:
pub unsafe trait DropHusk {
+ unsafe fn drop_husk(husk: *mut Self);
+}
+
+We would of course also use this trait for ProjectMove. Implementing DropHusk on its own does nothing; implementing DerefMove or ProjectMove will make the compiler call drop_husk instead of Drop::drop when the value goes out of scope after it has been projected or DerefMove::deref_move has been called.
We observed that DerefMove is a lot more restrictive in its usability than Deref--- and we need projections to make it actually useful in the common case. The reason for this is that &own can only be created once, but one would like to be able to create it once per field (which is exactly what moving projections allow). Consider this example:
let b = Box::new(Struct { ... });
+let field1 = &own b.field1; // desugars to `DerefMove::deref_move`
+let field2 = &own b.field2; //~ ERROR: cannot own `b` twice
+
+The "cannot own `b` twice error comes from the way the deref desugaring works:
let b = Box::new(Struct { ... });
+let field1 = &own DerefMove::deref_move(&own b).f1;
+let field2 = &own DerefMove::deref_move(&own b).f2;
+// ^^^ ERROR: cannot own `b` twice
+
+Now it's clear that we're trying to create two &own to the same value and that can't work (the issue also arises for &mut, but that already is covered by ProjectExclusive).
We can write this instead:
+ + +let b = Box::new(Struct { ... });
+let b = &own b;
+let field1 = &own b.field1;
+let field2 = &own b.field2;
+
+But that's cumbersome.
+We also note that ProjectMove is the correct projection for ArcRef, as it avoids any additional refcount updates. We can rely on the ergonomic refcounting proposal to provide ergonomic ways to clone the value & perform more projections.
Project traitThe definition of the now 3 Project* traits are 100% verbatim the same (modulo renaming of course), so we spent some time trying to unify them into a single trait. While we cannot get rid of having to have three traits, we can merge them into a single one by adding a generic:
#[sealed]
+pub trait ProjectKind {
+ type Ptr<T: ?Sized>;
+}
+
+pub enum Shared {}
+pub enum Exclusive {}
+
+impl ProjectKind for Shared {
+ type Ptr<T: ?Sized> = *const T;
+}
+
+impl ProjectKind for Exclusive {
+ type Ptr<T: ?Sized> = *mut T;
+}
+
+pub trait Projectable {
+ type Target;
+}
+
+pub unsafe trait Project<Kind: ProjectKind>: Projectable {
+ type Output<'a, F: Field<Base = Self::Target>>;
+
+ unsafe fn project<'a, F: Field<Base = Self::Target>>(
+ this: Kind::Ptr<Self>,
+ ) -> Self::Output<'a, F>;
+}
+
+We would need some more compiler magic to ensure that nobody implements this trait generically, so impl<K> Project<K> for MyType, to keep our approach extensible (this could be an attribute if it is also useful in other cases #[rustc_deny_generic_impls]).
The benefit of merging the definitions is that we only have one single trait that we need to document and we could also add documentation on the ProjectKind types. There are also ergonomic downsides, for example all output types are now called Output and thus need to be fully qualified if multiple projection impls exist (<MyType as Project<Exclusive>>::Output<'_, F> vs MyType::OutputExclusive<'_, F>).
To make this proposal compatible with moving projections, we also either need more compiler magic to ensure that if Kind = Move we require Self: DropHusk. Or we could use associated traits and add one to ProjectKind that's then used in Project (Kind = Shared would then set this to Pointee).
This approach also makes me think a bit more about the syntax, if we discover more projections in the future, it might make sense to go for an extensible approach, like @keyword expr{->,.@,.,~}ident (so for example @move x->y or @mut x.y).
@Nadrieril opened this zulip thread with the idea that "The normal rust way to reborrow a field uses places". He then proceeded to brainstorm a similar design for field projections with a crucial difference: making places the fundamental building block. We had a very long discussion in that thread (exchanging the existing ideas about field projection and the novel place-involving ones) that culminated in this awesome writeup by @Nadrieril: https://hackmd.io/[@Nadrieril][]/HJ0tuCO1-e. It is a very thorough document, so I will only be able to summarize it partially here:
+Project* traits, we have the Place* traits which govern what kind of place operations are possible on *x given x: MySmartPtr, those are reading, writing and borrowing.@MySmartPtr <place-expr>&mut x.field.a and &mut x.field.bWe still have many things to flesh out in this proposal (some of these pointed out by @Nadrieril):
+Projection trait?MaybeUninit<T>, UnsafeCell<T> and ManuallyDrop<T>?BorrowKind work as a model for the borrow checker?match ergonomics work nicely?This is a very interesting viewpoint and I'm inclined to make this the main proposal idea. The traits are not too different from the current field projection design and the special borrow checker behavior was also intended at least for the first level of fields. So this is a natural evolution of the field projection proposal. Thanks a lot to @Nadrieril for the stellar writeup!
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +We've worked towards coherence checking of the CoerceShared trait, and have come to a conclusion that (at least as a first step) only one lifetime, the first one, shall participate in reborrowing. Problems abound with how to store the field mappings for CoerceShared.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras) + |
+
| Task owners | ++ | +
1 detailed update available.
+ +Our first RFC - rust-lang/rfcs#3873 - is in the FCP process, waiting on boxes being checked. rust-lang/rfcs#3874 and rust-lang/rfcs#3875 are receiving feedback which is being addressed.
+ +| Progress | +|
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +bjorn3, Folkert de Vries, [Trifecta Tech Foundation] + |
+
| Progress | ++ | +
| Point of contact | ++ | +
| Task owners | ++ | +
| Progress | +|
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +@dropbear32, @osiewicz + |
+
1 detailed update available.
+ +linking this here so people know why there hasn't been any progress on this project goal.
+ + +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
2 detailed updates available.
+ +Three new blog posts:
+Handle and other follow-up thoughtsThe most important conclusions from those posts are
+move(cx.foo.clone()) || use(cx.foo).Alias or Share as the name for Handle trait; I am currently leaning towards Alias because it can be used as both a noun and a verb and is a bit more comparable to clone -- i.e., you can say "an alias of foo" just like you'd say "a clone of foo".clone and alias so that higher-level Rust gets the ergonomic benefits even when cloning "heavier-weight" types to which Alias does not apply.New blog post:
+Exploring one way to make things more ergonomic while remaining explicit, which is to make .clone() and .alias() (1) understood by move closure desugaring and (2) optimized away when redundant.
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett) + |
+
| Task owners | ++ | +
1 detailed update available.
+ +Key developments
+Blockers:
+| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +Taylor Cramer, Taylor Cramer & others + |
+
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts + |
+
1 detailed update available.
+ +On Nov 12th, there was a mini-design meeting organized by Xiangfei Ding on inplace initialization. The attendees were Xiangfei Ding, Alice Ryhl, Benno Lossin, Tyler Mandry, and Taylor Cramer.
+We discussed this document: https://hackmd.io/@rust-for-linux-/H11r2RXpgl
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +The new solver is now officially used by Rust Analyzer: https://rust-analyzer.github.io/thisweek/2025/10/27/changelog-299.html. A huge shoutout to Jack Huey Chayim Refael Friedman Shoyu Vanilla and Laurențiu Nicola for that work.
+On the rustc end Rémy Rakic spent a lot of time triaging the most recent crater run. This uncovered a bunch of new edge cases, resulting in 6 new tracked issues.
We've also merged fixes for 4 minor issues over the last 3 weeks: https://github.com/rust-lang/rust/pull/148292 https://github.com/rust-lang/rust/pull/148173 https://github.com/rust-lang/rust/pull/147840. Thanks to Jana Dönszelmann, tiif and @adwinwhite for implementing these. @adwinwhite was also instrumental in diagnosing the underlying issue of https://github.com/rust-lang/trait-system-refactor-initiative/issues/245.
+Going forward, we intend to continue the crater triage while fixing remaining issues until we're ready for stabilization :> the remaining issues are tracked in https://github.com/orgs/rust-lang/projects/61/views/1.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +Key developments:
+a-mir-formality, so I've also joined these meetings, since we'll also want to model the alpha.| Progress | +|
| Point of contact | ++ | +
| Champions | ++ | +
1 detailed update available.
+ +Done in https://github.com/rust-lang/rust-forge/pull/852.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
3 detailed updates available.
+ +tiif and I have been meeting weekly here and pushing changes to the living-large branch of a-mir-formality/nikomatsakis.
We are making progress, we have a minirust type checker and the start of a borrow checker. We've decided to try to use a "judgment-like" approach rather than modeling this as dataflow, as I believe it will give greater insight into the "structure" of the trait checker.
+ +tiif, Jack Huey, and I met today and did more work on the "living-large" branch. The borrow checker judgments are taking shape. My expectation is that we will walk the CFG, tracking the sets of borrows that have occurred so far. At each statement, we will have a judgment that looks at (a) the subtyping relations generated by the type check (flow-insensitive, like NLL); (b) the loans issued so far and not killed; and (c) the live places that may be accessed later. We'll require then that if you are accessing a place P, then there are no loans accessible from a live place that have borrowed P in an incompatible way.
+ +Continued work this week:
+Elaborated some on the definition of the when an access or a statement is valid. We are working our way towards what we believe will be a "largely accurate" model of today's NLL -- obviously we'll then want to test it and compare behavior around various edge cases.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay) + |
+
| Task owners | ++ | +
1 detailed update available.
+ +Key developments: What has happened since the last time. It's perfectly ok to list "nothing" if that's the truth, we know people get busy.
+Nothing! This is the first update and I have yet to focus attention on the project goal. For context, I am employed by the Rust Foundation leading the C++ Interoperability initiative and so far have been executing against the strategy detailed in the problem statement. Owing to greater than anticipated success and deadlines related to WG21 meetings, I've been focusing on the Social Interoperability strategy recently. I have just reached a point where I can turn more attention to the other strategies and so expect to make progress on this goal soon.
+Blockers: List any Rust teams you are waiting on and what you are waiting for.
+None; I'm getting excellent support from the Project in everything I'm doing. My successes thus far would not have been possible without them, and there are too many to enumerate in this space. There will be a blog post coming soon detailing the past year of work in the initiative where I intend to go into detail. Watch this space for updates.
+Help wanted: Are there places where you are looking for contribution or feedback from the broader community?
+I am always interested in contribution and feedback. If you're interested, please reach out via interop@rustfoundation.org or t-lang/interop.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
2 detailed updates available.
+ +Since the lang meeting most progress on this project goal has been unrelated to adt_const_params.
There's been a large amount of work on min_generic_const_args, specifically Noah Lev's PR (rust-lang/rust#139558) which once landed the core of the impl work for the feature will be done. I've reviewed it together with Oliver Scherer and it's pretty much ready to go other than some small reviews.
Once this PR lands I'm hoping that there should be a fair amount of "smallish" PRs that can be made which could be a good set of PRs to mentor new-ish contributors on.
+ +Once again most progress here has been on min_generic_const_args.
Noah Lev's PR (rust-lang/rust#139558) has now landed, as well as an additional PR of his: rust-lang/rust#148716. Between the two of these the core impl should be "mostly done" now, atleast with no additional feature gates enabled :).
+The next big step is to make the min_generic_const_args prototype work well with adt_const_params which I've implemented myself in rust-lang/rust#149136 and rust-lang/rust#149114. These PRs still need to be reviewed but the bulk of the impl work there is now done. These PRs allow for constructing ADTs where the field values may themselves be const parameters or non-concrete uses of type_consts (ie the values are const argument positions).
Once my PRs have landed I would consider mgca as a prototype to be truly "done" though not done as an actual feature. Huge thanks to camelid for sticking through a bunch of fairly painful PRs to get us to this point.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
2 detailed updates available.
+ +Status update as of November 1
+Key developments:
+Linting ?Sized and 'static bounds turned out to be quite a bit more complex than I anticipated. The key issue is that seeing T: Foo + ?Sized does not guarantee that T can be unsized, since we might have Foo: Sized which renders the ?Sized relaxation ineffective. Similarly, seeing T: Foo might also non-obviously imply T: 'static via a similar implied bound.
Failure to correctly account for implied bounds would lead to catastrophic false-positives and false-negatives. For example, changing T: Foo to T: Foo + 'static could be a major breaking change or a no-op, depending on whether we have Foo: 'static (either directly or implicitly via other trait bounds).
We cannot determine implied bounds using information present in rustdoc JSON today, so the rustdoc team and I have been iterating on the best way to compute and include that information in rustdoc JSON. Assuming something similar to the aforementioned PR becomes part of rustdoc JSON, cargo-semver-checks stands to gain several dozen new lints covering these tricky cases over trait associated types, generic type parameters, and APIT/RPIT/RPITIT.
Google Summer of Code 2025 is complete + finally some movement on cross-crate linting! 🚀
+Key developments
+cargo-semver-checks — find more details here!| 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, |
+
2 detailed updates available.
+ +Meeting minutes from meeting held on 2025-10-31 (thank you to Tomas Sedovic 🥰)
+Top-level:
+Discussion:
+Meeting notes here: 2025-11-14 - t-fls Meeting
Key developments: PR merged for 1.90 update of the FLS. We're preparing now to work on the 1.91 update of the FLS. +Blockers: None currently +Help wanted: Anyone that's familiar with the Rust Reference is more than encouraged to read through the FLS to get a sense of it and where further alignment may be possible. Feel free to open issues on the FLS repo as you find things.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby + |
+
1 detailed update available.
+ +We're putting together a prototype/demo of our reference changes at https://rust-lang.github.io/project-goal-reference-expansion/ . This includes a demonstration of tooling changes to provide stability markers (both "documenting unstable Rust" and "unstable documentation of stable Rust").
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +Key developments:
+#[test] macro addedshould_panicignoreBlockers
+Help wanted:
+| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +compiler (Manuel Drehwald), lang (TC) + |
+
| Task owners | +Manuel Drehwald, LLVM offload/GPU contributors + |
+
1 detailed update available.
+ +Time for the next update. By now, we've had std::autodiff for around a year in upstream rustc, but not in nightly. In order to get some more test users, I asked the infra team to re-evaluate just shipping autodiff as-is. This means that for the moment, we will increase the binary size of rustc by ~5%, even for nightly users who don't use this feature. We still have an open issue to avoid this overhead by using dlopen, please reach out if you have time to help. Thankfully, my request was accepted, so I spent most of my time lately preparing that release.
main.rs file, but also in dependencies (either lib.rs, or even rely on crates that use autodiff). With the help of Ben Kimock I figured out how to get the remaining cases covered, hopefully the PR will land soon.lto=fat: https://github.com/rust-lang/rust/pull/148855I have the following elements on my TODO list as part shipping AD on nightly
+AMD Ryzen 7 PRO 7840U unfortunately turned out to be not supported by AMD drivers.All in all, I think we made great progress over the last month, and it's motivating that we finally have no blockers left for flipping the llvm.enzyme config on our nightly builds.
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | +(depending on the flag) + |
+
2 detailed updates available.
+ +Update from the 2025-11-05 meeting.
+-Zharden-sls / rust#136597Wesley Wiser left a comment on the PR, Andr
+Merged, expected to ship in Rust 1.93. The Linux kernel added support for the new name for the option (-Cjump-tables=n).
Update form the 2025-11-19 meeting:
+-Zharden-sls / rust#136597Andrew addressed the comment and rebased the PR. It's waiting for a review again.
+#![register_tool] / rust#66079Tyler Mandry had an alternative proposal where lints would be defined in an external crate and could be brought in via use or something similar: https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/namespaced.20tool.20attrs.
A concern people had was the overhead of having to define a new crate and the potential difficulty with experimenting on new lints.
+Tyler suggested adding this as a future possibility to RFC#3808 and FCPing it.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +lang (Josh Triplett), lang-docs (TC) + |
+
| Task owners | ++ | +
2 detailed updates available.
+ +Update from the 2025-11-05 meeting.
+Deref/ReceiverDing Xiang Fei posted his reasoning for the trait split in the Zulip thread and suggested adding a second RFC to explain.
+TC recommended writing a Reference PR. The style forces one to explain the model clearly which should then make writing the RFC easier.
+The lang experiment PR for arbitrary self types have feature gates for the two options we're exploring.
+derive(CoercePointee) / tracking issue #44874theemathas opened an issue derive(CoercePointee) accepts ?Sized + Sized #148399. This isn't a critical issue, just an error that arguably should be a lint.
Boxy opened a fix for a derive(CoercePointee) blocker: Forbid freely casting lifetime bounds of dyn-types
+.
Ding Xiang Fei is working on the implementation (the parser and HIR interface for it). Ding's also working on a more complete section dedicated to questions raised by obi1kenobi
+Benno Lossin has been posting super detailed updates on the tracking issue
+We've discussed the idea of virtual places (see Zulip thread where they were proposed).
+Matt Mauer had an idea to compile C code into LLVM bytecode (instead of object file) and then the llvm-link tool to merge them together and treat everything in the second bytecode file as a static inlined function. Matt suggested we could integrate this into the rustc passes.
+This would make it easy to inline certain functions into Rust code without full LTO.
+Relevant Zulip thread.
+This sounds like a good candidate for the next Project Goals period.
+ +Update from the 2025-11-19 meeting.
+rustdoc checking for private and hidden items (rust##149105 & rust#149106)Miguel proposed Rust Doc checking for invalid links to items that are hidden or private even if no docs are built for them. This can help catch typos or dead links because the docs became out of date.
+Guillaume was much more open to this being a toggle, lolbinarycat opened a PR here: https://github.com/rust-lang/rust/pull/141299
+unsafe_op_in_unsafe_fn not respected in imported declarative macros rust#112504This lint doesn't trigger when importing a declarative macro that's calling unsafe code without having an unsafe block and without a SAFETY comment.
The lint is only triggered when the macro was actually used.
+imports_granularity is not respected for #[cfg]'d items / rustfmt#6666Ding opened a PR to fix this: https://github.com/rust-lang/rustfmt/issues/6666
+Ding and Manish were talking about writing up a proper fix for the vertical layout that's currently being solved by the , //, hack
TypeId layoutThis has been discussed in https://github.com/rust-lang/rust/pull/148265 and https://rust-lang.zulipchat.com/#narrow/channel/213817-t-lang/topic/TypeID.20design/near/560189854.
+Apiraino proposed a compiler design meeting here: https://github.com/rust-lang/compiler-team/issues/941. That meeting has not been scheduled yet, though.
+Deref / ReceiverFollowing TC's recommendation, Ding is drafting the Reference PR.
+derive(CoercePointee)Ding opened a PR to fix unsoundness in the DispatchFromDyn trait: https://github.com/rust-lang/rust/pull/149068
Theemathas opened a question on whether Receiver should by dyn-compatible: https://github.com/rust-lang/rust/issues/149094
const in assemblyMerged!
+Benno noted that Effects and In-place Init are not compatible with each other: https://rust-lang.zulipchat.com/#narrow/channel/528918-t-lang.2Fin-place-init/topic/Fundamental.20Issue.20of.20Effects.20and.20In-place-init/with/558268061
+This is going to affect any in-place init proposal.
+Benno proposes fixing this with keyword generics. This is a topic that will receive a lot of discussion doing forward.
+language-advisor. Fantastic news and congratulations!| Progress | ++ | +
| Point of contact | +|
| Champions | +cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols) + |
+
| Task owners | ++ | +
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +An RFC draft covering the MIR changes necessary to support this optimization has been written and is currently being reviewed by T-opsem. It has already received one round of review and the feedback has been incorporated in the draft.
+ +| Progress | ++ | +
| Point of contact | +|
| Task owners | +
|
+
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
2 detailed updates available.
+ +Instead of using a full-fledged database like SQLite, we switched to a basic JSONL-based logging system to collect build metrics. A simple design doc can be found here: https://hackmd.io/K5-sGEJeR5mLGsJLXqsHrw.
+Here are the recent pull requests:
+To enable it, set CARGO_BUILD_ANALYSIS_ENABLED=true or set the Cargo config file like this:
[build.analysis]
+enabled = true
+
+As of today (nightly-2025-11-03), it currently emits build-started and timing-info two log events to $CARGO_HOME/log/ (~/.cargo/log/ by default). The shape of timing-info JSON is basically the shape of the unstable --timing=json. I anticipate when this is stabilized we don't need --timing=json.
The build.analysis.enable is a non-blocking unstable feature. Unless bugs, should be able to set unconditionally even on stable toolchain. When not supported, it would just warn the unknown config merely.
Key developments: Started emitting basic fingerprint information, and kicked off the refactor of rendering HTML timing report for future report replay through cargo report timings command.
Blockers: no except my own availability
+Help wanted: Mendy on Zulip brought up log compression (#t-cargo > build analysis log format @ đź’¬) but I personally don't have time looking at it durnig this period. Would love to see people create an issue in rust-lang/cargo and help explore the idea.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett) + |
+
| Task owners | +oli-obk + |
+
1 detailed update available.
+ +Another related PR:
+https://github.com/rust-lang/rust/pull/148820
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +October was largely spent working out design details of the build cache and locking design.
+https://github.com/rust-lang/cargo/pull/16155 was opened with an initial implementation for fine grain locking for Cargo's build-dir however it needs to be reworked after the design clarifications mentioned above.
In November I had a change of employer so I my focus was largely on that. However, we did make some progress towards locking in https://github.com/rust-lang/cargo/pull/16230 which no longer lock the artifact-dir for cargo check. This is expected to land in 1.93.0.
I'm hoping to push fine grain locking forward later this month and in December.
+ +| Progress | +|
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +This project goal has been completed. I updated the first issue to reflect it. Closing the issue then.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Task owners | +[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec) + |
+
1 detailed update available.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Task owners | +vision team + |
+
1 detailed update available.
+ +Update:
+Jack Huey has been doing great work building out a system for analyzing interviews. We are currently looking at slicing the data along a few dimensions:
+and asking essentially the same set of questions for each, e.g., what about Rust worked well, what did not work as well, what got you into Rust, etc.
+Our plan is to prepare a draft of an RFC with some major conclusions and next steps also a repository with more detailed analysis (e.g., a deep dive into the Security Critical space).
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
1 detailed update available.
+ +The new system has been running in production without any major issues for a few weeks now. In a few weeks, I plan to start using the second collector, and then announce the new system to Project members to tell them how they can use its new features.
+ +| Progress | ++ | +
| Point of contact | +|
| Champions | ++ | +
| Task owners | +
|
+
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | +compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras) + |
+
| Task owners | ++ | +
2 detailed updates available.
+ +Notes from our meeting today:
+only keywordWe are exploring the use of a new only keyword to identify "special" bounds that will affect the default bounds applied to the type parameter. Under this proposal, T: SizeOfVal is a regular bound, but T: only SizeOfVal indicates that the T: const Sized default is suppressed.
For the initial proposal, only can only be applied to a known set of traits; one possible extension would be to permit traits with only supertraits to also have only applied to them:
trait MyDeref: only SizeOfVal { }
+fn foo<T: only MyDeref>() { }
+
+// equivalent to
+
+trait MyDeref: only SizeOfVal { }
+fn foo<T: MyDeref + only SizeOfVal>() { }
+
+We discussed a few other syntactic options:
+^SizeOfVal sigil was appealing due to the semver analogy but rejected on the basis of it being cryptic and hard to google.only T: SizeOfVal sort of made sense, but it would not compose well if we add additional families of "opt-out" traits like Destruct and Forget, and it's not clear how it applies to supertraits.After testing, we confirmed that relaxing Target bound will result in significant breakage without some kind of transitionary measures.
We discussed the options for addressing this. One option would be to leverage "Implementable trait aliases" RFC but that would require a new trait (Deref20XX) that has a weaker bound an alias trait Deref = Deref20XX<Target: only SizeOfVal>. That seems very disruptive.
Instead, we are considering an edition-based approach where (in Rust 2024) a T: Target bound is defaulted to T: Deref<Target: only SizeOfVal> and (in Rust 20XX) T: Target is defaulted to T: Deref<Target: only Pointee>. The edition transition would therefore convert bounds to one of those two forms to be fully explicit.
One caveat here is that this edition transition, if implemented naively, would result in stronger bounds than are needed much of the time. Therefore, we will explore the option of using bottom-up analysis to determine when transitioning whether the 20XX bound can be used instead of the more conservative 2024 bound.
+We explored the implications of weakening supertrait bounds a bit, looking at this example
+ + +trait FooTr<T: ?Sized> {}
+
+struct Foo<T: ?Sized>(std::marker::PhantomData<T>);
+
+fn bar<T: ?Sized>() {}
+
+trait Bar: FooTr<Self> /*: no longer MetaSized */ {
+ // ^^^^^^^^^^^ error!
+ // real examples are `Pin` and `TypeOf::of`:
+ fn foo(&self, x: Foo<Self>) {
+ // ^^^^^^^^^^^^ error!
+ bar::<Self>();
+ // ^^^^^^^^^^ error!
+
+
+ // real examples are in core::fmt and core::iter:
+ trait DoThing {
+ fn do_thing() {}
+ }
+
+ impl<T: ?Sized> DoThing for T {
+ default fn do_thing() {}
+ }
+
+ impl<T: Sized> DoThing for T {
+ fn do_thing() {}
+ }
+
+ self.do_thing();
+ // ^^^^^^^^^^^^^ error!
+ // specialisation case is not an issue because that feature isn't stable, we can adjust core, but is a hazard with expanding trait hierarchies in future if stabilisation is ever stabilised
+ }
+}
+
+The experimental_default_bounds work originally added Self: Trait bounds to default methods but moved away from that because it could cause region errors (source 1 / source 2). We expect the same would apply to us but we are not sure.
We decided not to do much on this, the focus remains on the Deref::Target transition as it has more uncertainty.
No progress since [Niko Matsakis's last comment](https://github.com/rust-lang/rust-project-goals/issues/270#issuecomment-3492255970) - intending to experiment with resolving challenges with Deref::Target and land the SVE infrastructure with unfinished parts for experimentation.
| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +
2 detailed updates available.
+ +A bit late on this update but I've sat down with lcnr a little while back and we tried to come up with a list of topics that we felt fell under type system documentation. This is an entirely unordered list and some topics may already be adequately covered in the dev guide already.
+Regardless this effectively serves as a "shiny future" for everything I'd like to have documentation about somewhere (be it dev guide or in-tree module level documentation):
+use<...> work'erased regions causes problems with outlives item bounds in livenessFn bounds are somewhat special in relation to thisimpl Trait
+impl Trait in bindingsty::Infer in ty overview-Zhigher-ranked-assumptions existsexistsA forallB A == B
+Since making this list I've started working on writing documentation about coercions/adjustments. So far this has mostly resulted in spending a lot of time reading the relevant code in rustc. I've discovered a few bugs and inconsistencies in behaviour and made some nice code cleanups which should be valuable for people learning how coercions are implemented already. This can be seen in #147565
+I intend to start actually writing stuff in the dev guide for coercions/adjustments now as that PR is almost done.
+I also intend to use a zulip thread (#t-compiler/rustc-dev-guide > Type System Docs Rewrite) for more "lightweight" and informal updates on this project goal, as well as just miscellaneous discussion about work relating to this project goal
+ +I've made a tracking issue on the dev guide repo for this project goal: rust-lang/rustc-dev-guide#2663. I've also written documentation for coercions: rust-lang/rustc-dev-guide#2662. There have been a few extra additions to the list in the previous update.
+ +| Progress | ++ | +
| Point of contact | ++ | +
| Champions | ++ | +
| Task owners | ++ | +