The 2025H2 Project Goal period has now concluded. Over these months, the Rust Project pursued 41 Project Goals, 13 of which were designated as Flagship Goals. This post contains curated updates on our progress since the last post and the final status for each of the goals (many of which continue as part of the 2026 period). Full details for any particular goal are available in its tracking issue.

Thanks to everyone who contributed! <3

Table of contents


Flagship: Beyond the &

Continue Experimentation with Pin Ergonomics

3 detailed updates available.

Design a language feature to solve Field Projections

5 detailed updates available.
  • Benno Lossincomment from 2026-01-01

  • Benno Lossincomment from 2026-01-25

    Earlier this month, Nadrieril Ding Xiang Fei and I held a meeting on autoref and method resolution in a world with field projections. This meeting resulted in a new page for the wiki on autoref.

  • Benno Lossincomment from 2026-02-28

    The first pull request of the lang experiment has just been merged: rust-lang/rust#152730

    This PR enables the use of the field_of! macro to obtain a unique type for each field of a struct, enum variant, tuple, or union. We call these types field representing types (FRTs). When the base type is a struct that is not repr(packed), only contains Sized fields, this type automatically implements the Field trait that exposes some information about the field to the type system. The offset in bytes from the start of the struct, the type of the field and the type of the base type.

    The feature is still incomplete and highly experimental. We also want to tackle the limitations in future PRs. For the moment this is enough to give us the ability to experiment with library versions of field projections and write functions that are generic over the fields of structs. For example one can write code like this:

    #![feature(field_projections)]
    
    use std::field::{Field, field_of};
    use std::ptr;
    
    fn project_ref<'a, T, F: Field<Base = T>>(r: &'a T) -> &'a F::Type {
        // SAFETY: the `Field` trait guarantees that this is sound.
        unsafe { &*ptr::from_ref(r).byte_add(F::OFFSET).cast() }
    }
    
    struct Struct {
        field: i32,
        other: u32,
    }
    
    fn main() {
        let s = Struct { field: 42, other: 24 };
        let r = &s;
        let field = project_ref::<_, field_of!(Struct, field)>(r);
        let other = project_ref::<_, field_of!(Struct, other)>(r);
        println!("field: {field}"); // prints 42
        println!("other: {other}"); // prints 24
    }

    A very important feature of the types returned by field_of! is that you can implement traits for them if you own the base type. This allows anointing fields with information by extending the Field trait. For example, this allows encoding the property of being a structurally pinned field:

    use std::pin::Pin;
    
    unsafe trait PinnableField: Field {
        type StructuralRefMut<'a>
        where
            Self::Type: 'a,
            Self::Base: 'a;
    
        fn project_mut<'a>(base: Pin<&'a mut Self::Base>) -> Self::StructuralRefMut<'a>
        where
            Self::Type: 'a,
            Self::Base: 'a;
    }
    
    fn project_pinned<'a, T, F>(r: Pin<&'a mut T>) -> <F as PinnableField>::StructuralRefMut<'a>
    where
        F: PinnableField<Base = T>,
    {
        F::project_mut(r)
    }

    We can then implement this extra trait for all of the fields of our struct (and automate that with a proc-macro):

    unsafe impl PinnableField for field_of!(Struct, field) {
        type StructuralRefMut<'a> = &'a mut i32;
    
        fn project_mut<'a>(base: Pin<&'a mut Self::Base>) -> Self::StructuralRefMut<'a>
        where
            Self::Type: 'a,
            Self::Base: 'a,
        {
            let base = unsafe { Pin::into_inner_unchecked(base) };
            &mut base.field
        }
    }
    
    unsafe impl PinnableField for field_of!(Struct, other) {
        type StructuralRefMut<'a> = Pin<&'a mut u32>;
        // u32 is `Unpin`, so this isn't doing anything special, but it highlights the pattern.
    
        fn project_mut<'a>(base: Pin<&'a mut Self::Base>) -> Self::StructuralRefMut<'a>
        where
            Self::Type: 'a,
            Self::Base: 'a,
        {
            let base = unsafe { Pin::into_inner_unchecked(base) };
            unsafe { Pin::new_unchecked(&mut base.other) }
        }
    }

    Now you can safely obtain a pinned mutable reference to other and a normal mutable reference to field by calling the project_pinned function and supplying the correct FRT.

    (playground link)

  • Benno Lossincomment from 2026-03-20

    Plan for 2026

    We have an updated plan for this goal in 2026 consisting of three major steps:

    • a-mir-formality,
    • Implementation,
    • Experimentation.

    Some of their subtasks depend on other subtasks for other steps. You can find the details in the updated tracking issue. Here is a short rundown of each:

    a-mir-formality: we want to create a formal model of the borrow checker changes we're proposing to ensure correctness. We also want to create a document explaining our model in a more human-friendly language. To really get started with this, we're blocked on the new expression based syntax in development by Niko.

    Implementation: at the same time, we can start implementing more parts in the compiler. We will continue to improve FRTs, while keeping in mind that we might remove them if they end up being unnecessary. They still pose for a useful feature, but they might be orthogonal to field projections. We plan to make small and incremental changes, starting with library additions. We also want to begin exploring potential desugarings, for which we will add some manual and low level macros. When we have that figured out, we can fast-track syntax changes. When we have a sufficiently mature formal model of the borrow checker integration, we will port it to the compiler. After further evaluation, we can think about removing the incomplete_feature flag.

    Experimentation: after each compiler or standard library change, we look to several projects to stress-test our ideas in real code. I will take care of experimentation in the Linux kernel, while Tyler Mandry will be taking a look at testing field projections with crubit. Josh Triplett also has expressed eagerness of introducing them in the standard library; I will coordinate with him and the rest of t-libs-api to experiment there.

  • Benno Lossincomment from 2026-04-02

    Yesterday, we held a t-lang design meeting on our current approach. Nadrieril and I authored a design document with the feedback of Tyler Mandry, Ding Xiang Fei, Alice Ryhl, and Gary Guo. In this document, we provided the motivation for this feature, what the look and feel of a solution fitting into the existing features of Rust is, and a comprehensive + compact introduction to our current approach based on virtual places.

    The general reception was extremely positive. To give some concrete quotes from the meeting:

    • Josh:

      I adore this! I love how orthogonal it is, and how impactful and universal it is. I anticipate this becoming a beloved, pervasive feature of Rust.

      Places and projection seem important enough to me that they're worth giving one of our precious remaining ASCII sigils to, and @ is nicely evocative of a place (something is at a place). So to the extent the final syntax benefits from a sigil, :+1: for giving this @. (See some feedback below on the details, though.)

    • TC:

      Love it. High concept. As I said in the last meeting:

      I particularly like language features that reduce the need for library surface area, and this is one of those.

      There are, of course, many details to resolve and understand further, e.g., with respect to migration issues, interaction with const, async, and other effect-like things, etc. I'm looking forward to seeing the formalization work.

    • tmandry:

      What I love about this direction is how effectively it builds on what Rust already has. I love to see designs that reinforce our existing concepts while pushing them in directions that make them more expressive.

    • Jack:

      Whoo boy. This is great. There's so much here that I'm not exactly sure where to begin and what to comment on. I think this is the type of thing that we will only really be able to figure out the nitty gritty details and ergonomics only after some amount of experimentation.

    There are a few takeaways from this meeting:

    • Mark raised the concern that t-libs should be more involved in reviewing the experimental traits that we intend to add. Ensuring that we don't accidentally stabilize or expose some behavior, have sufficient documentation on our experimental traits, and that t-libs is in the loop of this feature in general.
      • Mark offered to review PRs and I will be tagging him in those.
    • Jack raised the concern that increasing the cognitive load for the 95% use-case should be avoided. Making the right choice between @ and & might be challenging for users.
      • We discussed this point more in the meeting and concluded with that we need to do some experimentation, possibly utilizing the user research team. We will of course keep this in mind and revisit it later when we have a partially working implementation.
    • TC requested that we publish our fine-grained design axioms, essentially the list of things we go through when considering a modification of our proposal.
      • I will write an update on this issue explaining exactly those.

    Aside from the concerns and directly actionable items, the meeting also covered design questions/comments that we want to take a look at in the coming weeks/months:

    Thanks to everyone who participated in the meeting!

Reborrow traits

1 detailed update available.
  • Aapo Alasuutaricomment from 2026-02-28

    PR open to get the first working version of the Reborrow and CoerceShared traits merged.

    Blockers

    Currently "blocked" on PR review, and of course my (and Ding's) work to fix all review issues.

    The review has brought up an opportunity to replace Rvalue::Ref / ExprKind::Ref with a more generalised variant that could encompass both references and user-defined references. This would be powerful, but it would be a very big and scary change. If this turns out to be a blocking issue for reviewers, then this will block the goal for the foreseeable future as the PR then starts on a massive refactoring.

    Help wanted

    The PR currently does not include derive traits, but we'd really want them. Instead of these:

    impl<'a> Reborrow for CustomMarker<'a> {}
    impl<'a> CoerceShared<CustomMarkerRef<'a>> for CustomMarker<a'> {}
    
    impl<'a, T> Reborrow for CustomMut<'a, T> {}
    impl<'a, T> CoerceShared<CustomRef<'a, T>> for CustomMut<'a, T> {}

    we'd prefer to have something like this:

    #[derive(Reborrow, CoerceShared(CustomMarkerRef))]
    struct CustomMarker<'a> { ... }
    
    #[derive(Reborrow, CoerceShared(CustomRef))]
    struct CustomMut<'a, T> { ... }

    If anyone feels like picking up this thread, that'd be awesome: the derive macros do not need to really perform any validity checking, as the trait itself will do that.

    If the PR merges soon, then public testing and exploration of the traits will be the next big thing. Likely concurrently with that the massive refactoring to generalise Rvalue::Ref / ExprKind::Ref.

Flagship: Flexible, fast(er) compilation

build-std

4 detailed updates available.

Production-ready cranelift backend

Promoting Parallel Front End

Relink don't Rebuild

Flagship: Higher-level Rust

Ergonomic ref-counting: RFC decision and preview

Stabilize cargo-script

3 detailed updates available.

Flagship: Unblocking dormant traits

Evolving trait hierarchies

In-place initialization

1 detailed update available.

Next-generation trait solver

1 detailed update available.

Stabilizable Polonius support on nightly

2 detailed updates available.
  • Rémy Rakiccomment from 2026-01-30

    This month's update:

    • tiif is making progress on normalizing opaques while computing implied bounds
    • we discussed how to investigate and fix the remaining correctness issues in Tage's work, to be able to evaluate it more accurately: in particular around variance and bidirectional edges, and without the reliance on NLL (having computed region values / errors)
    • we've tried to see if it'd be possible to remove the cfg region elements
    • Amanda is still working on her two papers, one about the current borrow checker and one about the work on Polonius. Her major PR for the restructuring of placeholder handling during region inference is stalled due to a conflict with further trait solver developments and may have to be abandoned. Work with the larger types team is ongoing and smaller patches/refactorings/improvements are being landed in the meantime.
    • #149639 has now landed, and #150551 is still in review
    • I've also fixed more small inefficiencies (computing boring/relevant locals on-demand in diagnostics, removed conversions between locations and points, etc) building on top of the previous PRs (so they need to be reviewed first)
    • I've looked at crates.io again with the alpha, to find functions that are slower than with NLLs. AFAICT the worst case there is 60% for a 5KLOC function with 42K loans, 255K statements, and 125K outlives constraints. I'll see what we can do with this. Small composable functions is still good advice.
    • there seem to be optimization opportunities to 1. limit propagation to the smaller number of blocks that could be affected by bidirectional edges, 2. for unifying invariant lifetimes of live locals that are assigned at most once (à la use-def chains), 3. for invalidations that are just the activation of a reservation
    • we discussed possible plans to gather actual statistics, using the infrastructure that was created for the Metrics project
    • we're also preparing the new project goal for this year, where we'll want to stabilize the alpha 🤞
  • Rémy Rakiccomment from 2026-02-28

    We had a bit less time this month, the update will be shorter, but still meaningful I hope:

    • #150551 has landed, and it feels stabilizable. To me, this part of the goal is achieved.
    • still, "stabilizable" is not stable, and there is more work to do. We plan to stabilize this year, and the project goal proposal for 2026 tracks how.
    • tiif is still deep in #152051, and a-mir-formality work with Niko and I.
    • Amanda has opened a few cleanup PRs (#152438, and #152579), and #151863 has landed already. She also has started looking into Tage's old PR to see if we can fix it, benchmark it more accurately, and see the cool parts there that we could be using.
    • Jack is possibly going to have some time to work with us this year! His help will be very welcome, especially as I will have less time available myself.
    • we'll be tracking the opaque type region liveness soundness issue in #153215, and I've added a couple tests, in case tiif's PR or anything that impacts them lands.
    • some of the tiny cleanups I mentioned last time have also landed in #152587.

Other goal updates

Add a team charter for rustdoc team

Borrow checking in a-mir-formality

C++/Rust Interop Problem Space Mapping

5 detailed updates available.