Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Project goals

This repo tracks the effort to set and track goals for the Rust project.

Next goal period (2026)

The next goal period will be 2026. We are currently in the process of assembling goals. Click here to see the current list. If you’d like to propose a goal, instructions can be found here.

Current goal period (2025H2)

The 2025H2 goal period runs from Sept 1 to Dec 31. We have identified 12 flagship goals, broken out into four themes:

  • Beyond the &, making it possible to create user-defined smart pointers that are as ergonomic as Rust’s built-in references &.
  • Unblocking dormant traits, extending the core capabilities of Rust’s trait system to unblock long-desired features for language interop, lending iteration, and more.
  • Flexible, fast(er) compilation, making it faster to build Rust programs and improving support for specialized build scenarios like embedded usage and sanitizers.
  • Higher-level Rust, making higher-level usage patterns in Rust easier.

“Beyond the &

One of Rust’s core value propositions is that it’s a “library-based language”—libraries can build abstractions that feel built-in to the language even when they’re not. Smart pointer types like Rc and Arc are prime examples, implemented purely in the standard library yet feeling like native language features. However, Rust’s built-in reference types (&T and &mut T) have special capabilities that user-defined smart pointers cannot replicate. This creates a “second-class citizen” problem where custom pointer types can’t provide the same ergonomic experience as built-in references.

The “Beyond the &” initiative aims to share &’s special capabilities, allowing library authors to create smart pointers that are truly indistinguishable from built-in references in terms of syntax and ergonomics. This will enable more ergonomic smart pointers for use in cross-language interop (e.g., references to objects in other languages like C++ or Python) and for low-level projects like Rust for Linux which use smart pointers to express particular data structures.

“Unblocking dormant traits”

Rust’s trait system is one of its most powerful features, but it has a number of longstanding limitations that are preventing us from adopting new patterns. The goals in this category unblock a number of new capabilities:

  • Polonius will enable new borrowing patterns, and in particular unblock “lending iterators”. Over the last few goal periods we have identified an “alpha” version of polonius that addresses the most important cases while being relatively simple and optimizable. Our goal for 2025H2 is to implement this algorithm in a form that is ready for stabilization in 2026.
  • The next gen trait solver is a refactored trait solver that unblocks better support for numerous language features (implied bounds, negative impls, the list goes on) in addition to closing a number of existing bugs and unsoundnesses. Over the last few goal periods, the trait solver went from early prototype to being production use in coherence. The goal for 2025H2 is to prepare it for stabilization.
  • The work on evolving trait hierarchies will make it possible to refactor some parts of an existing trait out into a new supertrait so they can be used on their own. This unblocks a number of features where the existing trait is insufficiently general, in particular stabilizing support for custom receiver types, a prior project goal that wound up blocking on this refactoring. This will also make it safer to provide stable traits in the standard library, while preserving the ability to evolve them in the future.
  • The work to expand Rust’s Sized hierarchy will permit us to express types that are neither Sized nor ?Sized, such as extern types (which have no size) or ARM’s Scalable Vector Extensions (which have a size that is known at runtime, but not compilation time). This goal builds on RFC #3729 and RFC #3838, authored in previous project goal periods.
  • In-place initialization allows creating structs and values that are tied to a particular place in memory. While useful directly for projects doing advanced C interop, it also unblocks expanding dyn Trait to support for async fn and -> impl Trait methods, as compiling such methods requires the ability for the callee to return a future whose size is not known to the caller.

“Flexible, fast(er) compilation”

The “Flexible, fast(er) compilation” initiative focuses on improving Rust’s build system to better serve both specialized use cases and everyday development workflows:

“Higher-level Rust”

People generally start using Rust for foundational use cases, where the requirements for performance or reliability make it an obvious choice. But once they get used to it, they often find themselves turning to Rust even for higher-level use cases, like scripting, web services, or even GUI applications. Rust is often “surprisingly tolerable” for these high-level use cases – except for some specific pain points that, while they impact everyone using Rust, hit these use cases particularly hard. We plan two flagship goals this period in this area:

  • We aim to stabilize cargo script, a feature that allows single-file Rust programs that embed their dependencies, making it much easier to write small utilities, share code examples, and create reproducible bug reports without the overhead of full Cargo projects.
  • We aim to finalize the design of ergonomic ref-counting and to finalize the experimental impl feature so it is ready for beta testing. Ergonomic ref counting makes it less cumbersome to work with ref-counted types like Rc and Arc, particularly in closures.

The full list of 2025H2 goals is available here. We author monthly blog posts about our overall status, but you can also follow the tracking issue for a particular goal to get updates specific to that goal.

About the process

Want to learn more? Check out some of the following:

Rust project goals 2026

Summary

Status: Revising first draft We are in the process of revising the first draft of the goal slate. New proposals are still accepted but they must already have team consensus and appropriate champions.

This is a draft for the eventual RFC proposing the 2026 goals.

Motivation

The 2026 goal slate consists of 59 project goals. In comparison to prior rounds, we have changed to annual goals rather than six-month goal periods. Annuals goals give us more time to discuss and organize.

Why we set goals

Goals serve multiple purposes.

For would-be contributors, goals are Rust’s front door. If you want to improve Rust - whether that’s a new language feature, better tooling, or fixing a long-standing pain point - the goal process is how you turn that idea into reality. When you propose a goal and teams accept it, you get more than approval. You get a champion from the relevant team who will mentor you, help you navigate the project, and ensure your work gets the review attention it needs. Goals are a contract: you commit to doing the work, the project commits to supporting you.

For users, goals serve as a roadmap, giving you an early picture of what work we expect to get done this year.

For Rust maintainers, goals help to surface interactions across teams. They aid in coordination because people know what work others are aiming to do and where they may need to offer support.

Goals are proposed by contributors and accepted by teams

As an open-source project, Rust’s goal process works differently than a company’s. In a company, leadership sets goals and assigns employees to execute them. Rust doesn’t have employees - we have contributors who volunteer their time and energy. So in our process, goals begin with the contributor: the person (or company) that wants to do the work.

Contributors propose goals; Rust teams accept them. When you propose a goal, you’re saying you’re prepared to invest the time to make it happen. When a team accepts, they’re committing to support that work - doing reviews, engaging in RFC discussions, and providing the guidance needed to land it in Rust.

How these goals were selected

Goal proposals were accepted during the month of January. Many of the goals are continuing goals that are carried over from the previous year, but others goal are new.

In February, an alpha version of this RFC is reviewed with teams. Teams vet the goals to determine if they are realistic and to make sure that goal have champions from the team. A champion is a Rust team member that can will mentor and guide the contributor as they do their work. Champions keep up with progress on the goal, help the champion figure out technical challenges, and also help the contributor to navigate the Rust team(s). Champions also field questions from others in the project who want to understand the goal.

How to follow along with a goal’s progress

Once the Goals RFC is accepted, you can follow along with the progress on a goal in a few different ways:

  • Each goal has a tracking issue. Goal contributors and champions are expected to post regular updates. These updates are also posted to Zulip in the #project-goals channel.
  • Regular blog posts cover major happenings in goals.

Highlights from the 2026 goals

There are a total of 59 planned for this year. That’s a lot! You can see the complete list, but to help you get a handle on it, we’ve selected a few to highlight. These are goals that will be stabilizing this year or which we think people will be particularly excited to learn about.

Important: You have to understand the nature of a Rust goal. Rust is an open-source project, which means that progress only happens when contributors come and make it happen. When the Rust project declares a goal, that means that (a) contributors, who we call the task owners, have said they want to do the work and (b) members of the Rust team members have promised to support them. Sometimes those task owners are volunteers, sometimes they are paid by a company, and sometimes they supported by grants. But no matter which category they are, if they ultimately are not able to do the work (say, because something else comes up that is higher priority for them in their lives), then the goal won’t happen. That’s ok, there’s always next year!

Cargo improvements

Stabilize cargo-script

Ed Page (point of contact)

Stabilize support for “cargo script”, the ability to have a single file that contains both Rust code and a Cargo.toml.

Language changes

Const Generics

Boxy (point of contact), Niko Matsakis (lang champion), Boxy (types champion)

Extend const generics in two independent directions, both aiming for stabilization:

  • adt_const_params: Allow structs and enums as const generic arguments, not just integers.
  • min_generic_const_args: Allow associated constants as const generic arguments (e.g., Foo<T::ASSOC_CONST>).

We will also model const generics in a-mir-formality and experiment with upstreaming those changes into the Rust specification. This work also serves as a forcing function for advancing a-mir-formality and its integration into the Rust specification.

Stabilize the next-generation trait solver

lcnr (point of contact), Niko Matsakis (lang champion), lcnr (types champion)

Stabilize -Znext-solver=globally, replacing the existing trait solver implementation entirely.

Sized Hierarchy and Scalable Vectors

David Wood (point of contact), David Wood (compiler champion), Niko Matsakis (lang champion), Amanieu d’Antras (libs-api champion), lcnr (types champion)

Over the next year, we will build on the foundational work from 2025 to stabilize the Sized trait hierarchy and continue nightly support for scalable vectors:

  • Stabilize the refined Sized trait hierarchy (without constness), unblocking extern types
  • Propose and implement const Sized to support scalable vectors
  • Achieve RFC acceptance for [rfcs#3838] (Scalable Vectors)
  • Land SVE types and intrinsics in stdarch for nightly experimentation
  • Continue addressing stabilization blockers for SVE itself
  • Begin design work for supporting the Scalable Matrix Extension (SME)

The const Sized work (Part II of [rfcs#3729]) is deferred to a future goal, allowing us to deliver value sooner through the trait hierarchy stabilization. This future work interacts with ongoing const generics efforts, as const Sized depends on progress in const traits.

Other

Stabilize MemorySanitizer and ThreadSanitizer Support

Jakob Koschel (point of contact)

Stabilize the MemorySanitizer and ThreadSanitizer support. This includes fixing open bugs for the sanitizers to open a path for stabilization and the necessary infrastructure changes to provide precompiled and instrumented standard libraries for the sanitizers.

Wasm Components

Yoshua Wuyts (point of contact)

In 2026 we want to improve the state of Wasm Component support in Rust. This means adding and stabilizing three new compiler targets, as well as begin experimentation with Wasm-specific language features.

Help wanted Help Wanted

This section contains goals that are in need of help.

Looking for contributors

The goals below are looking for a contributor to do the implementation work. The goal summaries include details of the expected time commitment and work duration. If you might be interested in helping with a goal, please join the rust-lang Zulip and post a message in the #project-goals/2026-workshop channel: tell us a bit about yourself, and mention us (the goals team) in that message, like Hello @T-goals!. You could also write to the goals team at goals-team@rust-lang.org! We would love to help you learn more about it.

Box notation for dyn async trait Help wanted

Niko Matsakis (point of contact), Niko Matsakis (lang champion)

Introduce .box notation and use it to enable dyn dispatch for traits with async methods. The initial scope is foo.method().box where method() returns a dyn-compatible RPITIT. In the future .box could be used more generally but before expanding it we would like to see progress on the work towards in-place initialization.

Contingent on contributor: Niko Matsakis is able to devote 1h/wk to support an experienced contributor or a cohort of contributors in driving this design forward as a lang experiment. This is a challenging problem that will require modifying various parts of the compiler and would also benefit from modeling in a-mir-formality.

Prototype a new set of Cargo “plumbing” commands Help wanted

Ed Page (point of contact)

  1. Refactor Cargo to allow hacks in proposed cargo-plumbing commands to be removed (cargo-plumbing#82).
  2. Round out proposed commands (issues)
  3. Finalize the message formats (cargo-plumbing#18)

Contingent on contributor: This goal needs contributors to refactor Cargo internals, implement remaining plumbing commands, optimize performance, and iterate on output schemas. The work is primarily in rust-lang/cargo and crate-ci/cargo-plumbing. Estimated time commitment: TBD.

Ergonomic ref-counting: Share trait and move expressions Help wanted

Niko Matsakis (point of contact), Niko Matsakis (lang champion)

Implement and prototype two foundational improvements for ergonomic ref-counting: (1) a Share trait that semantically identifies types where cloning creates an alias to the same underlying value, and (2) move expressions (move($expr)) that allow precise control over what closures capture and when. These changes lay groundwork for future ergonomic improvements while delivering immediate value, with prototypes targeted for summer 2026.

Contingent on contributor: This is a medium complexity problem. Niko Matsakis would like to mentor this goal with either an experienced contributor or a cohort of folks who know Rust but not the compiler. It is estimated that the goal will take about 6 months to implement for a cohort with minimal compiler hacking experience.

Control over Drop semantics Help wanted

@thunderseethe (point of contact)

Allow users to easily control the drop semantics of struct fields, letting them change drop order, and disable recursive destructors to make working with cross-language bindings easier.

  • Allow cross-language bindings to expose struct fields without compatibility hazards, and
  • Make all code that disables default destructor behavior more convenient to use in Rust.

Contingent on contributor: This goal needs a contributor to implement a lang experiment in rustc and write an RFC. The work is a focused compiler feature touching drop semantics and destructor codegen. Estimated time commitment: TBD.

Implement Open Rust Namespace Support Help wanted

Ed Page (point of contact)

Navigate the cross-team design work to get RFC 3243 implemented.

Contingent on contributor: This goal needs contributors to help complete the implementations in Cargo, rustc, and crates.io. The work spans multiple repositories and involves cross-team coordination. Estimated time commitment: TBD.

Stabilize public/private dependencies Help wanted

Ed Page (point of contact)

Implement and stabilize the MVP of public dependencies described in RFC #3516. Public dependencies allow crates to declare dependencies whose types are meant to be exposed in the public API.

Contingent on contributor: This goal needs a contributor to work with the compiler team on identifying and implementing the minimal lint subset needed for stabilization. The work spans rustc (lint implementation) and Cargo (dependency metadata). Estimated time commitment: TBD.

Prepare TAIT + RTN for stabilization Help wanted

Niko Matsakis (point of contact), Niko Matsakis (lang champion), lcnr (types champion)

Prepare TAIT (type alias impl trait) and return type notation (RTN) for stabilization together, giving Rust a coherent story for naming and bounding previously unnameable and unboundable types. TAIT lets users name opaque types like closures, async blocks, and complex iterators without boxing. RTN enables bounds like T::method(..): Send, solving the “Send bound” problem and unblocking widespread use of async fn in traits. This goal also extends RTN to async closures via a new RFC. Full stabilization is blocked on the next-gen trait solver work and is intended to happen late this year.

Contingent on contributor: The majority of the impl work for TAIT and RTN has been done however the syntactic design for RTN and async closures is incomplete. Niko Matsakis is seeking someone willing to help work on the RFC and explore the design space as well as to finalize impl details.

Stabilize Cargo SBOM precursor Help wanted

Sergey Davidoff (point of contact)

Progress towards an MVP version of Cargo SBOM support by resolving known issues in Cargo’s SBOM precursor feature and finalizing the RFC.

Contingent on contributor: This goal needs contributors to help with testing, resolving known issues in Cargo’s SBOM precursor, and converting downstream tooling like cargo-cyclonedx. The work is primarily in the rust-lang/cargo repository. Estimated time commitment: TBD.

Looking for funds

The goals below are looking for funding. The goal summaries include details of the expected time commitment and work duration. If you might be interested in helping to fund a goal, please join the rust-lang Zulip and post a message in the #project-goals/2026-workshop channel or write to the goals team at goals-team@rust-lang.org.

Improve rustc_codegen_cranelift performance

bjorn3 (point of contact)

This goal aims to improve the rust development experience through faster incremental code generation with rustc_codegen_cranelift. We additionally want to fix several long-standing bugs that currently prevent rustc_codegen_cranelift from being used for popular crates.

Contingent on funding: This goal is contingent on finding funding for this effort.

Control over Drop semantics Help wanted

@thunderseethe (point of contact)

Allow users to easily control the drop semantics of struct fields, letting them change drop order, and disable recursive destructors to make working with cross-language bindings easier.

  • Allow cross-language bindings to expose struct fields without compatibility hazards, and
  • Make all code that disables default destructor behavior more convenient to use in Rust.

Contingent on contributor: This goal needs a contributor to implement a lang experiment in rustc and write an RFC. The work is a focused compiler feature touching drop semantics and destructor codegen. Estimated time commitment: TBD.

Stabilize concrete type specialization

Tyler Mandry (point of contact)

Follow stabilization of the new trait solver this year by stabilizing a subset of specializing impls: Impls that follow the [always applicable] rule. This roughly corresponds to specializing trait impls on concrete types.

Stabilize the Try trait

Tyler Mandry (point of contact)

Stabilize the Try trait, which customizes the behavior of the ? operator.

Roadmaps: Looking to the future

Looking past 2026, we have a number of ongoing roadmaps. Roadmaps are collections of goals aimed at achieving a particular purpose.

Each roadmap has a point of contact who can give more technical details. If you’d be interested in helping to accelerate a roadmap with funding, please get in touch with the Rust Foundation who will help coordinate with the open-source project.

RoadmapPoint of contactWhat and why
Beyond the &Tyler MandrySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Building blocksEd PageStable, machine-readable Cargo plumbing commands; rebuild std on stable
Constify all the thingsOliver SchererConst generics accept structs and enums; compile-time reflection means serialize(&my_struct) works without derives
Just add asyncNiko MatsakisPatterns that work in sync Rust should work in async Rust — traits, closures, drop, scoped tasks
Rust for LinuxTomas SedovicBuild the Linux kernel with only stable language features.
Safety-Critical RustPete LeVasseurMC/DC coverage, a specification that tracks stable releases, and unsafe documentation — the evidence safety assessors need
Secure your supply chainTBDAccurate SBOMs, SemVer violation detection, explicit public/private dependencies
Unblocking dormant traitsTBDNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring

Application areas

We’ve organized the roadmaps by the application areas that they benefit (many roadmaps appear in multiple areas).

Network services

Async servers, middleware, and cloud infrastructure.

RoadmapPoint of contactWhat and why
Beyond the &Tyler MandrySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Just add asyncNiko MatsakisPatterns that work in sync Rust should work in async Rust — traits, closures, drop, scoped tasks
Unblocking dormant traitsTBDNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring

Systems & embedded

Kernels, drivers, embedded firmware, SIMD, and performance-critical code.

RoadmapPoint of contactWhat and why
Beyond the &Tyler MandrySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Constify all the thingsOliver SchererConst generics accept structs and enums; compile-time reflection means serialize(&my_struct) works without derives
Rust for LinuxTomas SedovicBuild the Linux kernel with only stable language features.
Unblocking dormant traitsTBDNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring

Cross-language interop

FFI, C++/Python/JS bindings, and mixed-language codebases.

RoadmapPoint of contactWhat and why
Beyond the &Tyler MandrySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Unblocking dormant traitsTBDNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring

Enterprise integration

Build system integration, tooling, and supply chain management for organizations adopting Rust at scale.

RoadmapPoint of contactWhat and why
Building blocksEd PageStable, machine-readable Cargo plumbing commands; rebuild std on stable
Secure your supply chainTBDAccurate SBOMs, SemVer violation detection, explicit public/private dependencies

Safety-critical & regulated

Automotive, aerospace, medical, and industrial systems requiring certification evidence.

RoadmapPoint of contactWhat and why
Safety-Critical RustPete LeVasseurMC/DC coverage, a specification that tracks stable releases, and unsafe documentation — the evidence safety assessors need
Secure your supply chainTBDAccurate SBOMs, SemVer violation detection, explicit public/private dependencies

Reference: all goals and roadmaps

This section contains the complete lists of application areas, roadmaps, and goals for 2026:

  • A goal is a specific feature or project.
  • Goals are collected into larger roadmaps that tell a more complete story. A single goal can be involved in many roadmaps.
  • Roadmaps are themselves organized into distinct application areas.

Application areas

Roadmaps

RoadmapPoint of contactWhat and why
Beyond the &Tyler MandrySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Building blocksEd PageStable, machine-readable Cargo plumbing commands; rebuild std on stable
Constify all the thingsOliver SchererConst generics accept structs and enums; compile-time reflection means serialize(&my_struct) works without derives
Just add asyncNiko MatsakisPatterns that work in sync Rust should work in async Rust — traits, closures, drop, scoped tasks
Rust for LinuxTomas SedovicBuild the Linux kernel with only stable language features.
Safety-Critical RustPete LeVasseurMC/DC coverage, a specification that tracks stable releases, and unsafe documentation — the evidence safety assessors need
Secure your supply chainTBDAccurate SBOMs, SemVer violation detection, explicit public/private dependencies
Unblocking dormant traitsTBDNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring

Goals

Just because a goal is listed on this list does not mean the goal has been accepted. The owner of the goal process makes the final decisions on which goals to include and prepares an RFC to ask approval from the teams.

Goals by size

Large goals

Large goals require the engagement of entire team(s). The teams that need to engage with the goal are highlighted in bold.

Medium goals

Medium goals require support from an individual, the team champion.

GoalPoCTeamChampion
Box notation for dyn async traitHelp WantedcompilerTBD
langNiko Matsakis
typesn/a
asm_const_ptrAlice Ryhllang-docsTBD
langTBD
libs-apin/a
libsn/a
Assumptions on BindersBoxytypesBoxy
Async Future Memory OptimisationDing Xiang FeicompilerTBD
Async statemachine optimisation@diondoktercompilerTBD
BorrowSanitizerIan McCormackcompilerRalf Jung
opsemRalf Jung
infran/a
langn/a
Cargo cross workspace cacheRoss SullivancargoEd Page
cfg(no_fp_fmt_parse)@todolang-docsTBD
langTBD
libs-apin/a
libsn/a
Crate Slicing for Faster Fresh Builds@yijunyucargoTBD
compilerTBD
langn/a
rust-analyzern/a
typesn/a
Ergonomic ref-counting: Share trait and move expressionsHelp WantedlangNiko Matsakis
compilern/a
lang-docsn/a
libs-apin/a
Case study for experimental language specification, with integration into project teams and processesJack HueylangJosh Triplett
typesJack Huey
specn/a
Project goal - High-Level ML optimizationsManuel DrehwaldcompilerOliver Scherer
langTC
infran/a
Improve rustc_codegen_cranelift performancebjorn3compilerTBD
cargon/a
In-place initializationAlice RyhllangTBD
Incremental Systems RethoughtAlejandra GonzálezcompilerTBD
C++/Rust Interop Problem Space MappingJon BaumanopsemTBD
compilern/a
langn/a
libs-apin/a
Control over Drop semanticsHelp WantedlangTBD
compilern/a
opsemn/a
typesn/a
Implement and Maintain MC/DC Coverage Support@RenjiSanncompilerTBD
project-stable-mirTBD
infran/a
Open Enums@kupiakoscompilerTBD
langTBD
libsn/a
opsemn/a
typesn/a
Nightly support for function overloading in FFI bindings@ssbrlangTBD
compilern/a
libs-apin/a
typesn/a
Continue Experimentation with Pin ErgonomicsFrank KingcompilerOliver Scherer
langTC
typesOliver Scherer
Stabilize public/private dependenciesHelp WantedcompilerTBD
cargon/a
Reborrow traitsAapo AlasuutarilangTyler Mandry
compilern/a
typesn/a
Prepare TAIT + RTN for stabilizationHelp WantedlangNiko Matsakis
typeslcnr
Stabilize Rust for Linux compiler featuresTomas SedoviccompilerWesley Wiser
Sized Hierarchy and Scalable VectorsDavid WoodlangNiko Matsakis
libs-apiAmanieu d’Antras
typeslcnr
compilern/a
Stabilize MemorySanitizer and ThreadSanitizer SupportJakob KoschelbootstrapTBD
compilerTBD
project-exploit-mitigationsTBD
infran/a
Stabilize Cargo SBOM precursorHelp WantedcargoTBD
Stabilize the Try traitTyler MandrylangTBD
libsTBD
compilern/a
typesn/a
Implement Supertrait auto implTyler MandrylangTBD
typesBoxy
used_with_arg@todolang-docsTBD
langTBD
libs-apin/a
libsn/a

Small goals

Small goals are covered by standard team processes and do not require dedicated support from anyone.

Goals by champion

Champion#Goals
Amanieu d’Antras2° MIR move elimination
° Sized Hierarchy and Scalable Vectors
Boxy4° Assumptions on Binders
° Const Generics
° Implement Supertrait auto impl
° Reborrow traits
Ralf Jung2° BorrowSanitizer
° Normative Documentation for Sound unsafe Rust
Wesley Wiser1° Stabilize Rust for Linux compiler features
Alona Enraght-Moony1° Continue resolving cargo-semver-checks blockers for merging into cargo
Boxy1° Type System Documentation
David Wood1° Sized Hierarchy and Scalable Vectors
Ding Xiang Fei1° Field Projections
David Tolnay1° C++/Rust Interop Problem Space Mapping
Ed Page2° Cargo cross workspace cache
° Continue resolving cargo-semver-checks blockers for merging into cargo
Jack Huey4° Arbitrary Self Types
° Case study for experimental language specification, with integration into project teams and processes
° Expanding a-mir-formality to work better as a Rust type system spec
° Stabilize the polonius alpha analysis
Josh Triplett2° Case study for experimental language specification, with integration into project teams and processes
° reflection and comptime
lcnr4° Immobile types and guaranteed destructors
° Prepare TAIT + RTN for stabilization
° Sized Hierarchy and Scalable Vectors
° Stabilize the next-generation trait solver
Rémy Rakic1° Field Projections
Niko Matsakis6° Box notation for dyn async trait
° Const Generics
° Ergonomic ref-counting: Share trait and move expressions
° Prepare TAIT + RTN for stabilization
° Sized Hierarchy and Scalable Vectors
° Stabilize the next-generation trait solver
Oliver Scherer5° C++/Rust Interop Problem Space Mapping
° Continue Experimentation with Pin Ergonomics
° Project goal - High-Level ML optimizations
° Stabilize Const Traits
° reflection and comptime
Scott McMurray1° reflection and comptime
Tyler Mandry5° Arbitrary Self Types
° BorrowSanitizer
° C++/Rust Interop Problem Space Mapping
° Field Projections
° Reborrow traits
TC3° Arbitrary Self Types
° Continue Experimentation with Pin Ergonomics
° Project goal - High-Level ML optimizations

Goals by team

The following table highlights the support level requested from each affected team. Each goal specifies the level of involvement needed:

  • Small: The team only needs to do routine activities (e.g., reviewing a few small PRs).
  • Medium: Dedicated support from one team member, but the rest of the team doesn’t need to be heavily involved.
  • Large: Deeper review and involvement from the entire team (e.g., design meetings, complex RFCs).

“Small” asks require someone on the team to “second” the goal. “Medium” and “Large” asks require a dedicated champion from the team.

bootstrap team

GoalLevelChampionNotes
Stabilize MemorySanitizer and ThreadSanitizer SupportMediumDedicated reviewer

cargo team

*1: Reviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and many implementation patches (from here)

*2: Discussion on cargo integration options (from here)

*3: Design and code reviews (from here)

*4: Alignment on direction, possible integration help and review. (from here)

*5: Discussion and moral support (from here)

*6: PR reviews for Cargo changes; design discussions (from here)

*7: In case we end up pursuing JITing as a way to improve performance that will eventually need native integration with cargo run. For now we’re just prototyping, and so the occasional vibe check should be sufficient (from here)

clippy team

*1: Initial onboarding support for SCRC contributors; guidance on lint design (from here)

compiler team

GoalLevelChampionNotes
Stabilize public/private dependenciesMedium*1
Crate Slicing for Faster Fresh BuildsMedium*2
Async statemachine optimisationMedium*3
BorrowSanitizerMediumRalf Jung*4
Open EnumsMediumImplementation reviews
reflection and comptimeMediumOliver SchererStandard reviews
Stabilize Rust for Linux compiler featuresMediumWesley WiserReviews, RfL meetings
Field ProjectionsMediumDing Xiang Fei*5
Improve rustc_codegen_cranelift performanceMedium*6
Stabilize MemorySanitizer and ThreadSanitizer SupportMediumReviews, stabilization
Async Future Memory OptimisationMedium*7
Project goal - High-Level ML optimizationsMediumOliver Scherer*8
Implement and Maintain MC/DC Coverage SupportMedium*9
Evolving the standard library API across editionsMedium*10
Incremental Systems RethoughtMediumChampion: Jack Huey
Continue Experimentation with Pin ErgonomicsMediumOliver SchererReviews
Box notation for dyn async traitMediumImplementation review
Redesigning super let: Flexible Temporary Lifetime ExtensionSmall*11
MIR move eliminationSmallRFC decision
Const GenericsSmallCode reviews
Stabilize the Try traitSmall
C++/Rust Interop Problem Space MappingSmallOliver SchererReviews
Ergonomic ref-counting: Share trait and move expressionsSmallReviews
Stabilize Const TraitsSmallCode reviews
Implement Open Rust Namespace SupportSmall*12
Stabilize cargo-scriptSmall*13
Control over Drop semanticsSmallImplementation reviews
build-stdSmall*14
Reborrow traitsSmall*15
Sized Hierarchy and Scalable VectorsSmallDavid Wood*16
Wasm ComponentsSmall*17
Nightly support for function overloading in FFI bindingsSmall*18
Stabilize concrete type specializationSmall
Stabilizing f16Small

*1: An implementer, design discussions, PR review (from here)

*2: Consultation on approach feasibility and soundness concerns (from here)

*3: Most will be review work, but pushing optimisations to the max will possibly touch on some controversial points that need discussion (from here)

*4: Champion: Ralf Jung. Design discussions, PR review, and upstream integration. (from here)

*5: Reviews of big changes needed; also looking for implementation help (from here)

*6: Depending on what ways we end up pursuing, we might need no rustc side changes at all or medium sized changes. (from here)

*7: Is this Small or Medium? Does it need a champion? (from here)

*8: My changes should be contained to few places in the compiler. Potentially one frontend macro/intrinsic, and otherwise almost exclusively in the backend. (from here)

*9: Review of implementation PRs; guidance on architecture to avoid previous maintenance issues; input on Stable MIR extension feasibility (from here)

*10: Design discussions and implementation review. (from here)

*11: May escalate to medium depending on how the feature design turns out. (from here)

*12: Design discussions, PR review (from here)

*13: Reviewing any further compiler changes (from here)

*14: Reviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches (from here)

*15: Standard reviews for trait implementation PRs (from here)

*16: Standard reviews for stabilization and SVE work (from here)

*17: New targets will need review and approval (from here)

*18: Most complexity is in the type system (from here)

crate-maintainers team

GoalLevelChampionNotes
libc 1.0 release readinessSmall

crates-io team

GoalLevelChampionNotes
build-stdSmall*1

*1: Reviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches (from here)

edition team

*1: Review the feasibility of this proposal as well as the specific API changes. (from here)

fls team

GoalLevelChampionNotes
Stabilize FLS Release CadenceLarge*1

*1: Core work of authoring and releasing FLS versions on schedule (from here)

infra team

*1: I will work with Jakub Beránek to add more bootstrap options to build and configure MLIR (an LLVM subproject) (from here)

*2: CI support for MC/DC testing (from here)

lang team

GoalLevelChampionNotes
Redesigning super let: Flexible Temporary Lifetime ExtensionLarge*1
Immobile types and guaranteed destructorsLarge*2
Const GenericsLargeNiko Matsakis*3
reflection and comptimeLargeScott McMurray*4
Field ProjectionsLargeTyler Mandry*5
Stabilize Const TraitsLarge*6
In-place initializationMedium*7
Prepare TAIT + RTN for stabilizationMediumNiko Matsakis*8
Open EnumsMedium*9
Stabilize the next-generation trait solverMediumNiko Matsakis*10
Arbitrary Self TypesMediumTyler Mandry*11
used_with_argMedium*12
Stabilize the Try traitMedium
Ergonomic ref-counting: Share trait and move expressionsMediumNiko Matsakis
cfg(no_fp_fmt_parse)Medium*13
Control over Drop semanticsMedium*14
Reborrow traitsMediumTyler Mandry*15
Sized Hierarchy and Scalable VectorsMediumNiko Matsakis*16
Case study for experimental language specification, with integration into project teams and processesMediumJosh Triplett
asm_const_ptrMedium*17
Nightly support for function overloading in FFI bindingsMedium*18
Stabilize concrete type specializationMedium*19
Project goal - High-Level ML optimizationsMediumTC*20
Implement Supertrait auto implMedium*21
Continue Experimentation with Pin ErgonomicsMediumTCDesign meeting?
Box notation for dyn async traitMediumNiko MatsakisRFC decision
MIR move eliminationSmallAmanieu d’AntrasRFC decision
Crate Slicing for Faster Fresh BuildsSmall*22
BorrowSanitizerSmallTyler Mandry*23
C++/Rust Interop Problem Space MappingSmallTyler MandryReviews
Stabilize cargo-scriptSmall*24
Wasm ComponentsSmall*25
Normative Documentation for Sound unsafe RustSmall*26
Evolving the standard library API across editionsSmall*27
Stabilizing f16Small*28

*1: Would need a design meeting and RFC review. (from here)

*2: Design session needed to work through design (from here)

*3: Stabilization decisions, directional alignment (from here)

*4: Design meeting, experiment (from here)

*5: Aiming for two design meetings; large language feature (from here)

*6: Semantics, syntax, and stabilization decisions (from here)

*7: Review and accept a design space RFC (from here)

*8: RFC review, design discussions (from here)

*9: Champion and (ideally) a lang meeting (from here)

*10: Stabilization decision for user facing changes (from here)

*11: Reviews, Lang/RfL meetings (from here)

*12: Reviews, Lang/RfL meetings (from here)

*13: Reviews, Lang/RfL meetings (from here)

*14: Vibe check and RFC review (from here)

*15: Continued experiment support, design feedback (from here)

*16: RFC decision for [rfcs#3838], stabilization sign-off (from here)

*17: Reviews, Lang/RfL meetings (from here)

*18: Design meeting Experiment (from here)

*19: Resolve design concerns like #[override] and review stabilization (from here)

*20: Discussions to understand which parts of gpu programming and std::offload are problematic wrt. stabilization, from a lang perspective. Non-blocking, since we are not rushing stabilization. (from here)

*21: Team aligned already on the shape of the feature (from here)

*22: Discussion on review of research methodology and findings (from here)

*23: Champion: Tyler Mandry. General support and guidance. (from here)

*24: Stabilization discussions (from here)

*25: Experimentation with native Wasm features will need approval. May become “medium” if we are somehow really successful. (from here)

*26: Feedback on language semantics questions as needed (from here)

*27: Review of the feature and lang implications. (from here)

*28: occasionally being fast-tracked would be nice (from here)

lang-docs team

*1: Reviews, Lang/RfL meetings (from here)

*2: Reviews, Lang/RfL meetings (from here)

*3: Reviews, Lang/RfL meetings (from here)

*4: Reviews, Lang/RfL meetings (from here)

*5: Standard PR reviews for Rust Reference (from here)

*6: General discussion of shape of integration of a-mir-formality into reference (from here)

leadership-council team

GoalLevelChampionNotes
Establish a User Research TeamSmall*1

*1: Org decision to establish team, ongoing coordination (from here)

libs team

*1: Since super let affects the standard library, the library team should be on-board with any new directions it takes. Additionally, library team review may be required for changes to pin!’s implementation. (from here)

*2: Small reviews of library PRs (implementing FP for core & std types) (from here)

*3: Reviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches (from here)

*4: Threading support will need review (from here)

libs-api team

*1: Determine what API changes should be made across editions. (from here)

*2: Review RFC; review and approve stdarch SVE APIs (from here)

*3: Reviews of RFC and API surface area (from here)

*4: Would like to know if they have use cases for overloading in standard Rust, or if there are certain approaches they would like better. May be involved if experiment involves library surface area (e.g. Fn traits) (from here)

*5: PR reviews for core/std public documentation; feedback on approach. (from here)

opsem team

*1: Review unsafe patterns, establish safety contracts, guide documentation (from here)

*2: Problem statement review (from here)

*3: Doc changes if necessary (from here)

*4: Small reviews of RFC and/or compiler PRs (from here)

project-exploit-mitigations team

GoalLevelChampionNotes
Stabilize MemorySanitizer and ThreadSanitizer SupportMediumDedicated reviewer

project-stable-mir team

GoalLevelChampionNotes
Implement and Maintain MC/DC Coverage SupportMedium*1

*1: Consultation on extending Stable MIR with syntactic structure; review of any proposed API additions (if this approach is chosen) (from here)

rust-analyzer team

GoalLevelChampionNotes
Crate Slicing for Faster Fresh BuildsSmall*1

*1: Discussion on rust-analyzer integration potential (from here)

rustdoc team

*1: Figure out how such API changes should be presented in the API docs. (from here)

*2: Discussion and moral support (from here)

*3: Design decision and PR review (from here)

spec team

*1: Alignment on release cadence goal (from here)

*2: General discussion on how this may align with other efforts to specify Rust. (from here)

*3: General discussion of integration of a-mir-formality with reference (from here)

testing-devex team

GoalLevelChampionNotes
Finish the libtest json output experimentSmall*1

*1: Design discussions and review (from here)

types team

*1: Involved in implementation + review (from here)

*2: a-mir-formality modeling, design alignment (from here)

*3: Stabilization decision, ongoing review work (from here)

*4: Review of type-system stabilization/implementation (from here)

*5: Implementation design and sign-off (from here)

*6: Review future extensions for plausibility, soundness, and stabilization (from here)

*7: Design review, stabilization decision, reviews from Jack Huey and Matthew Jasper (from here)

*8: implementation/reviews/deciding on a design (from here)

*9: Stabilization report review, TAIT interactions (from here)

*10: Collaborating on a-mir-formality on the borrow checker integration; small reviews of RFC and/or compiler PRs (from here)

*11: Type System implementation and stabilization sign-off (from here)

*12: Evaluate potential changes to (experimental) reference in routine team decisions (from here)

*13: Want to ensure that the feature “fits within the lines” of a simple desugaring, still some possible type-system impl work (from here)

*14: Discussion and moral support (from here)

*15: Consultation on trait coherence requirements for slicing (from here)

*16: General discussion on any additional type-system changes (from here)

*17: Standard reviews for trait implementation PRs (from here)

*18: No dedicated reviewer needed/given, but tracking issue should note the needed for dedicated types review prior to stabilization (from here)

*19: Members may have comments/thoughts on direction and priorities; Review work for a-mir-formality (from here)

*20: Review of any changes to HIR ty lowering or method resolution (from here)

*21: May have changes to dyn-compatibility rules (from here)

wg-mir-opt team

GoalLevelChampionNotes
MIR move eliminationMediumDesign meeting

Beyond the &

Metadata
Short titleBeyond the &
What and whySmart pointers (Arc, Pin, FFI wrappers) get the same ergonomics as & and &mut — reborrowing, field access, in-place init
Point of contactTyler Mandry
Application areaNetwork services
Application areaSystems & embedded
Application areaCross-language interop

Summary

Smart pointers that feel as natural as & and &mut.

Motivation

The status quo

One of Rust’s core value propositions is that it’s a “library-based language”—libraries can build abstractions that feel built-in to the language even when they’re not. Smart pointer types like Rc and Arc are prime examples, implemented purely in the standard library yet feeling like native language features.

However, Rust’s built-in reference types (&T and &mut T) have special capabilities that user-defined smart pointers cannot replicate:

  • Reborrowing: When you pass a &mut T to a function, Rust automatically reborrows it so you can use it again afterward. But Option<&mut T> or custom smart pointers require awkward .as_deref_mut() or .reborrow() calls—and values derived from these reborrows cannot be returned from the function.
  • Field projection: Writing &x.field gives you &Field—the borrow checker tracks that you’re only borrowing part of the struct. Custom pointer types like NonNull<T> or ArcRef<T> have no equivalent; you can’t write arc_ref.field and get back an ArcRef<Field>.
  • In-place initialization: Creating a value directly at its final memory location—crucial for unmovable types and large structs—requires complex macro-based solutions because the language has no native support.

This creates a “second-class citizen” problem: custom pointer types can never provide the same ergonomic experience as built-in references, limiting Rust’s promise of zero-cost abstractions.

What we are shooting for

We want user-defined smart pointers to be truly indistinguishable from built-in references in terms of syntax and ergonomics. When you use an ArcRef<T> or Pin<&mut T>, it should feel just like using &T or &mut T:

  • Automatic reborrowing for any pointer type that opts in, with derived values returnable from functions
  • Field projection that lets you write ptr.field and get back a pointer to the field, with full borrow-checker integration
  • Language-level in-place initialization that’s more ergonomic than what macros can achieve

Key use cases

  • Rust for Linux: The kernel uses custom smart pointer types (Arc, ArcBorrow, Ref) to express ownership and borrowing patterns that don’t map directly to Rust’s built-in references. Field projection and reborrowing would make these types dramatically more ergonomic.
  • Cross-language interop: FFI wrappers like PyRef<T> (Python) or CppMutRef<T> (C++) represent references into foreign runtimes. These should feel as natural as native Rust references when accessing fields or passing to functions.
  • MaybeUninit initialization: Safely initializing structs field-by-field through &mut MaybeUninit<T> is currently verbose and error-prone. Field projection would let you write uninit.field and get &mut MaybeUninit<Field>.
  • Interior mutability: Types like cell::Ref<T> and RefMut<T> wrap borrowed data but lose the ability to project into fields. You can’t write ref_mut.field to get a RefMut<Field>.
  • Volatile and atomic access: Low-level code working with memory-mapped I/O needs pointer types like VolatilePtr<T> that preserve access semantics through field projection.

Design axioms

  • Generalize and extend the basic operations of Rust. Build on existing models of how the language works while relaxing restrictions. Fix expressiveness gaps in the base paradigm, rather than inventing new paradigms altogether.
  • Enable abstractions that are powerful, transparent, and ergonomic to use. These abstractions should allow code to be clearer in its purpose and behavior than it is without them.
  • Ship iteratively. Ship building blocks that unblock existing use cases and new experimentation. Don’t block on full generality and ease of use when that can be done in the future.
  • Design holistically. Look for ways to accommodate further generality in our designs, even if we don’t expose that generality at first.

2026 goals

Frequently asked questions

How do these goals relate to each other?

The goals are complementary but largely independent:

  • Reborrow traits address the “automatic reborrowing” problem, providing the general mechanism that types can opt into.
  • Field projections provides the broader “place operations” framework that encompasses projection, borrowing, and reading/writing through custom pointer types.
  • In-place initialization tackles a related but distinct problem: creating values that can’t be moved.

What types will benefit from this work?

A non-exhaustive list: NonNull<T>, *const T and *mut T, &mut MaybeUninit<T>, cell::Ref and RefMut, ArcRef<T>, FFI pointer wrappers like PyRef<T> or CppMutRef<T>, volatile pointers, and many more.

Is this the same as the “custom receivers” feature?

Related but distinct. Custom receivers (RFC 3519) allow methods with self: MyPtr<Self>. The “Beyond the &” work goes further: making those custom pointer types feel like native references through automatic reborrowing, field access, and borrow checker integration.

Building blocks

Metadata
Short titleBuilding blocks
What and whyStable, machine-readable Cargo plumbing commands; rebuild std on stable
Point of contactEd Page
Application areaEnterprise integration

Summary

Expose Cargo and Rust’s internal infrastructure as stable, composable building blocks for tooling authors and power users.

Motivation

The status quo

Rust’s tooling ecosystem includes hundreds of third-party tools built on top of Cargo, rustc, and the standard library. Tools like cargo-nextest, rust-analyzer, and cargo-deny extend what ships with Rust. But tool authors face significant friction:

  • Cargo is designed for humans, not scripts. When tools need dependency information, feature resolution, or build graph data, they must parse human-readable output or use cargo metadata (which has known limitations). There’s no stable programmatic interface.

  • libtest’s output is unstable. The standard test harness provides no stable machine-readable format. When --format json was accidentally stabilized and then reverted to nightly-only, it revealed how many tools depended on it.

  • Building std requires nightly. The -Zbuild-std flag lets users rebuild the standard library with custom settings, but it remains unstable. Embedded developers and those on tier-3 targets must use nightly.

The result: tool authors spend effort reverse-engineering Cargo’s behavior and building workarounds for missing capabilities.

What we are shooting for

By the end of 2026:

  • Cargo plumbing commands are prototyped and validated. External experimentation with machine-readable commands that expose Cargo’s operations, with a path toward eventual inclusion in Cargo. Just as Git distinguishes “porcelain” (user-facing) from “plumbing” (scriptable), this work explores building blocks for programmatic access.

  • libtest JSON output experiment is complete. The experiment concludes with a proposal for stable JSON output, enabling better test runners and IDE integration.

  • build-std implementation is underway. RFCs are accepted and implementation has begun, moving toward eventual stabilization of rebuilding the standard library with custom configurations.

  • Interactive dependency exploration is prototyped. External tooling demonstrates interactive navigation of dependency graphs, with preparation for eventual Cargo integration.

Key use cases

  • Custom test runners: Tools like cargo-nextest rely on stable JSON output for parallel execution and better failure reporting.

  • Build system integration: Organizations using Buck, Bazel, or custom systems need reliable programmatic access to Cargo’s dependency and build information.

  • IDE tooling: rust-analyzer needs fast, reliable project structure and dependency information.

  • Embedded development: Developers working on embedded systems or kernel development need to rebuild std with specific configurations on stable Rust.

Design axioms

  • Separate porcelain from plumbing. User-facing commands remain focused on usability. Programmatic access comes through dedicated plumbing commands with stable schemas.

  • Stable means stable. When we stabilize an interface, tool authors can depend on it without checking Rust versions.

  • Expose the truth. Plumbing commands expose what Cargo actually knows, not a simplified approximation that might miss edge cases.

  • Prototype externally, integrate when ready. New capabilities start as external tools where iteration is fast, then integrate into Cargo once designs stabilize.

2026 goals

Frequently asked questions

How do these goals relate to each other?

The goals share a vision but are largely independent:

  • build-std focuses on completing RFCs and beginning implementation for the compiler and standard library.
  • cargo-plumbing prototypes programmatic access to Cargo’s operations as an external tool.
  • libtest-json completes the experiment toward stable test harness output.
  • interactive-cargo-tree prototypes improved dependency exploration UX externally.

Each delivers value independently, though cargo-plumbing may eventually provide APIs that other tools use.

Who benefits from this work?

Primarily tooling authors, large organizations integrating Rust into build systems, embedded developers, IDE developers, and power users. Indirectly, all Rust users benefit because better infrastructure enables better tools.

Why not expose Cargo as a library?

Cargo-as-a-library has significant challenges: API stability commitments, versioning complexity, and architectural constraints. Plumbing commands provide a practical near-term solution with clear boundaries and schema versioning.

Constify all the things

Metadata
Short titleConstify all the things
What and whyConst generics accept structs and enums; compile-time reflection means serialize(&my_struct) works without derives
Point of contactOliver Scherer
Application areaSystems & embedded

Summary

Richer const generics and compile-time reflection that works without derives.

Motivation

The status quo

Rust’s compile-time capabilities are powerful but incomplete. const fn enables compile-time evaluation, but users repeatedly hit limitations when trying to use it for real work:

  • Const generics only support primitive types. You can write Array<T, 4> but not Array<T, Dimensions { width: 4, height: 4 }>. Using associated constants as const parameters (Buffer<T, T::SIZE>) also doesn’t work. These limitations force workarounds or abandoning const generics entirely.

  • Reflection requires derives on every type. Libraries for serialization, logging, or reflection need users to add derives for each type they want to work with. This creates ecosystem friction: crate authors must choose which libraries to support, users must add boilerplate for each library, and new libraries can’t reach existing types.

  • Proc macros are the only option for code generation. When you need compile-time code generation, proc macros work but are difficult to debug, can’t access type information, and add compile-time overhead.

Extending const generics and adding compile-time reflection would address all three limitations, letting users write normal Rust code that inspects types and runs at compile time.

What we are shooting for

Stable by end of 2026:

  • Const generics accept structs and enums. Write Array<T, Dimensions { width: 4, height: 4 }> and have it work. Use associated constants like Buffer<T, T::SIZE>.

RFC by end of 2026:

  • Reflection without derives. An experimental comptime reflection system will be available on nightly and validated against libraries like bevy_reflect and facet. We aim to have an RFC merged defining the stabilization path.

Key use cases

  • Zero-boilerplate serialization: serialize(&my_struct) works for any struct without derives. The library inspects field types at compile time.

  • Game engine reflection: Engines like Bevy can inspect any type’s structure directly, making #[derive(Component)] optional.

  • Dimension-checked numerics: Libraries encode physical dimensions in const generic structs, providing compile-time verification of unit calculations.

  • Protocol buffer generation: Libraries work directly with Rust structs at compile time, without external code generators.

2026 goals

Frequently asked questions

How do these goals relate to each other?

  • Const generics extends what values can be used as compile-time parameters—foundational for many advanced patterns.

  • Reflection and comptime provides the ability to inspect types at compile time, enabling libraries that work without derives.

Together they transform what’s possible at compile time: const generics let you parameterize by complex values, reflection lets you adapt to any type’s structure.

How does reflection differ from proc macros?

Proc macros operate on syntax (tokens) before type checking. Reflection operates on types during const evaluation. Reflection can see actual type information (field types, sizes, layouts), is debuggable with standard tools, and doesn’t require proc-macro compilation overhead.

Will reflection make derives obsolete?

Not obsolete, but often optional. Derives generate specialized code and can be more efficient. Reflection offers less boilerplate with potentially some runtime cost. Many libraries will likely offer both modes.

Just add async

Metadata
Short titleJust add async
What and whyPatterns that work in sync Rust should work in async Rust — traits, closures, drop, scoped tasks
Point of contactNiko Matsakis
Application areaNetwork services

Summary

Writing async Rust should be a natural extension of sync Rust: take your sync code, sprinkle some async and await keywords around in logical places, follow the compiler’s guidance, and wind up with working code.

Motivation

The status quo

Async Rust is widely used

The promise of tight tail latency, low memory usage, and high-level reliable code has made Rust, and async Rust in particular, a popular choice for network services. Rust is now widely used at all levels, from superscalars like Amazon and Microsoft, to simple CRUD apps built on FAAS platforms like Lambda or Azure Functions, to low-level networking on embedded devices.

But Async Rust doesn’t support standard Rust patterns

Despite this success, async Rust is widely seen as qualitatively harder than sync Rust. Not just more complex, but a different kind of challenge:

“I feel like there’s a ramp in learning and then there’s a jump and then there’s async over here. And so the goal is to get enough excitement about Rust to where you can jump the chasm of sadness and land on the async Rust side.” (from the Rust Vision Doc interviews)

The problem isn’t async concepts themselves. Developers understand concurrency (well, mostly). The problem is that patterns which work in sync Rust don’t transfer to async:

  • Traits: async fn in traits is stable, but you can’t use &dyn Trait with async methods, and there’s no way to require that an impl returns a Send future.
  • Closures: Async closures are stable, but compiler bugs frequently report invalid Send errors, and the trait limitations above make them hard to use in practice.
  • Recursion: In sync Rust, recursion just works. In async Rust, it requires arcane signatures with explicit lifetimes, Box, dyn Future, and Pin.
  • Scoped patterns: Sync Rust has std::thread::scope for borrowing into spawned threads. Async spawn APIs require 'static, forcing Arc everywhere.
  • Drop: Destructors are sync-only. Resources that need async cleanup (database connections, network sessions) can’t clean up properly in Drop.

Each issue has workarounds. But the workarounds require knowledge that doesn’t transfer from sync Rust, and the compiler doesn’t guide you to them. The result: developers who would otherwise build a network service in Rust hit these walls and wonder if it’s worth the trouble.

The ecosystem is waiting too. Libraries like Tower remain on 0.x because they can’t express the APIs they need. Tower’s Service trait predates async fn in traits and uses complex workarounds. The maintainers want to ship a cleaner design, but they’re blocked on language features. Particularly the ability to define one trait that works with both Send and non-Send futures. So Tower waits, and the middleware ecosystem built on it stays in flux.

What we are shooting for

The goal is “Just add async”: patterns that work in sync Rust should work in async Rust without requiring workarounds, restructuring, or arcane incantations. When async does require something extra (like explicit boxing for dyn dispatch), the compiler guides you with clear, actionable errors. Not walls of opaque type errors.

There should be straightforward equivalents for all the “rudiments of Rust”:

Key use cases

  • Network service development: Backend services, API servers, data pipelines. The most common async use case. In this scenario, allocation is acceptable. Performance bounds vary by application but consistency is often more important than absolute level of performance.

  • Middleware and composable abstractions: Libraries like Tower can define Service traits that work across runtimes (work-stealing and thread-per-core) without complex workarounds.

Design axioms

  • Sync patterns should transfer. If a pattern works in sync Rust, it should work in async Rust. When async requires something extra, the compiler should guide you there.

  • Server-first, but not server-only. We focus on server and application use cases to ship complete workflows now. But designs should leave space for users with stricter requirements. Features that allocate today can be extended with custom allocators or in-place initialization later. We’re not closing doors, we’re opening the first one.

  • Unblock the ecosystem, enable experimentation. The goal isn’t just language features. It’s enabling libraries like Tower to ship stable APIs, and creating space for exploration of harder problems (in-place initialization, structured concurrency) without blocking on them. Ship end-to-end workflows that work today while leaving room for the designs to evolve.

2026 goals

Frequently asked questions

What am I agreeing to by accepting this theme?

Accepting this roadmap means agreeing that:

  1. These problems matter. The gaps between sync and async Rust are real and worth fixing.
  2. This direction is right. Closing these gaps so “Just add async” works is the right goal.
  3. Server-first is the right prioritization. We ship end-to-end workflows for server/application environments first, with designs that leave space for stricter requirements later.

It does not mean agreeing to specific syntax (like .box) or implementation details. Those will be decided in individual goal RFCs.

What about async iterators / streams?

Async iteration is part of this theme’s vision, but not a 2026 focus. The 2026 goals target the foundational work: getting async fn in traits and closures fully working. That’s enough scope for one year. Exploring streams fully will require those foundations plus guaranteed destructors (because streams interact with structured concurrency and cancellation). Once the 2026 work lands, streams become much more tractable.

How do the goals in this theme relate to each other?

The four 2026 goals are largely independent:

  • RTN enables generic async code and is already RFC’d, waiting on trait solver work
  • AFIDT / .box notation enables dyn dispatch for async traits
  • Ergonomic ref-counting addresses closure capture pain that’s amplified by async’s 'static spawn requirements
  • Immobile types and guaranteed destructors enables scoped spawn and async drop by letting types opt out of being moved or forgotten

RTN and AFIDT share a dependency on the next-generation trait solver, which is being worked on separately.

Rust for Linux

Metadata
Short titleRust for Linux
What and whyBuild the Linux kernel with only stable language features.
Point of contactTomas Sedovic
Application areaSystems & embedded

Summary

Rust is now an integral part of the Linux kernel. There are mainline drivers built in it, tooling and it’s even directly in the kernel itself.

The Rust for Linux project is leading the development and the Rust Project is helping to facilitate some of the coordination.

While the project is built on a stable version of the Rust compiler, it relies on language features that are unstable (via the #![feature(...)] declarations). Ultimately, we want to stabilize all the features Rust for Linux relies on and support any platform that Linux itself supports.

Motivation

The status quo

The Rust for Linux page has a great overview of what’s supported and being worked on at the moment.

The project has to use the feature-gated functionality and it’s currently limited to platforms that LLVM supports.

The Rust Project has a regular meeting with the Rust for Linux folks every two weeks and that is where we synchronise on status and discuss any potential road blocks and issues or topics that came out.

We have representatives from the Language and Compiler teams present.

We have also been tracking the coordination through Project goals and this is a continuation of that effort.

What we are shooting for

Key use cases

  • Reduce the risk of critical errors: By compartmentalising the unsafe parts of the code base and having a clear boundary, we can build code that will have fewer bugs. We can rewrite notoriously tricky sections and provide better primitives.

  • Improve code quality across the kernel: In addition to the direct benefits of the Rust code, the Kernel is seeing improvements in the C side as well. We are seeing improvements of existing APIs in terms of const-ness, clarity and safety. Even people working solely with C have started pushing for better API documentation. Having Rust with the constantly maintained high bar that the Rust for Linux folks started results in a better codebase overall.

  • Bring in new contributors: It is a frequent theme within the Rust community that people who would never felt confident writing C dive into low-level topics and able to learn, experiment and ship code that is safe to be integrated into larger systems.

Design axioms

Don’t let perfect be the enemy of good™: The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of the functionality that meets the kernel developers’ needs while leaving other aspects unstable.

2026 Goals

compiler_builtins TODO(tomassedovic) the previous issue also lists compiler builtins. What are those?

Frequently asked questions

TODO

  • when is this done? (A: when the work here is all stable?)
  • how do the goals relate to each other (note the interdependencies)

Safety-Critical Rust

Metadata
Short titleSafety-Critical Rust
What and whyMC/DC coverage, a specification that tracks stable releases, and unsafe documentation — the evidence safety assessors need
Point of contactPete LeVasseur
Application areaSafety-critical & regulated

Summary

Make Rust viable for certified safety-critical systems by delivering coverage, specification, linting, and unsafe documentation foundations.

Motivation

The status quo

Engineers building software under functional safety standards need auditable evidence and predictable tooling. The major standards families include:

DomainStandards
AutomotiveISO 26262
AerospaceDO-178C, DO-333 (formal methods)
IndustrialIEC 61508, IEC 61511 (process), IEC 62061 (machinery)
Medical devicesIEC 62304
RailwayEN 50128, EN 50716
NuclearIEC 60880, IEC 61513
SpaceECSS-E-ST-40C, ECSS-Q-ST-80C
Agriculture/ForestryISO 25119

This includes OEMs, suppliers, integrators, and toolchain vendors. Safety cases must reference a specification for the language being used, and the toolchain must produce evidence that assessors accept.

What these teams need most:

  • Coverage tooling. MC/DC reports that assessors accept.
  • A specification that tracks stable releases. So safety cases can reference current language features via the FLS.
  • Continued progress on unsafe documentation. The Reference, Rustonomicon, and standard library docs have improved substantially over the years, but gaps remain for common patterns.
  • Stable foundations. Product lifetimes of 10-20 years require confidence in toolchain support and MSRV conventions.

Teams at SIL 2 and ASIL B are shipping Rust today. These deliverables reduce the workarounds they need and create a path to higher integrity levels.

What we are shooting for

We are building a capability ladder that unlocks Rust at increasing safety-integrity levels. The 2026 focus is the foundation, while keeping a clear path to higher tiers.

  • Foundation (ASIL A/B, SIL 1/2, DO-178C Level C). Stable branch/DC coverage baselines and predictable FLS releases, plus initial safety-critical linting to enforce Safety-Critical Rust Consortium coding standards.
  • Intermediate (ASIL C, SIL 3, DO-178C Level B). Normative unsafe pattern documentation and expanded lint coverage, with coordination for mixed-language interop and async runtime patterns.
  • Highest integrity (ASIL D, SIL 4, DO-178C Level A). MC/DC coverage in rustc and formal-methods coordination toward contracts, semantics documentation, and verified tooling.

Key use cases

  • Certification evidence: Generate coverage and spec references that auditors accept.
  • Qualified toolchains: Tool vendors can qualify rustc/Clippy with predictable releases and lint sets.
  • Mixed-language systems: Integrate Rust into C and C++ stacks with well-defined unsafe contracts.
  • Long-lived products: Maintain 10-20 year systems with stable MSRV and documentation baselines.

Design axioms

  • Evidence first. Prioritize deliverables that produce audit-ready evidence.
  • Use standard tooling. Improve rustc, Clippy, and core docs rather than forks.
  • Ship a ladder. Foundations first, with an explicit path to higher integrity levels.
  • Document safety contracts. unsafe patterns must have normative, citable guidance.

2026 goals

Frequently asked questions

How do these goals relate to each other?

They form a coherent evidence chain: FLS releases provide a citable specification, unsafe documentation defines safety contracts, Clippy lints enforce coding guidelines, and MC/DC coverage produces the evidence required at the highest integrity levels.

Does this certify Rust for safety-critical use?

No. Certification is per product and toolchain. These goals deliver the foundations that make qualification and certification feasible without bespoke tooling.

Why focus on foundations in 2026?

Teams at lower integrity levels are already shipping Rust and need practical improvements now. The foundation work also makes the higher-integrity goals achievable later.

Secure your supply chain

Metadata
Short titleSecure your supply chain
What and whyAccurate SBOMs, SemVer violation detection, explicit public/private dependencies
Point of contactTBD
Application areaEnterprise integration
Application areaSafety-critical & regulated

Summary

Know exactly what code ships in your binaries, catch breaking changes before they break your users, and keep your public API under control.

Motivation

The status quo

Every Rust project is built on a foundation of dependencies—the average crate pulls in dozens of transitive dependencies. This is powerful, but it means you’re responsible for code you didn’t write and may not fully understand.

Today, Rust developers face three challenges:

  • You don’t know what’s actually in your binary. cargo metadata reports all possible dependencies across all configurations, not what actually got compiled. When a vulnerability is announced, you need to know whether your production binary contains the affected code. Regulatory requirements are increasing: the US Executive Order 14028 requires Software Bills of Materials (SBOMs) for federal software, and the EU Cyber Resilience Act mandates SBOMs for products sold in Europe starting in 2027.

  • Breaking changes slip through. Research shows accidental SemVer violations occur in roughly 3% of releases. When you publish 1.2.3, you might not realize you’ve removed a method or tightened a trait bound. Users find out when cargo update breaks their build.

  • Dependencies leak into your public API. When you write pub fn process(data: some_crate::Data), that crate becomes part of your API contract. But Cargo doesn’t distinguish between dependencies you intentionally expose and ones that accidentally surface.

What we are shooting for

By the end of 2026:

  • Accurate SBOMs on stable Rust. cargo build produces machine-readable metadata about exactly which crate versions were compiled, in standard formats like CycloneDX or SPDX. When a CVE drops, you can query whether your binary contains the affected code.

  • Better tooling for catching SemVer violations. cargo-semver-checks continues toward integration with cargo publish, with progress on type-checking lints and cross-crate analysis. Today, you can run it in CI to catch common breaking changes before they reach users.

  • Public vs private dependencies are explicit. Marking a dependency as “private” means it can’t appear in your public interface. If you accidentally expose a private dependency’s type, you get a warning.

Key use cases

  • Regulatory compliance: Generate accurate SBOMs directly from the build process for US federal or EU market requirements.

  • Vulnerability response: Query SBOM data to determine which deployed binaries contain affected code.

  • Confident publishing: Run SemVer checks in CI, catching breaking changes in PRs before they merge.

  • Intentional API design: Declare which dependencies are implementation details, catching accidental leakage at compile time.

Design axioms

  • Accuracy over approximation. Dependency information must reflect what actually ships. An SBOM with phantom dependencies is worse than none.

  • Integrate into existing workflows. These capabilities should feel like natural extensions of commands developers already run.

  • Explicit over implicit. Whether a dependency is public or private should be a deliberate choice in Cargo.toml.

  • Incremental value. Each piece delivers value independently. SBOMs are useful without SemVer checks; SemVer checks are useful without pub/priv dependencies.

2026 goals

Frequently asked questions

How do these goals relate to each other?

The three goals address different aspects of supply chain security and can proceed in parallel:

  • Public/private dependencies helps control API surface by marking which dependencies should be exposed.

  • cargo-semver-checks verifies no accidental breaking changes before publishing.

  • Cargo SBOM generates accurate dependency manifests for compliance and security.

While independent, they’re complementary: knowing which dependencies are public helps SemVer checking focus on the right API surface.

Will cargo-semver-checks catch all breaking changes?

No tool can catch every possible breaking change, but it catches the most common categories (removed items, changed signatures, tightened bounds). The long-term goal is reliability sufficient for cargo publish to require compliance by default, with an escape hatch for intentional exceptions. In 2026, work focuses on resolving key blockers like type-checking lints and cross-crate analysis.

Why does Cargo need its own SBOM feature?

Third-party tools that generate SBOMs from cargo metadata see the full dependency graph across all configurations, not what actually gets compiled. Only Cargo knows which crates are selected after feature unification and target filtering.

Unblocking dormant traits

Metadata
Short titleUnblocking dormant traits
What and whyNew trait solver ships, unblocking extern types, scalable vectors, and painless trait refactoring
Point of contactTBD
Application areaNetwork services
Application areaSystems & embedded
Application areaCross-language interop

Summary

Long-blocked type system improvements finally ship, enabling extern types, scalable vectors, and painless trait refactoring.

Motivation

The status quo

Rust’s trait system is one of its most powerful features, but a number of long-desired improvements have been blocked on foundational work in the trait solver—the compiler component responsible for proving trait bounds, normalizing associated types, and more.

The current trait solver has accumulated technical debt and limitations over the years. This has led to:

  • Known soundness bugs that can’t be fixed without breaking the solver’s assumptions (tracking board)
  • Blocked language features like coinductive trait semantics, perfect derive, and better handling of higher-ranked types
  • An inability to express new concepts in the type system, such as a richer Sized hierarchy needed for extern types or scalable vectors

The next-generation trait solver has been in development since late 2022 and is already stable for coherence checking (since Rust 1.84). Stabilizing it everywhere will fix these soundness issues, unblock the stalled features, and provide a foundation for future type system work.

With that foundation in place, we can:

  • Extend the Sized hierarchy (RFC #3729, RFC #3838) to express types that are neither Sized nor ?Sized—like extern types (RFC #1861, no size at all) or scalable vectors (size known at runtime but not compile time)
  • Enable backward-compatible trait refactoring so library authors can split traits into smaller pieces without breaking downstream code

RFC #1861: https://rust-lang.github.io/rfcs/1861-extern-types.html RFC #3729: https://rust-lang.github.io/rfcs/3729-sized-hierarchy.html RFC #3838: https://github.com/rust-lang/rfcs/pull/3838

What we are shooting for

By the end of 2026:

  • New trait solver on stable. The next-generation trait solver replaces the old implementation everywhere, fixing known soundness bugs and providing a foundation for future type system work.
  • Extern types work. You can declare extern type Foo; and use it in FFI code without the compiler demanding a size it can’t know.
  • Trait evolution is field-testing on nightly. Library authors can experiment with splitting traits into smaller pieces without breaking downstream code, with the standard library running field trials.
  • Scalable vectors are experimenting on nightly. Developers targeting AArch64 SVE can use scalable vector types that adapt to hardware capabilities.

Key use cases

  • Soundness without surprises: Known trait solver bugs are fixed. Code that compiles continues to compile, except where it was relying on unsound behavior.

  • C library bindings: FFI wrappers for C libraries with opaque types (like FILE *) can express that these types exist but have no meaningful size in Rust.

  • Standard library evolution: The standard library team can begin field-testing trait refactoring—extracting common functionality into supertraits or reorganizing hierarchies—with the supertrait auto-impl feature, paving the way for ecosystem-wide adoption.

  • High-performance SIMD: Performance-critical code for AArch64 servers can experiment with scalable vector extensions that adapt to hardware vector width.

Design axioms

  • Fix the foundations first. Many desired features share common blockers in the trait solver. Rather than working around limitations repeatedly, we invest in fixing the underlying infrastructure once.

  • Unblock, then polish. Ship the core capabilities that unblock use cases, even if ergonomic improvements come later.

  • Preserve the ecosystem. Backward compatibility is paramount. Soundness fixes must not break working code except where that code relies on unsound behavior.

2026 goals

Frequently asked questions

How do these goals relate to each other?

The goals form a foundation-and-application pattern:

  • Next-generation trait solver is the foundational layer. The new solver fixes soundness issues and provides the infrastructure needed for more sophisticated type system features.

  • Sized hierarchy and scalable vectors extends the type system to express new categories of types, building on the sound foundation the new solver provides.

  • Supertrait item implementations enables backward-compatible trait evolution—largely independent of the solver work, but benefits from landing after the new solver is stable.

Will these changes break my code?

The goal is to avoid breakage. The next-generation trait solver has been extensively tested via crater runs, and known regressions are either fixed or were cases where the old solver was unsound. The Sized hierarchy is additive—existing code using Sized and ?Sized continues to work. Supertrait item implementations is specifically designed to make changes that would have been breaking become non-breaking.

Expanding a-mir-formality to work better as a Rust type system spec

Metadata
Point of contactJack Huey
StatusProposed
Tracking issuerust-lang/rust-project-goals#122
Zulip channel#types/formality
types championJack Huey
Teamslang-docs, spec, types
Task owners(none)

Summary

The goal here is to begin to move a-mir-formality into a position where it can be used as a formal specification of the Rust type system:

  • Identify type system areas lacking in a-mir-formality
  • Build a “roadmap” to add those lacking areas
  • Continuing to contribute to a-mir-formality and build towards completeness
  • Experiment with integration of a-mir-formality into an experimental reference

Motivation

The status quo

Most communication and definition of Rust’s type/trait system today takes place through informal argument and with reference to compiler internals. a-mir-formality offers a model of Rust at a much higher level, but it remains very incomplete compared to Rust.

Previously, there has been some progress in increasing contributions to a-mir-formality by others besides Niko Matsakis, but we still haven’t achieved a “fully living” project. That being said, steady progress has been and continues to be made, and we are at a point where it makes sense to try to outline a concrete plan for the future.

What we propose to do about it

The work here is primarily divided into two main goals:

  1. Document the status of a-mir-formality implementation, identify a plan towards “completion”, and work towards that.
  2. Experiment with integration of a-mir-formality into an “experimental reference” (led primarily as a separate goal).

For the former, it is expected this will intersect with other ongoing work (such as implementing borrow checking in a-mir-formality). It is also likely that this will be done through some combination of manual identification (such as through census of open issues) and more automatic identification (such as cross-testing the rustc test suite).

For the latter, it is not yet clear in what form the integration with the reference will occur. Possibilities may range from simple linking of behavior from the reference to the relevant rules in a-mir-formality, to more complex integration, such as embedding of a-mir-formality tests or rules within the reference itself. Notably, the goal is to allow the reference to remain a user-friendly text while providing a platform to share the more concrete formalism of the type system.

The types team has also discussed forming a subteam focused on a-mir-formality, which would likely own this work, rather than being owned primarily by individuals on the types team.

TaskOwner(s)Notes
Implementation documentationJack Huey
ReviewsNiko Matsakis
Implementation workJack Huey, Niko Matsakis, @tiff
Design and implementation of a-mir-formality integrationJack Huey

Team asks

TeamSupport levelNotes
typesSmallMembers may have comments/thoughts on direction and priorities; Review work for a-mir-formality
specSmallGeneral discussion of integration of a-mir-formality with reference
lang-docsSmallGeneral discussion of shape of integration of a-mir-formality into reference

Frequently asked questions

Does this cover XYZ work in a-mir-formality?

Generally, the work under the first subgoal can be thought of as the “meta” work that may be covered under other goals. The hope is that this goal should be mainly focused on the planning and organization around “finishing” the implementation of a-mir-formality to be a “complete” definition of the Rust type system, and that may include discussions about other ongoing work.

Is there an expectation that the integration of a-mir-formality into the reference must eventually be merged into the main reference?

Generally, no. The goal of the proposed work is not necessarily to find some single solution to integrate a-mir-formality into the reference, but rather to learn more about how this integration could happen, and moreso to inform us about how we can document the Rust type system in the reference in the best way possible to maintain preciseness with the constraint of user-friendly text.

Box notation for dyn async trait

Metadata
Point of contactNiko Matsakis
StatusProposed
Contingent onContributor
RoadmapJust add async
Tracking issue
Zulip channel#wg-async
lang championNiko Matsakis
Teamscompiler, lang, types
Task owners(none)

Summary

Introduce .box notation and use it to enable dyn dispatch for traits with async methods. The initial scope is foo.method().box where method() returns a dyn-compatible RPITIT. In the future .box could be used more generally but before expanding it we would like to see progress on the work towards in-place initialization.

Contingent on contributor: Niko Matsakis is able to devote 1h/wk to support an experienced contributor or a cohort of contributors in driving this design forward as a lang experiment. This is a challenging problem that will require modifying various parts of the compiler and would also benefit from modeling in a-mir-formality.

Motivation

The status quo

Async fn in traits (AFIT) has been stable since Rust 1.75, but traits with async methods are not dyn-compatible. If you write:

#![allow(unused)]
fn main() {
trait HttpClient {
    async fn fetch(&self, url: &str) -> Response;
}
}

You cannot use &dyn HttpClient. The compiler rejects it because async methods return opaque future types whose size isn’t known at compile time, and dyn dispatch requires the caller to allocate space for the return value without knowing the concrete type.

Today, developers work around this by:

  • Using static dispatch only: Generics everywhere, increasing compile times and binary size
  • Manual desugaring: Write -> Pin<Box<dyn Future<Output = Response> + Send + '_>> and lose the ergonomics of async fn
  • Proc macros: Use crates like async-trait or dynosaur that transform your code

The broader problem is complex

Making dyn Trait work with unsized return types is a deep problem that has been explored extensively. The caller must provide storage for the returned value, but doesn’t know its size. There are many options one might wish to use, with stack allocation and boxing being the most obvious. The in-place initialization goal is exploring the design space here for a fully general solution that allows the caller to have total control. But that design work requires time, and the goal for 2026 is only to settle on a specific design, not necessarily to implement it or even stabilize it! In the meantime, Rust’s support for async-fn-in-trait is only usable in narrow circumstances.

Boxing is the simplest approach and it’s what many users will want

The widespread use of the async-trait crate demonstrates that boxing is perfectly acceptable for many applications. async-trait transforms async fn into a fn that returns Pin<Box<dyn Future + Send>>, allocating on every call. Despite this cost, the crate has been downloaded millions of times because for most server and application code, the allocation overhead is negligible compared to the I/O being performed.

The problem with async-trait isn’t that it boxes. It’s that it modifies the trait definition, forcing all implementors to box on every call. This means library authors can’t use it for public traits where some users need static dispatch (no allocation) while others want dyn dispatch.

What we want is for the call site to decide whether to box. A library like Tower could define its Service trait using native async fn, implementors would write normal async code without any boxing, and generic code using T: Service would have zero allocation overhead. But users who need dyn Service could opt into boxing at the call site. Once the in-place initialization work proceeds, that same trait would support other allocation strategies too. But boxing unblocks the ecosystem now.

What we propose to do about it

The .box operator. We propose to build out an end-to-end solution based on the .box operator. The biggest impact on users is that they could invoke async fn via dyn trait, but they have to use .box at the call site, like so:

#![allow(unused)]
fn main() {
async fn fetch_data(client: &dyn HttpClient) -> Response {
    client.fetch(url).box.await
    //                ---
    //
    // Signals that the resulting future will be boxed.
}
}

For the purposes of this goal, .box would only be usable when calling a trait method where the trait definition returns -> impl SomeTrait. We expect it would be generalized in the future to serve as a replacement for Box::new but the details of that will depend on the outcome from the in-place initialization exploration currently taking place.

Method-scope dyn compatibility. An implication of the .box design is that we need to make the definition of dyn-compatibility more fine-grained. Today, a trait is only “dyn compatible” if all of its methods are dyn-safe – that is, can be used in the same way whether through dyn or not. But async fn (and -> impl Trait methods in general) are not dyn-safe in this way: they can only be used if the user specifies a memory allocation strategy (with .box being the first example).

For more details and a broader look, see the box, box, box blog post.

Work items over the next year

TaskOwner(s)Notes
RFC for method-scope dyn compatNiko Matsakis
RFC for .box notationNiko MatsakisScoped to RPITIT/async returns initially
ImplementationHelp WantedNightly experiment
DocumentationHelp Wanted

Team asks

TeamSupport levelNotes
langMediumRFC decision
compilerMediumImplementation review
typesSmallMay have changes to dyn-compatibility rules

Frequently asked questions

Why .box instead of implicit boxing?

Explicit is better here. Boxing has runtime cost (allocation), and Rust’s philosophy is to make costs visible. .box lets you see exactly where allocations happen, which matters for performance-sensitive async code.

What about the other allocation strategies?

The status quo section describes several options: boxing, in-place initialization, inline storage, and custom allocators. This goal focuses on boxing because it’s the option we’re most confident about. It’s proven by async-trait, works everywhere with an allocator, and is simplest to implement.

Other strategies can be added later with different syntax. For example, inline storage might use .inline::<N> or similar. The key insight is that we don’t need to solve everything at once.

Could .box generalize beyond async?

Yes. The notation could potentially work anywhere you would use Box::new, but we don’t want to figure out the full desugaring yet. This goal scopes .box to method call position (foo.bar().box) for RPITIT methods. That includes async fn, explicit -> impl Future, but also -> impl Iterator and similar patterns.

Why not just use the dynosaur crate?

The dynosaur crate is a good workaround, but native language support would:

  • Avoid proc macro complexity and compile-time overhead
  • Provide better error messages
  • Enable optimizations the compiler can’t do through macro-generated code
  • Make the pattern discoverable and standard

How does this relate to the “Just add async” roadmap?

Dynamic dispatch is a core Rust pattern. In sync code, you can freely use &dyn Trait for most traits. The “Just add async” theme is about making async code work like sync code. With .box, you can use &dyn Trait with async methods. You just need to explicitly box the future, which is a reasonable cost for the flexibility of dynamic dispatch.

Arbitrary Self Types

Metadata
Point of contactDing Xiang Fei
StatusProposed
RoadmapRust for Linux
RoadmapBeyond the &
Tracking issue
Other tracking issuesrust-lang/rust#44874, rust-lang/rust#146095, rust-lang/rust#123430
Zulip channelN/A
lang championTyler Mandry
types championJack Huey
lang-docs championTC
Teamslang, lang-docs, libs, libs-api, types
Task owners(none)

Summary

It is possible to create custom smart pointers by implementing the Deref trait. However, the standard library types are able to do things user-defined pointers can’t. For example, acting as a method receiver (self etc.) or turning a concrete type implementing a custom Trait to a dyn Trait.

These limitations are of particular importance to low-level systems (e.g. Rust for Linux) and cross-language interoperability (e.g. when designing a reference to C++ objects).

We want to stabilize these features to reduce the gap between smart pointers in the standard library and user-defined ones.

These features are all interconnected and depend on one another so we’re proposing a single goal that makes user-defined smart pointers on par with the ones in the standard library.

Motivation

The status quo

There are two main limitations custom pointers face today.

First, being able to use one as a method receiver. You can implement a method on a type with the first parameter being Box<self>, Rc<self>, or Arc<self> etc. and then call the method directly on the pointer.

The arbitrary_self_types language feature allows users to do the same for their pointers:

#![allow(unused)]
fn main() {
pub struct SmartPointer<T> { ... }

impl<T> Receiver for SmartPointer<T> {
    type Target = T;
}

struct Person { ... };

// It is now possible to use `SmartPointer`s as method receivers.
// Previously, only blessed types like `Box` could act like method receivers.
impl Person {
    pub fn biometrics(self: &SmartPointer<Self>) -> &Biometrics {
        ...
    }
}

let person: SmartPointer<Person> = get_data();
// Method calls can now also dispatch `SmartPointer<Person>` to the intended methods.
let _: &Biometrics = person.biometrics();
}

Arbitrary self types do this by implementing the Receiver trait. Right now, we have a blanket Receiver implementation for any type that implements Deref.

We want to remove that coupling and have Receiver be a standalone trait. In particular, we would like to keep the door open for the ability to have Receiver::Target and Deref::Target different (when both are implemented) in the future.

The second limitation is around coercion to a dyn Trait. We want to be able to define custom smart pointers that work with trait objects.

It would allow us to do this:

#[derive(CoercePointee)]
#[repr(transparent)]
pub struct SmartPointer<T> { ... }

impl<T: ?Sized> Deref for SmartPointer<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &self.0
    }
}

trait MyTrait {}

impl MyTrait for i32 {}

fn main() {
    let ptr: MySmartPointer<i32> = MySmartPointer(Box::new(42));

    // This coercion would be an error without the derive.
    let ptr: MySmartPointer<dyn MyTrait> = ptr;
}

What we propose to do about it

For arbitrary_self_types:

  • Implement the decoupling of the two traits.
  • Decide on the fate of the arbitrary_self_types_pointers feature, whose design would run against common language principles and may hinder future library and language feature evolution.
  • Update the Rust language reference to codify the method resolution rules while considering possible language extensions from “Beyond &.”
  • Propose a second stabilisation attempt to conclude the project goal work.

For Deref/Receiver chain:

While we have settled with splitting the coupling of the two traits so that they will affect method resolution independently, we would also like to open a small language experiment by introducing a feature gate arbitrary_self_types_split_chain, through which the Rust language users can experiment with diverging target types in Receiver and Deref. Through this experiment, we will collect the data on the utility of having this feature in the language and potential use cases of this construction.

  • Land the implementation for decoupling the Deref and Receiver traits rust#146095 at the start of the language experiment.
  • Engage the community through various channels and users that have interest in or make use of the Receiver language feature to collect opinions, when they find a need to enable this new unstable feature.
  • Draft a stabilisation or de-RFC report based on the experiment data to finalise the fate of this unstable feature.

For derive(CoercePointee):

The implementation is largely done, but the stabilization is blocked on arbitrary_self_types. Once that feature is stabilized, we can proceed with stabilizing derive(CoercePointee) too.

Work items over the next year

TaskOwner(s)Notes
Implementation of Deref decouplingDing Xiang Fei
(de-)RFC raw pointer receiversDing Xiang Fei
Update arbitrary_self_types documentationDing Xiang Fei
arbitrary_self_types Reference PRDing Xiang Fei
arbitrary_self_types Stabilization PRDing Xiang Fei
Deref/Receiver ImplementationDing Xiang Fei
Deref/Receiver Community engagementDing Xiang Fei
Deref/Receiver Stabilization PRDing Xiang Fei
Deref/Receiver Reference PRDing Xiang Fei
derive(CoercePointee) Reference PRAlice RyhlBlocked on `arbitrary_self_types
derive(CoercePointee) Stabilization PRAlice RyhlBlocked on `arbitrary_self_types

Team asks

TeamSupport levelNotes
langMediumReviews, Lang/RfL meetings
lang-docsMediumReviews, Lang/RfL meetings
libsSmallReviews
libs-apiSmallStabilizations
typesLargeReview of type-system stabilization/implementation

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

asm_const_ptr

Metadata
Point of contactAlice Ryhl
StatusProposed
RoadmapRust for Linux
Tracking issue
Other tracking issuesrust-lang/rust#128464
Zulip channelN/A
Teamslang, lang-docs, libs, libs-api
Task owners(none)

Summary

Short description of what you will do over the next year.

Motivation

The status quo

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

What we propose to do about it

Explain your overall approach to solving the problem. Explain your design philosophy (including design axioms). Focus your discussion on what you aim to get done this year, but it is good to also give a sense for the “overall goal” you are working towards, if it extends beyond the work for this year. Team(s) should give you feedback on whether they are aligned both with your short-term and longer-term goals.

Work items over the next year

TaskOwner(s)Notes
Implementation & docsAlice Ryhl
Reference PR
Style and rustfmt
Stabilization PR

Team asks

TeamSupport levelNotes
langMediumReviews, Lang/RfL meetings
lang-docsMediumReviews, Lang/RfL meetings
libsSmallReviews
libs-apiSmallStabilizations

Assumptions on Binders

Metadata
Point of contactBoxy
StatusProposed
Tracking issue
Zulip channelN/A (just make a thread in t-types)
types championBoxy
Teamstypes
Task owners(none)

Summary

Attempt to implement a version of -Zhigher-ranked-assumptions which works for all binders, not just witness types of futures.

Motivation

The status quo

Binders (for<'a>) currently don’t track any where clauses involving the bound variables introduced. This leads to many bugs (some soundness bugs) e.g. “that async Send bug” (#149407), or higher ranked subtyping being unsound (#25860).

The -Zhigher-ranked-assumptions flag currently exists and tries so solve some of the problems caused by this, but it is not fully general and likely not the implementation strategy we want when solving all problems in this area.

What we propose to do about it

Figure out a different impl strategy than -Zhigher-ranked-assumptions’s current design then try and implement a prototype.

Work items over the next year

TaskOwner(s)Notes
Figure out impl possibilitiesBoxy
Attempt to implement a prototypeBoxy

Team asks

TeamSupport levelNotes
typesMediumimplementation/reviews/deciding on a design

Frequently asked questions

Will anything be stabilized

We are not intending to do anything affecting stable users in this goal period. It will likely take a while to get anything working, let alone good enough to stabilize.

Async Future Memory Optimisation

Metadata
Point of contactDing Xiang Fei
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler
Task owners(none)

Summary

We want to solve async-future memory bloat problem.

Playground

async fn combining_future(compute: impl Future<Output = ()>) {
    async {}.await;
    compute.await;
}

fn main() {
    let blob = [0u8; 65536];
    let monster = combining_future(combining_future(combining_future(combining_future(async move {
        async {}.await;
        println!("{:?}", blob)
    }))));
    println!("{}", std::mem::size_of_val(&monster));
    //~^ prints at least 1000000 bytes
}

We would like to deliver the first async-future memory packing scheme -Zpack-coroutine-layout as a nightly-only compiler flag, followed by a more aggressive memory packing scheme built on top of the foundation of the first pack-coroutine-layout support. Meanwhile, we would like to conduct two experiments in two possible approaches that could further improve the memory economy of async-futures.

  • Explore the memory layout optimisation by enabling coroutine state inlining.
  • Explore direct lowering of Rust async-futures, and coroutines in particular, into native LLVM coroutine intrinsics.

Motivation

The status quo

Exponential growth of async-future types has been a long-standing issue, tracked by #62958. In addition, any data that is alive and used across more than two await points will incur further penalty, because their memory slots are indiscriminately reserved throughout the futures’ life span.

This issue has manifested in two ways that hinder the adoption of general async Rust or require use of unergonomic mitigations.

  • On cloud platforms and in general network computing applications, it has led to unexpected or even unexplainable stack-overflow that is hard to debug. Application developers have to resort to unnecessary heap allocation and indirection in order to restore reliability.
  • On embedded platforms and specialised environments, such as Linux Kernel, this issue has been quoted as the greatest concern to respective developers. Rust async has been a very attractive abstraction, but the memory footprint issue has deterred adoption in such fields because the memory requirement is more stringent.

What we propose to do about it

A proposed fix has been proposed in #135527 which strives for perfect preservation of coroutine semantics while reducing the memory bloat contributed by coroutine captures, which has been the most common case for large future sizes. This experimental implementation work has shown success in improving future sizes. It also retains the default memory layout scheme in order to allow experimentation without affecting existing stable Rust users. Based on this foundation, the proposed work involves a second packing scheme to relax the overall layout computation, so that memory allocation can still be released even values are live across more than one await suspension points, enabling even further memory compaction. These changes will continue to abide by the design axiom, under which the surface Rust language remains unchanged and improvement work should be contained only in the internal Application Binary Interface (ABI) or code generation.

The proposed work also includes two further experiments as stretch goals.

  • Enabling inlining of coroutine states: Many cases of bloat in async-future arise from combining futures in a nested fashion, where one future needs to drive other futures towards completion. The state and data of the nested futures are currently opaque to the driver future and the layout calculation must consider the memory layouts of the futures in isolation. This unfortunately leads to sub-optimal memory allotment leaving padding gaps that could have been used. Inlining these futures under reasonable conditions, on the other hand, allows the layout computation to pool the liveness information of futures’ internal data as a whole and enable the opportunity to fill the padding gaps.
  • Experimenting with unstable coroutine intrinsics of LLVM: LLVM has since made coroutine intrinsics available, albeit without stability guarantee across releases at the moment. Nevertheless, this enables a code generation strategy for Rust async futures, which is to directly lower coroutine MIRs into LLVM IR coroutines, through one or more lowering strategies from LLVM. This allows LLVM to independently compute coroutine liveness information and eventually layout information directly, like how regular Rust synchronous fn is compiled, by exploiting the target information known to LLVM. This will potentially also allow LLVM to further apply optimisation to the final coroutine code, given more accurate information made available by the Rust code generator.

Work items over the next year

TaskOwner(s)Notes
Polish the initial PR and mergeDing Xiang FeiThis is a work item that is most feasible, with work ready for upstreaming
Implement the second packing scheme, removing the liveness restrictionDing Xiang FeiThis is a work item that can be experimental, with existing work ready for reviews
Perform industry-wide survey to measure improvementsDing Xiang Fei et al.This is a work item that requires collaboration with partners
Implement coroutine inlining under reasonable conditionDing Xiang FeiThis is a stretch goal that requires design meetings
Explore lowering to native LLVM coroutine, draft design documentation, liaison with LLVM on potential upstream workTentatively Ding Xiang FeiThis is a work item that requires collaboration with compiler team and partners at LLVM

Team asks

TeamSupport levelNotes
compilerMediumIs this Small or Medium? Does it need a champion?

Frequently asked questions

Async statemachine optimisation

Metadata
Point of contact@diondokter
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler
Task owners(none)

Summary

Add optimisations to the coroutine MIR transform to elide or simplify the generated statemachines.

This will help both async futures and generators.

Note: This has some overlap with this other proposal. I’m not trying to userp the issue. I was working on it incidentally at the same time and noticed very late that proposal already existed.

Motivation

The status quo

Generated Rust futures (from async blocks and functions) are unoptimised. That is, they always naively generate a full statemachine even when it’s not required.

Often on opt-level 3, the compiler is able to optimize out this statemachine. But when the tree of futures gets deep, this is no longer the case. The compiler struggles even more on opt-level s or z where even simple cases aren’t optimized away.

Every statemachine also has a panicking branch. This litters the code with panics that makes the compiler’s job a lot more difficult. Those panics will also pretty much never be run when a good functioning executor is used to poll the futures.

What we propose to do about it

I want to come up with a list of optimisations we can do. I’ve already thought of a couple.

A simple example:

#![allow(unused)]
fn main() {
// MIR for `foo::{closure#0}` 0 coroutine_resume
/* coroutine_layout = CoroutineLayout {
    field_tys: {},
    variant_fields: {
        Unresumed(0): [],
        Returned (1): [],
        Panicked (2): [],
    },
    storage_conflicts: BitMatrix(0x0) {},
} */

async fn foo() -> i32 {
    5
}
}

This generates a whole statemachine with 3 states. In the best case, LLVM can optimize this away. But when this is deep in an async ‘tree’, the compiler can fail to optimize this away. This leads to lost performance and binary size bloat. The latter of which is very noticeable on embedded.

Another example:

#![allow(unused)]
fn main() {
async fn bar() -> i32 {
    foo().await
}
}

Here bar gets its own future, just to poll the foo future. Instead bar could ‘become’ the foo future which would save a statemachine.

I believe that if we keep stacking optimizations like these, we’ll get some really nice results.

I’ve got 3 optimisations on my list so far. You can see them in the work items and in the draft blog post I’m writing (linked in FAQ).

Work items over the next year

TaskOwner(s)Notes
Create a list of all the optimisations we could do@diondokter
Create (unstable?) compiler flag to replace future panics with returning Poll::Pending@diondokter
Create an optimisation for futures with no awaits@diondokter
Create an optimisation for futures with one await (bar becomes foo)@diondokterMaybe generalisable to the ‘last’ await
Implement the rest of the list from task 1@diondokter

Team asks

TeamSupport levelNotes
compilerMediumMost will be review work, but pushing optimisations to the max will possibly touch on some controversial points that need discussion

Frequently asked questions

Why this, why now?

I work as an embedded developer most of the time. We love to use async Rust, but as the firmware grows in size, the async bloat gets quite unwieldy. For example, I developed a, async radio device driver. After I was done I wrote an example for it.

The example was about 35 KB in binary size. This seemed way too big, so I converted it to be mostly blocking code and the size dropped to about 17 KB. This shows how much bloat async can add.

For a big customer we were running against the 900 KB limit of the hardware and had to do a lot of manual optimisations to the async code to make it fit. I then looked into the MIR pass responsible and found it pretty much does no optimisations.

The plan is/was to find parties willing to fund work on these optimisations. To get to stage, we want to release 2 blogposts on the Tweede golf website. The first one will cover the bloat and some optimisations you can do as a developer now and the second one (draft) dives more into how we could bring those optimisations to the compiler so you don’t have to apply them manually anymore.

What’s your commitment?

Without funding other commercial work will sadly take priority. This means I can only commit up to half a day per week on most weeks.

With funding we can make it a real project and we (Tweede golf) can bring in more people too like Folkert de Vries and/or bjorn3.

How does this relate to the other similar proposal?

We have similar goals, but a different philosofy.

I want to tackle the problem at the front:

  • Stop generating statemachines that don’t have to be there
  • Make the compiler’s job easier by removing panic paths and branches
  • Make statemachines smaller

The other proposal tackles the problem at the back:

  • Given there are statemachines, make them interact better with each other (real proper inlining)
  • Research the options LLVM now provides

I think these can compliment each other. Optimisations done at the front will trickle down to the optimisations at the back. Inlining a small statemachine should prove easier/more efficient than inlining a big statemachine.

Also, for code size you may not want to inline everything, just as with normal blocking code.

BorrowSanitizer

Metadata
Point of contactIan McCormack
StatusProposed
Tracking issue
Zulip channelN/A
compiler championRalf Jung
opsem championRalf Jung
lang championTyler Mandry
Teamscompiler, infra, lang, opsem
Task owners(none)

Summary

We are building BorrowSanitizer: an LLVM-based instrumentation tool for finding violations of Rust’s aliasing model. In 2026, we want to make it feature-complete and useful in practice.

Motivation

The status quo

Developers rely on Miri to validate their programs against Rust’s latest Tree Borrows aliasing model. However, Miri cannot find these Rust-specific aliasing bugs when they are caused by foreign function calls. Miri’s performance is also several orders of magnitude slower than native execution. As Rust is increasingly being in security-critical C and C++ applications, like Android and Chromium, developers will need a method for finding aliasing errors that can scale across language boundaries.

What we propose to do about it

We are developing BorrowSanitizer to fix this tooling gap. Much like AddressSanitizer, MemorySanitizer, and other LLVM-based tools, BorrowSanitizer inserts checks during compilation to detect errors at run-time. Its purpose is to find violations of Rust’s newest Tree Borrows aliasing model, as well as accesses out-of-bounds and use-after-free errors.

BorrowSanitizer relies on changes to the Rust compiler, an LLVM instrumentation pass, and a runtime library. We modified the compiler to emit special “retag” intrinsics that indicate when references are created and updated. Our LLVM pass lowers these intrinsics into runtime calls that associate each pointer with “provenance” metadata (see RFC #3559(https://rust-lang.github.io/rfcs/3559-rust-has-provenance.html)). We validate provenance before memory accesses to detect undefined behavior.

Our primary goal is for BorrowSanitizer to be useful in practice. This will require broad support for Rust, C, and C++ language features. We want to achieve better performance than Miri while fully supporting the different features of Tree Borrows.

Work items over the next year

Throughout 2026, we will complete the remaining features needed for BorrowSanitizer to have parity with Miri for detecting aliasing violations. We will finish contributing the retag intrinsics described in our previous project goal and evaluate when and how the rest of BorrowSanitizer should be integrated with the compiler.

One topic for discussion is whether the BorrowSanitizer itself should live in a subtree of rust-lang/rust, with a new Github repo under rust-lang, or as an independent project.

TaskOwner(s)Notes
Complete MCP and implementation for retag intrinsicsIan McCormack
Feature-parity with MiriIan McCormack, BorSan TeamGarbage collection, error reporting, atomics, interception, and more!
Automated EvaluationIan McCormack, BorSan TeamSelf-hosted crater instance, benchmarking.
Full compiler integrationIan McCormackHave the runtime, instrumentation pass, and other components available upstream in nightly.

BorrowSanitizer is open source and available on GitHub, and we welcome any contributions. We will post monthly status updates on our website throughout 2026. We are available at any point for Q/A on Zulip. Ian McCormack will be the primary point-of-contact for the BorrowSanitizer Team.

Team asks

TeamSupport levelNotes
compilerMediumChampion: Ralf Jung. Design discussions, PR review, and upstream integration.
opsemMediumChampion: Ralf Jung.
langSmallChampion: Tyler Mandry. General support and guidance.
infraSmallUpstream integration.

Frequently asked questions

build-std

Metadata
Point of contactDavid Wood
StatusProposed
RoadmapBuilding blocks
Zulip channel#project-goals/build-std
Tracking issuerust-lang/rust-project-goals#274
Teamscargo, compiler, crates-io, libs
Task owners(none)

Summary

Complete the remaining design work for #3874 and #3875 and start on implementation.

Motivation

build-std is a well-known unstable feature in Cargo which enables Cargo to re-build the standard library, this is useful for a variety of reasons:

  1. Building the standard library without relying on unstable escape hatches

  2. Building standard library crates that are not shipped for a target

  3. Using the standard library with tier three targets

  4. Unblock stabilisation of ABI-modifying compiler flags

  5. Re-building the standard library with different codegen flags or profile

The following use cases are not currently planned as part of this project goal, but could be supported with follow-up goals:

  1. Using the standard library with custom targets

  2. Enabling Cargo features for the standard library

  3. Progress towards using miri on a stable toolchain

Some use cases are unlikely to be supported by this project goal unless a new and compelling use-case is presented, and so this project goal may make decisions which make these motivations harder to solve in future:

  1. Modifying the source code of the standard library

  2. Retire the concept of the sysroot

These features are more useful for some subsets of the Rust community, such as embedded developers where optimising for size can be more important and where the targets often don’t ship with a pre-compiled std.

The status quo

In previous goal cycles, the goal authors in collaboration with relevant project teams have drafted a proposed design for build-std, resulting in rust-lang/rfcs#3873, rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and two yet-to-be-published RFCs. rust-lang/rfcs#3873 has since been accepted.

What we propose to do about it

There are two primary objectives of this goal in this next goal cycle:

  1. Continue to address feedback on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 until these RFCs are accepted

  2. Start implementation of rust-lang/rfcs#3874 and rust-lang/rfcs#3875

Work items over the next year

TaskOwner(s)Notes
Continue to run the weekly build-std sync meetingdavidtwcoInvite available in Zulip for anyone interested
Continue to advance build-std RFCsdavidtwco
Implement build-stdadamgemmellSee https://hackmd.io/BcimnLUdQ0W3kv9dd9rMUw for a detailed breakdown of implementation required

Team asks

TeamSupport levelNotes
cargoLargeReviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and many implementation patches
compilerSmallReviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches
libsSmallReviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches
crates-ioSmallReviews of rust-lang/rfcs#3874 and rust-lang/rfcs#3875 and any implementation patches

Frequently asked questions

None yet.

rust-lang/rfcs#3874: https://github.com/rust-lang/rfcs/pull/3874 rust-lang/rfcs#3875: https://github.com/rust-lang/rfcs/pull/3875

Cargo cross workspace cache

Metadata
Point of contactRoss Sullivan
StatusProposed
Tracking issue
Zulip channelN/A
cargo championEd Page
Teamscargo
Task owners(none)

Summary

Work towards a build cache that is shared across workspaces to build times and reduce disk usage.

Motivation

The status quo

Currently Cargo stores build artifacts in build-dir (which defaults to target in root of the workspace). These artifacts are local to the current workspace. This is not ideal as it requires Cargo to rebuild build units when we could simply reuse the artifacts that have previously been built for other workspaces. Not sharing artifacts across workspaces also results in higher disc usage as files are duplicated.

What we propose to do about it

In 2025, we split target-dir into 2 directories (artifact-dir and build-dir) as well as began re-organizing the file layout to be grouped by build unit. With this preliminary work complete, we can begin working towards creating a shared cache that shares build units across workspaces.

A shared cache would:

  • Skip compilation for commonly used crates
  • Reduce disk usage as we only store build artifacts for a given build unit once
  • Make it possible to share build artifacts between profiles (e.g. debug, release)
  • Provide a central location to cleanup unneeded build artifacts (potentially automatically by Cargo)
  • Could be extended in the future to be pre-populated from a remote cache for CI usecases.

In 2026, we will design and implement this cache in Cargo, making it available on nightly for users to begin experimenting with. (tracked in cargo#5931) As part of implementing the cache we will stabilize the build-dir layout rework that was done in 2025. In the beginning, the cache would be fairly conservative in what is cached but would be expanded over time. At the end of the year, we should have an understanding of the benefits and tradeoffs of the design we pick as well as a rough path towards stablization.

Work items over the next year

TaskOwner(s)Notes
Design the cacheRoss SullivanIn collaboration with T-cargo
Implement in CargoRoss Sullivan

Team asks

TeamSupport levelNotes
cargoMediumDesign and code reviews

Frequently asked questions

What about shared CARGO_TARGET_DIR?

Having a global CARGO_TARGET_DIR is a common pattern, but comes with some downsides like cargo clean removing all artifacts for all workspaces as well not having the output binaries in the workspace directory. Users also need to be aware of this pattern and configure it themselves. It would be great if we could get the benefits of a shared CARGO_TARGET_DIR out of the box no configuration.

What about tools like sccache?

Tools like sccache try to infer inputs for hashing a cache key from command-line arguments. In Cargo, we have much more knowledge about the dependency graph and crate metadata, which could allow us to be more aggressive in what we choose to cache.

Prototype a new set of Cargo “plumbing” commands

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
RoadmapBuilding blocks
Tracking issuerust-lang/rust-project-goals#264
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
Teamscargo
Task owners(none)

Summary

  1. Refactor Cargo to allow hacks in proposed cargo-plumbing commands to be removed (cargo-plumbing#82).
  2. Round out proposed commands (issues)
  3. Finalize the message formats (cargo-plumbing#18)

Contingent on contributor: This goal needs contributors to refactor Cargo internals, implement remaining plumbing commands, optimize performance, and iterate on output schemas. The work is primarily in rust-lang/cargo and crate-ci/cargo-plumbing. Estimated time commitment: TBD.

Motivation

Cargo is a “porcelain” (UX) focused command and is highly opinionated which can work well for common cases. However, as Cargo scales into larger applications, users need the ability to adapt Cargo to their specific processes and needs.

The status quo

While most Cargo commands can be used programmatically, they still only operate at the porcelain level. Currently, Cargo’s plumbing commands are

  • cargo read-manifest:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • deprecated
  • cargo locate-project:
    • works off of a Cargo.toml file on disk
    • text or json output, undocumented json schema
    • uses a pre-1.0 term for package
  • cargo metadata:
    • works off of Cargo.toml, Cargo.lock files on disk
    • uses a custom json schema
    • can include dependency resolution but excludes feature resolution
    • some users want this faster
    • some users want this to report more information
    • See also open issues
  • cargo pkgid:
    • works off of Cargo.toml, Cargo.lock files on disk
    • text output
  • cargo verify-project:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • uses a pre-1.0 term for package
    • deprecated

There have been experiments for a plumbing for builds

  • --build-plan attempts to report what commands will be run so external build tools can manage them.
    • The actual commands to be run is dynamic, based on the output of build scripts from build graph dependencies
    • Difficulty in supporting build pipelining
  • --unit-graph reports the graph the build operates off of which corresponds to calls to the compiler and build scripts
    • Also provides a way to get the results of feature resolution

Thanks to GSoC, we now have prototypes for some plumbing commands.

The next 6 months

Continue on the third-party subcommand to experiment with plumbing commands (source).

TaskOwner(s) or team(s)Notes
Refactor cargoHelp wanted
Implement remaining commandsHelp wanted
Inside Rust blog post inviting feedbackEd Page
Optimizing CargoHelp wanted, Ed Page
Iterate on schemas including schema evolution planHelp wanted

See 2025h2 goal for more background.

The “shiny future” we are working towards

  • Collect user feedback on these commands and iterate on them for eventual inclusion into Cargo
  • Evaluate refactoring Cargo to better align with these plumbing commands to have better boundaries between subsystems
  • Evaluate splitting the cargo [lib] into crates for each of these plumbing commands as smaller, more approachable, more “blessed” Rust APIs for users to call into

Team asks

TeamSupport levelNotes
cargoSmallPR reviews for Cargo changes; design discussions

Frequently asked questions

Stabilize cargo-script

Metadata
Point of contactEd Page
StatusProposed
Tracking issuerust-lang/rust-project-goals#119
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
HighlightCargo improvements
Teamscargo, compiler, lang, rustdoc
Task owners(none)

Summary

Stabilize support for “cargo script”, the ability to have a single file that contains both Rust code and a Cargo.toml.

Motivation

Being able to have a Cargo package in a single file can reduce friction in development and communication, improving bug reports, educational material, prototyping, and development of small utilities.

The status quo

Today, at minimum a Cargo package is at least two files (Cargo.toml and either main.rs or lib.rs). The Cargo.toml has several required fields.

To share this in a bug report, people resort to

  • Creating a repo and sharing it
  • A shell script that cats out to multiple files
  • Manually specifying each file
  • Under-specifying the reproduction case (likely the most common due to being the easiest)

To create a utility, a developer will need to run cargo new, update the Cargo.toml and main.rs, and decide on a strategy to run this (e.g. a shell script in the path that calls cargo run --manifest-path ...).

Cargo has had unstable Cargo script support for years. New, unstable syntax has been added and gone through rounds of testing. A stabilization report exists for frontmatter syntax but work is needed to finish going through that process and then on Cargo’s side.

The next 6 months

Work with T-lang, T-cargo, and other affected teams as we go through the stabilization process.

TaskOwner(s)Notes
T-rustdoc decide on frontmatter in doctestsowner
Implement behavior for frontmatter in doctestsowner

The “shiny future” we are working towards

Team asks

TeamSupport levelNotes
cargoSmallStabilization process
compilerSmallReviewing any further compiler changes
langSmallStabilization discussions
rustdocSmallDesign decision and PR review

Frequently asked questions

Continue resolving cargo-semver-checks blockers for merging into cargo

Metadata
Point of contactPredrag Gruevski
StatusProposed
RoadmapSecure your supply chain
Tracking issuerust-lang/rust-project-goals#104
Zulip channelN/A
cargo championEd Page
rustdoc championAlona Enraght-Moony
Teamscargo, rustdoc
Task owners(none)

Summary

Design and implement cargo-semver-checks functionality that lies on the critical path for merging the tool into cargo itself. Continues the work of the 2025h2 goal.

Motivation

Cargo assumes that all packages adhere to semantic versioning (SemVer). However, SemVer adherence is quite hard in practice: research shows that accidental SemVer violations are relatively common (lower-bound: in 3% of releases) and happen to Rustaceans of all skill levels. Given the significant complexity of the Rust SemVer rules, improvements here require better tooling.

cargo-semver-checks is a linter for semantic versioning (SemVer) in Rust. It is broadly adopted by the Rust community, and the cargo team has expressed interest in merging it into cargo itself as part of the existing cargo publish workflow. By default, cargo publish would require SemVer compliance, but offer a flag (analogous to the --allow-dirty flag for uncommitted changes) to override the SemVer check and proceed with publishing anyway.

The cargo team has identified a set of milestones and blockers that must be resolved before cargo-semver-checks can be integrated into the cargo publish workflow. Our goal here is to make steady progress toward resolving them.

From a user perspective, we want a fearless cargo update: one’s project should never be broken by updating dependences without changing major versions.

From a maintainer perspective, we want a fearless cargo publish: we want to prevent breakage, not to find out about it when a frustrated user opens a GitHub issue. Just like cargo flags uncommitted changes in the publish flow, it should also quickly and accurately flag breaking changes in non-major releases. Then the maintainer may choose to release a major version instead, or acknowledge and explicitly override the check to proceed with publishing as-is.

To accomplish this, cargo-semver-checks needs the ability to express more kinds of lints (including manifest and type-based ones), eliminate false-positives, and stabilize its public interfaces (e.g. the CLI). At that point, we’ll have lifted the main merge-blockers and we can consider making it a first-party component of cargo itself.

The status quo

cargo-semver-checks currently ships with 245 lints, and is effective at catching many forms of breakage — both in crate manifests and also inside crates’ source code.

However, many more lints remain to be written, and they will require additional infrastructure in both rustdoc JSON and in cargo-semver-checks itself, as we describe below.

For a detailed look at the status quo, we recommend checking out the most recent cargo-semver-checks annual summary

What we propose to do about it

The following are the largest remaining blockers for merging cargo-semver-checks in Cargo:

Performing type-checking in lints

https://github.com/obi1kenobi/cargo-semver-checks/issues/149

This lets us catch changes like: pub fn example(x: i64) {} becoming pub fn example(x: String) {}.

This is our most commonly requested feature today, and will resolve the largest remaining class of false-negative (lint should fire, but doesn’t) outcomes!

We plan to accomplish this in two steps:

  • Expose additional information in rustdoc JSON to make it possible to reliably observe that something about a type has changed. This will enable some lints by itself, but is not sufficient in all cases: for example, changing impl Display to String or vice versa isn’t always breaking.
  • Build out infrastructure in cargo-semver-checks to make it possible to generate “witness” programs: ones on which cargo check can be executed in order to determine whether a changed type caused breakage or not. This will allow us to rely on rustc to be the arbiter of breakage, instead of requiring us to reimplement the Rust type checker, trait solver, borrow checker, etc. Some of the infrastructure here was already built as part of GSoC 2025, and we expect to continue building on top of that foundation.

Linting across crate boundaries

https://github.com/obi1kenobi/cargo-semver-checks/issues/638

Linting across crate boundaries with high reliability and acceptable performance, so that for example, we can correctly handle cross-crate item re-exports. This will resolve the largest remaining class of false-positive bugs (a lint fires where it shouldn’t) in our linting system.

Completing this will require close cooperation with T-rustdoc, to enable rustdoc JSON files to be reliably connected to each other. This work already began in 2025 with Alona Enraght-Moony leading it from the rustdoc side.

Participate Google Summer of Code (GSoC)

The main blocker towards progress is funding and development capacity. cargo-semver-checks has successfully participated in GSoC before and we plan to do it again.

Work items over the next year

Owner: Predrag Gruevski, as maintainer of cargo-semver-checks

I (Predrag Gruevski) will be working on this effort. The only other resource request would be occasional discussions and moral support from the cargo and rustdoc teams, of which I already have the privilege as maintainer of a popular cargo plugin that makes extensive use of rustdoc JSON.

TaskOwner(s)Notes
Audit lint contributionsPredrag Gruevski
Mentor GSoC participantsPredrag Gruevski
Implement type-checking in lints
Implement linting across crate boundaries

Team asks

TeamSupport levelNotes
cargoSmallDiscussion and moral support
rustdocSmallDiscussion and moral support

Frequently asked questions

This section is unchanged from the 2024h2 goal.

Why not use semverver instead?

Semverver is a prior attempt at enforcing SemVer compliance, but has been deprecated and is no longer developed or maintained. It relied on compiler-internal APIs, which are much more unstable than rustdoc JSON and required much more maintenance to “keep the lights on.” This also meant that semverver required users to install a specific nightly versions that were known to be compatible with their version of semverver.

While cargo-semver-checks relies on rustdoc JSON which is also an unstable nightly-only interface, its changes are much less frequent and less severe. By using the Trustfall query engine, cargo-semver-checks can simultaneously support a range of rustdoc JSON formats (and therefore Rust versions) within the same tool. On the maintenance side, cargo-semver-checks lints are written in a declarative manner that is oblivious to the details of the underlying data format, and do not need to be updated when the rustdoc JSON format changes. This makes maintenance much easier: updating to a new rustdoc JSON format usually requires just a few lines of code, instead of “a few lines of code apiece in each of hundreds of lints.”

cfg(no_fp_fmt_parse)

Metadata
Point of contact@todo
StatusProposed
RoadmapRust for Linux
Tracking issue
Other tracking issuesrust-lang/rust#86048
Zulip channelN/A
Teamslang, lang-docs, libs, libs-api
Task owners(none)

Summary

Short description of what you will do over the next year.

Motivation

The status quo

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

What we propose to do about it

Explain your overall approach to solving the problem. Explain your design philosophy (including design axioms). Focus your discussion on what you aim to get done this year, but it is good to also give a sense for the “overall goal” you are working towards, if it extends beyond the work for this year. Team(s) should give you feedback on whether they are aligned both with your short-term and longer-term goals.

Work items over the next year

TaskOwner(s)Notes
Reference PR
Stabilization PR

Team asks

TeamSupport levelNotes
langMediumReviews, Lang/RfL meetings
lang-docsMediumReviews, Lang/RfL meetings
libsSmallReviews
libs-apiSmallStabilizations

Const Generics

Metadata
Point of contactBoxy
StatusProposed
RoadmapConstify all the things
Tracking issuerust-lang/rust-project-goals#100
Zulip channelN/A
HighlightLanguage changes
lang championNiko Matsakis
types championBoxy
Teamscompiler, lang, types
Task owners(none)

Summary

Extend const generics in two independent directions, both aiming for stabilization:

  • adt_const_params: Allow structs and enums as const generic arguments, not just integers.
  • min_generic_const_args: Allow associated constants as const generic arguments (e.g., Foo<T::ASSOC_CONST>).

We will also model const generics in a-mir-formality and experiment with upstreaming those changes into the Rust specification. This work also serves as a forcing function for advancing a-mir-formality and its integration into the Rust specification.

Motivation

The status quo

The min_const_generics feature is stable, but with significant limitations on what can be used as a const generic argument:

  • Only integers: Const generic parameters are limited to integer types. You cannot use structs or enums, even simple ones like struct Dimensions { width: u32, height: u32 }.
  • Only literals or generic parameters: You can write Foo<5> or Foo<N> (where N is a const generic parameter), but you cannot write Foo<T::ASSOC_CONST> to use an associated constant.

When using const generics it is common to run into these limitations and be unable to move forwards, having to rewrite your code to use workarounds or not use const generics at all. This is a poor user experience and makes the language feel incomplete.

The next few steps

We are extending const generics in two independent directions:

adt_const_params: Extending const generic arguments to include structs and enums. The implementation is largely complete, but we need to:

  • Publish an RFC defining which ADTs are permitted. Some structs may be excluded due to concerns about privacy and unsafe invariants when the compiler infers const values. The RFC will nail down the precise rules.
  • Model the feature in a-mir-formality to ensure we have a solid specification.

min_generic_const_args (MGCA): Extending const generic arguments to include associated constants. This is currently in a “full prototype” state (feature(min_generic_const_args) has been merged) with more work needed before stabilization.

The “shiny future” we are working towards

Our ultimate goal is to stabilize all parts of the const generics feature that were left out of the minimum stabilization. Users should not encounter “functionality cliffs” where const generics suddenly stops working as well as type generics, forcing code to be rewritten to work around language limitations.

Design axioms

TBD

Work items over the next year

TaskOwner(s)Notes
Publish and merge adt_const_params RFCBoxy
Model adt_const_params in a-mir-formalityBoxyNiko Matsakis to help
Stabilize adt_const_params
Finish min_generic_const_args implementationBoxyCurrently in “full prototype” state
Model min_generic_const_args in a-mir-formalityBoxyNiko Matsakis to help
Stabilize min_generic_const_args

Team asks

TeamSupport levelNotes
langLargeStabilization decisions, directional alignment
typesLargea-mir-formality modeling, design alignment
compilerSmallCode reviews

Frequently asked questions

What is the role of lang vs types team in the stabilizations?

The question of what equality means and what kinds of ADTs (structs, enums) can be used as const values, intersects both lang and types (adt_const_params).

Design and stabilization of min_generic_const_args is purely a types team affair.

Stabilize Const Traits

Metadata
Point of contactDeadbeef
StatusProposed
Tracking issuerust-lang/rust-project-goals#106
Zulip channel#t-compiler/project-const-traits
Highlighttrue
RoadmapConstify all the things
types championOliver Scherer
Teamscompiler, lang, types
Task owners(none)

Summary

Finish drafting the const traits RFC to address outstanding concerns; do any remaining work necessary in the compiler to push const traits towards stabilization.

Motivation

const fn on stable are unable to invoke trait methods, limiting their usefulness. After years of experimentation, the compiler now has a promising implementation of const traits and key parts of the stdlib have been updated to use it. However, the feature is still firmly in experimental territory: there has never been an accepted RFC describing its syntax.

The goal for the next year is to build upon the currently open RFC to finalize the syntax and semantics of const traits, make the required compiler changes, issue a public call for experimentation, and otherwise pave the ground for stabilization.

The status quo

People write a lot of code that will be run in compile time. They include procedural macros, build scripts (42.8k hits on GitHub for build.rs), and const functions/consts (108k hits on GitHub for const fn). Not being able to write const functions with generic behavior is often cited as a pain point of Rust’s compile time capabilities. Because of the limited expressiveness of const fn, people may decide to move some compile time logic to a build script, which could increase build times, or simply choose not to do it in compile time (even though it would have helped runtime performance).

There are also language features that require the use of traits, such as iterating with for and handling errors with ?. Because the Iterator and Try traits currently cannot be used in constant contexts, people are unable to use ? to handle results, nor use iterators e.g. for x in 0..5.

What we propose to do about it

The compiler already has a mature implementation of const traits. We will draft the RFC to address any outstanding concerns from existing feedback. Afterwards we will call for testing and push for stabilization.

Work items over the next year

TaskOwner(s)Notes
Edit and merge the RFCDeadbeef
Finalize compiler implDeadbeef
Stabilize const traitsDeadbeef

Team asks

TeamSupport levelNotes
langLargeSemantics, syntax, and stabilization decisions
typesLargeImplementation design and sign-off
compilerSmallCode reviews

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Crate Slicing for Faster Fresh Builds

Metadata
Point of contact@yijunyu
StatusProposed
Zulip channelTBD
Teamscargo, compiler, lang, rust-analyzer, types
Task owners(none)

Summary

Prototype “crate slicing” — a static analysis technique that computes the transitive closure of items actually used from dependency crates and generates minimal sliced versions, reducing frontend parsing and type-checking overhead during fresh builds.

Motivation

The status quo

Rust compilation remains I/O and CPU-bound on dependency crates during fresh builds. Consider a typical async web service:

[dependencies]
tokio = { version = "1.48", features = ["full"] }
axum = "0.7"
serde = { version = "1", features = ["derive"] }
sqlx = { version = "0.8", features = ["postgres", "runtime-tokio"] }

This dependency graph expands to 161 crates. The tokio crate alone contains 315 module files totaling 92,790 lines of Rust source. Yet an application may only use a fraction of tokio’s public API surface (e.g., tokio::spawn), and some may depend only on a subcrate e.g., tokio-macros rather than on the main crate (as did by the cargo-slicer tool).

The Rust compiler is designed to find and diagnose errors first and generate good code quickly second, hence it needs to do the following steps:

  1. Parse all the ~90,000 lines
  2. Resolve names and expand macros across all modules and submodules
  3. Type-check all items, including unused ones
  4. Monomorphize generic code (though only used instantiations)

Only step 4 naturally excludes unused code. Steps 1-3 process everything.

Current mitigations:

  • Incremental compilation: Caches type-checking results but requires prior builds
  • sccache: Caches compilation artifacts but requires cache hits
  • Cranelift: Accelerates codegen but not frontend (steps 1-3)
  • Parallel frontend: Parallelizes work but doesn’t reduce total work
  • Hint mostly unused: Avoid codegen from unused dependencies by hinting on LLVM linker

None of these reduce the fundamental quantity of source code processed during fresh builds.

The next 6 months

We propose to slice crates: statically analyzing which items a project uses from each dependency and generating minimal crate versions containing only those items plus their transitive dependencies.

Technical approach:

  1. Usage extraction: Parse project source using a customized parser or rust-analyzer to identify:

    • Direct type references, e.g., tokio::net::TcpListener
    • Use statements, e.g., use axum::{Router, routing::get}
    • Method calls via variable type tracking, e.g., listener.accept()TcpListener::accept
    • Trait bounds, e.g., impl<T: Serialize>serde::Serialize
  2. Crate indexing: Build a dependency graph of all items in the target crate:

    • Map each pub item to its defining module
    • Track pub use re-exports through the module tree
    • Evaluate #[cfg(...)] expressions against enabled features
    • Handle #[path = "..."] module redirections
  3. Transitive closure: Compute minimal item set:

    • Include all trait impls for used types
    • Follow type definitions for struct fields and enum variants
    • Expand pub use crate::* glob re-exports
    • Preserve visibility modifiers for cross-module access
    • Include document cooments and attributes related to the preserved items
  4. Sliced crate generation: Emit minimal source:

    • Copy only needed module files
    • Filter items within each module
    • Generate Cargo.toml with subset of features/dependencies
  5. Rustc verification: For the soundness and correctness with respect to type inferencing on trait bounds, e.g., simply slicing away everything unused may lead to errors unless we have considered the corner cases. To make sure it generates correct results, we will use Rust compiler to double check the decisions made at the testing phase, before release the solution as replacement of the Rust compiler.

Prototype results (December 2025):

We have an early implementation (cargo-slicer) just demonstrates feasibility on major ecosystem crates:

CrateVersionOriginal ModulesOriginal LOCSlice TimeStatus
tokio1.48.0315~90,000✅ Compiles
actix-web4.12.187~28,000✅ Compiles
hyper1.8.151~19,000✅ Compiles
axum0.7.945~15,000✅ Compiles
reqwest0.12.2826~13,000✅ Compiles
syn2.0.x47~15,000✅ Compiles
rand0.9.231~8,000✅ Compiles
regex1.x21~6,0000.147s✅ Compiles

Measured slice times for smaller utility crates:

CrateItems NeededModule FilesLines Generated
regex3092010,671
memchr83514,475
anyhow147114,412
futures3091
once_cell2029
thiserror2028

The prototype handles complex patterns:

  • Feature flag evaluation: Parses #[cfg(all(feature = "std", not(feature = "parking_lot")))] expressions and evaluates against cargo metadata
  • Facade crates: Handles futures (re-exports from futures-*) and sqlx (facade over sqlx-core)
  • Platform-specific code: Filters #[cfg(unix)] / #[cfg(windows)] based on target
  • Proc-macro crates: Preserves as external dependencies (not sliced)
  • Re-export chains: Traces pub use self::module::Item through module hierarchy

Research goals for 2026:

  1. Quantify compilation time reduction: Benchmark cargo build with sliced vs. original dependencies across diverse projects (CLI tools, web services, embedded)

  2. Formalize soundness criteria: Under what conditions is sliced_crate semantically equivalent to original_crate for a given usage set? Key concerns:

    • Trait coherence: Are all required impl blocks included?
    • Monomorphization: Does slicing affect which generic instantiations exist?
    • Build scripts: How to handle build.rs code generation?
  3. Evaluate integration architectures:

    • Cargo plugin: cargo slice generates sliced deps before cargo build
    • Build script: Slice at build.rs time with caching
    • Registry proxy: Serve pre-sliced crates based on declared usage
    • Compiler integration: rustc-assisted slicing via query system
  4. Identify fundamental limitations: Which crate patterns cannot be safely sliced?

    • Proc-macro crates (execute at compile time)
    • Heavy build.rs generators
    • #[doc(hidden)] internal APIs used via macros
  5. Engage compiler/cargo teams: Present findings and gather feedback on viable integration paths

The “shiny future”

The end state: cargo build automatically slices dependencies based on static usage analysis, achieving:

  • 30-50% reduction in fresh build time for dependency-heavy projects
  • Faster CI pipelines: Cold builds complete much faster
  • No ecosystem changes required: Works with existing crates.io crates
  • Slicing on transitive dependencies: cache frequently used (stably dependent) crates by large project such as Zed

This complements ongoing efforts:

  • Parallel frontend reduces wall-clock time; slicing reduces total work
  • Cranelift accelerates codegen; slicing reduces frontend overhead

Design notes

Prior art: C/C++ precompilation

This research extends techniques proven effective for C/C++:

ICSM 2005 [1]: Demonstrated function-level compilation units for faster incremental builds. Changing one function recompiles only that unit.

TR2012 [2]: Formalized CTags-based splitting architecture. Identified that preprocessing overhead was the bottleneck — AWK scripts took 4.68s to process 2,000 LOC.

precc (2024-2025): Rewrote AWK to Rust, achieving 200× preprocessing speedup (4.68s → 0.022s). Achieved 1.8× fresh build speedup on Vim codebase (125 files, 100K LOC):

ModeTimeCompilation UnitsSpeedup
Baseline (gcc -j48)15s1251.0×
Passthrough (precc)8.5s1251.8×
Split (fine-grained)12s8,3111.25×

Key insight: Preprocessing overhead must be < 10% of compilation time for fresh build benefits.

Rust-specific considerations

AspectC/C++RustImplication
Compilation unit.c fileCrateSlicing operates at crate granularity
Name resolutionHeaders + includesModule systemMust trace pub use chains
GenericsTemplates (header-only)MonomorphizationOnly used instantiations codegen’d
Trait implsN/ACoherence rulesMust include all impls for used types
Conditional compilation#ifdef#[cfg] + featuresMust evaluate feature expressions
MacrosPreprocessor (textual)Proc-macros (semantic) + macro_rules!Proc-macro crates kept as-is

Technical challenges solved

The prototype required solving several non-trivial problems:

  1. Cfg expression parsing: Hand-rolled parser for all(), any(), not(), feature = "x", target_os = "linux" expressions

  2. Feature resolution: Query cargo metadata for enabled features, expand default features from crate’s own Cargo.toml

  3. Module path resolution: Handle #[path = "imp_std.rs"] with cfg gates like #[cfg(feature = "std")]

  4. Re-export tracing: Follow pub use self::module::Item through arbitrary nesting

  5. Trait coherence: Conservative inclusion of all trait impls where the implementing type or trait is used

  6. Macro handling: Skip macro_rules! bodies during re-export extraction; preserve proc-macro crate references by utilizing a function similar to cargo-expand

Open research questions

  1. Monomorphization interaction: Does slicing reduce monomorphization work (fewer generic items) ?

  2. Incremental compilation interaction: Do sliced crates have smaller/faster incremental compilation fingerprints?

  3. Build determinism: Is sliced output deterministic across platforms and Rust versions?

  4. Semver compatibility: If a crate updates and the sliced subset is unchanged, can we skip recompilation?

Task list

TaskOwnerStatus
Benchmark sliced crate compilation (10 diverse crates)@yijunyuDone
Prototype cargo integration@yijunyuDone
Measure compilation time with sliced deps@yijunyuDone
Document cfg expression evaluation algorithm@yijunyuPartially Done
Formalize soundness requirements (trait coherence, visibility)@yijunyuNot started
Present research findings to cargo teamTBDNot started
Write technical paper on crate slicing@yijunyuNot started

Team asks

TeamSupport levelNotes
compilerMediumConsultation on approach feasibility and soundness concerns
cargoMediumDiscussion on cargo integration options
typesSmallConsultation on trait coherence requirements for slicing
langSmallDiscussion on review of research methodology and findings
rust-analyzerSmallDiscussion on rust-analyzer integration potential

Frequently asked questions

What exactly is being “sliced”?

Source code at the item level. Given:

#![allow(unused)]
fn main() {
// In dependency crate `foo`
pub struct Used { ... }      // Kept: referenced by project
pub struct Unused { ... }    // Removed: never referenced
pub fn helper() { ... }      // Removed: never called
impl Used {
    pub fn needed(&self) { } // Kept: called by project
    pub fn extra(&self) { }  // Removed: never called
}
impl Unused { ... }          // Removed: type not used
impl Display for Used { }    // Kept: trait impl for used type
}

The sliced crate contains only Used, Used::needed, and the Display impl.

How is this different from dead code elimination?

Dead code elimination (DCE) happens during codegen for the final binary. Slicing happens before compilation, reducing:

  • Parsing time (fewer tokens to lex/parse)
  • Name resolution (smaller module tree)
  • Type checking (fewer items to check)
  • Macro expansion (fewer macro invocations)

DCE doesn’t help with these frontend costs.

How is this different from feature flags?

Feature flags require crate authors to manually partition their API:

[features]
http1 = []
http2 = ["h2"]
full = ["http1", "http2", "websocket" ] # ... and so forth

This is labor-intensive, imperfect, and doesn’t capture per-project usage patterns. Slicing is automatic and usage-based.

What about proc-macro crates?

Proc-macro crates (like serde_derive, tokio-macros) are small and execute during compilation rather than being compiled into the output. They’re preserved as-is and referenced as external dependencies in sliced crates.

Won’t sliced crates break things?

The research phase will establish correctness criteria. The prototype uses conservative inclusion:

  • All trait impls for any used type or trait
  • All items in the dependency closure
  • All visibility requirements satisfied

Current prototype compiles 100% of tested crates (8/8 major async crates, 9/9 utility crates).

What’s the expected speedup?

Preliminary hypothesis based on:

  • C/C++ precompilation achieved 1.8× speedup when preprocessing overhead was eliminated
  • Many projects use <20% of dependency API surface
  • Frontend (parsing + type-checking) is ~30-50% of compilation time

We hypothesize 20-40% reduction in fresh build time for dependency-heavy projects. The research phase will produce concrete measurements across diverse workloads.

How does this interact with caching?

Complementary:

  • sccache: Caches compiled artifacts; slicing reduces what needs caching
  • Incremental: Caches type-check results; sliced crates have smaller fingerprints
  • cargo-chef: Caches dependency layer in Docker; sliced layer is smaller

What about crates that can’t be sliced?

Known limitations:

  • Proc-macro crates: Keep as-is (small anyway)
  • Heavy build.rs: May generate code not visible to static analysis
  • #[doc(hidden)] internals: Macros may use these; conservative inclusion needed
  • Blanket impls: impl<T> Trait for T must be included if Trait is used

These are documented and handled gracefully (fall back to full crate).

References

[1] Y. Yu, H. Dayani-Fard, J. Mylopoulos, P. Andritsos. “Reducing Build Time through Precompilations for Evolving Large Software.” ICSM 2005.

[2] Y. Yu. “Precompilation: Splitting C/C++ Source Files for Faster Incremental Builds.” Open University TR2012/01.

[3] demo-precc: https://github.com/yijunyu/demo-precc (binaries for C/C++ precompilation)

[4] cargo-slicer: https://github.com/yijunyu/cargo-slicer (proof-of-concept implementation of the proposed prototype)

Ergonomic ref-counting: Share trait and move expressions

Metadata
Point of contactNiko Matsakis
StatusProposed
Contingent onContributor
RoadmapJust add async
Tracking issuerust-lang/rust-project-goals#107
Zulip channelN/A
lang championNiko Matsakis
Teamscompiler, lang, lang-docs, libs-api
Task owners(none)

Summary

Implement and prototype two foundational improvements for ergonomic ref-counting: (1) a Share trait that semantically identifies types where cloning creates an alias to the same underlying value, and (2) move expressions (move($expr)) that allow precise control over what closures capture and when. These changes lay groundwork for future ergonomic improvements while delivering immediate value, with prototypes targeted for summer 2026.

Contingent on contributor: This is a medium complexity problem. Niko Matsakis would like to mentor this goal with either an experienced contributor or a cohort of folks who know Rust but not the compiler. It is estimated that the goal will take about 6 months to implement for a cohort with minimal compiler hacking experience.

Motivation

The status quo

Working with ref-counted data in Rust is a well-documented pain point. The problem affects high-level GUI applications (Dioxus, Sycamore), async network services (tokio), language interop (PyO3), and even the Rust compiler itself. Projects have gone to great lengths to work around it, from arena-based designs to custom preprocessors.

This goal represents the culmination of extensive design exploration. After RFC #3680 proposed .use syntax and received mixed feedback, we spent 2025H2 deeply exploring the design space through a series of blog posts and community discussions. Those discussions led to reframing the goal, focusing first on solutions “low-level enough for a kernel, usable enough for a GUI”.

What we propose to do about it

We are proposing to move forward with two features

  1. a Share trait that semantically identifies types where cloning creates an alias to the same underlying value;
  2. move expressions (move($expr)) that allow precise control over what closures capture and when.

These two features make working with ref-counted data more ergonomic while still retaining Rust’s traditional guarantee that all ref counts are visible. Merging these two features is not meant to imply that we will not make other improvements targeting ref-counted data in the future, rather the idea is that these features are a solid step forward, so we should take that, and then assess what else may be needed.

Design axioms

  • Low-level enough for a kernel, usable enough for a GUI. Solutions should make low-level details visible for those who need them while being ergonomic enough for high-level applications.

  • Semantic over operational. Traits should be defined by what they mean, not just what they cost. Share means “creates an alias,” not “is cheap to clone.”

The Share trait

A new trait that identifies types where cloning creates an alias to the same underlying value:

#![allow(unused)]
fn main() {
trait Share: Clone {
    fn share(&self) -> Self {
        self.clone()
    }
}

impl<T: ?Sized> Share for Arc<T> {}
impl<T: ?Sized> Share for Rc<T> {}
impl<T: ?Sized> Share for &T {}
impl<T> Share for mpsc::Sender<T> {}
}

The share() method is semantically equivalent to clone() but signals to readers that this creates an alias, not an independent copy. Types like Arc, Rc, channel senders, and shared references would implement Share. Types like Vec or String would not—cloning those creates independent values.

This addresses a real confusion today: when you see map.clone(), you can’t tell if you’re creating a second handle to the same map or a deep copy. With Share, you’d write map.share() for the former, making the code’s intent clear.

Move expressions

Within closures and async blocks, move($expr) evaluates the expression at closure creation time and captures the result:

#![allow(unused)]
fn main() {
// Today: awkward temporary variables
let tx_clone = tx.clone();
tokio::spawn(async move {
    send_data(tx_clone).await;
});

// With move expressions: inline and clear
tokio::spawn(async {
    send_data(move(tx.clone())).await;
});
}

This generalizes Rust’s existing closure model. Rather than having separate “ref closures” and “move closures,” you have closures where some captures use move(). The move || syntax becomes shorthand for “use move() everywhere.”

Combined with Share:

#![allow(unused)]
fn main() {
tokio::spawn(async {
    do_something(move(self.some_a.share()), move(self.some_b.share()));
});
}

Work items over the next year

TaskOwner(s)Notes
RFC for Share traitNiko MatsakisDefine semantics, stdlib impls
RFC for move expressionsNiko MatsakisClosure desugaring semantics
Implement Share traitSantiago Pastorino
Implement move expressionsSantiago Pastorino
Prepare reference changesNiko Matsakis
Prepare stabilization PR for Share traitSantiago Pastorino
Prepare stabilization PR for move expressionsSantiago Pastorino

Target: Working prototypes on nightly by summer 2026.

Team asks

TeamSupport levelNotes
compilerSmallReviews
langMedium
lang-docsSmall
libs-apiSmallReviews of RFC and API surface area

Frequently asked questions

This goal looks very different than I remembered. What has changed?

The goal has taken a long journey:

2024H2: Jonathan Kelley from Dioxus wrote a blog post about high-level Rust that sparked the ergonomic ref-counting effort as a project goal.

2025H1: RFC #3680 proposed .use syntax and use || closures. Santiago Pastorino implemented experimental support on nightly. Community feedback was positive about addressing the problem but raised concerns about whether adding more required syntax actually improves ergonomics.

2025H2: Through design meetings, the RustConf Unconf, and extensive blogging, we explored the design space more deeply. Key realizations emerged:

  • Semantic over operational: Rather than defining a trait by “what is cheap to clone” (operational), we should focus on “what does cloning mean” (semantic). When you clone an Arc, you get a second handle to the same value—this “entanglement” is the key property.

  • Explicit can be ergonomic: After conversations with Josh Triplett, we concluded that some applications genuinely need to track where aliases are created. The goal should be making explicit code ergonomic, not making everything implicit.

  • Move expressions generalize nicely: The move($expr) syntax elegantly extends Rust’s existing closure model rather than adding a parallel system.

Can you give me an example of how these features will help?

The “Cloudflare example” from the Dioxus blog post illustrates the current pain:

#![allow(unused)]
fn main() {
let _some_a = self.some_a.clone();
let _some_b = self.some_b.clone();
let _some_c = self.some_c.clone();
tokio::task::spawn(async move {
    do_something(_some_a, _some_b, _some_c)
});
}

With Share and move expressions:

#![allow(unused)]
fn main() {
tokio::task::spawn(async {
    do_something(
        move(self.some_a.share()),
        move(self.some_b.share()),
        move(self.some_c.share()),
    )
});
}

This is more concise, keeps the cloning visible, and eliminates the awkward temporary variables.

Why Share instead of Alias or Handle?

We considered several names. Handle is a good noun but awkward as a verb (“handle this value?”). Alias works as both noun and verb but feels slightly technical. Share is common, intuitive, and already used in Rust (&T is a “shared reference”). The share() method reads naturally: “share this value with the closure.”

Why not just make cloning automatic?

Some applications genuinely need to track where aliases are created—for performance debugging, memory leak investigation, or APIs like Arc::make_mut. Making everything automatic would serve high-level apps well but fail the “low-level enough for a kernel” test. Our approach keeps aliases visible while reducing boilerplate. Once this is done, we will evaluate whether to continue with further changes.

How does this relate to RFC #3680?

RFC #3680 proposed .use syntax and a Use trait. That work remains available on nightly and informed our thinking. This goal represents a refined direction based on community feedback and deeper exploration. The Share trait is similar in spirit to Use but with clearer semantics; move expressions address similar problems to use || closures but generalize more naturally.

rust-lang/rust-project-goals#107: https://github.com/rust-lang/rust-project-goals/issues/107

Case study for experimental language specification, with integration into project teams and processes

Metadata
Point of contactJack Huey
StatusProposed
Tracking issue
Zulip channelLikely a combination of #t-types and #t-spec
lang championJosh Triplett
types championJack Huey
Teamslang, spec, types
Task owners(none)

Summary

Create an experimental/nightly version of a language specification, based on a branch of the Rust Reference with the addition of stability markers and corresponding tooling. Develop and refine processes around it. (This could theoretically use the Reference directly, but for experimentation purposes it likely makes sense to make it a separate repository, depending on how we can best implement and experiment with this new process without gating on its adoption.)

Do an N=1 case study using the types team as the exemplar, on what it would look like to integrate this with the processes of various teams, with extensive documentation to facilitate scaling this to other teams of domain experts within the project. This case study would include:

  • The handling of proposed changes that fall within the purview of that team, where the types team would review the proposed content.
  • The handling of changes from that team, which would be reviewed by other members of the team. This includes ensuring that prospective language changes arising from the work of the team get flagged as needing documentation changes, and the documentation occurs contemporaneously with the language changes.
  • How and when to merge text with unstability markers (whether “unstable text” or “unstable Rust feature”), and what process to follow to review and remove the markers so that text is considered stable.

As a case study, we can use current work on const generics, RTN, or const traits. All of those would heavily overlap with the purview of the types team. (Lang would make design calls on the feel of the language, but the detailed semantics and recommendations typically fall under the types team.)

This goal may potentially align with separate work to improve lang processes, but that work would not be part of this project goal.

This goal will collaborate with the goal to integrate a-mir-formality into language specifications, though neither goal will block on the other.

Motivation

The status quo

Currently, there is no established process for teams of domain experts within the Project to document prospective language changes within their domain, or to check in at an early point about prospective changes within their domain that may have a language-level impact requiring documentation.

Often, such changes may take place primarily on the language side, and end up with documentation as a subsequent step beginning after the language change has been decided and largely completed. Yet, the documentation would potentially serve to facilitate the change; since such documentation will be needed anyway, the documentation could potentially precede the change.

Conversely, proposed changes within a given domain typically go through review cycles with non-domain-experts, rather than being systematically reviewed and approved by domain experts.

What we propose to do about it

Experiment with, and iteratively refine, processes for documenting changes within a domain, and processes for reviewing such changes.

Work with the types team as an N=1 case study of a Project team. Use one or more specific language improvements (e.g. const generics, RTN, or const traits) as a case study for larger changes to review, with the active cooperation of one of the leads for one of those language improvements.

This experiment will necessarily involve a fast, iterative process that’s amenable to delegation. Conducting the experiment may involve creating a nightly repository for integrating Reference work, in order to facilitate this iterative approach.

Part of this process includes the process for stabilizing for removing the instability markers from the text and declaring it stable.

One output of this goal will be clear periodic reporting of “how the experiment is going”.

Work items over the next year

Sketch out the specific things you are trying to achieve in this goal period. This should be short and high-level – we don’t want to see the design!

TaskOwner(s)Notes
Develop and iterate on processJack Huey, Josh TriplettIncremental, iterative.
Implement experimental process within types teamJack Huey
Provide clear process documentationJosh Triplett, Jack Huey
Work with new process as part of shipping a language featureVariousVaries by the language feature.
Start conversations with other domain-expert teamsJosh Triplett, Jack HueyFor instance, wg-const-eval, compiler, opsem
Provide experimental reference repositoryJosh Triplett, Jack Huey
Develop tooling/infrastructure as neededJosh Triplett, Jack Huey

Team asks

TeamSupport levelNotes
typesMediumEvaluate potential changes to (experimental) reference in routine team decisions
langMedium
specSmallGeneral discussion on how this may align with other efforts to specify Rust.

This goal will also coordinate discussions with lang-docs in a non-blocking fashion, to ensure that different sources of Rust documentation are clearly delineated in a manner that avoids confusion, both in source repositories and in any rendered versions.

Frequently asked questions

Will this experiment take a year?

Hopefully not. If the experiment iterates to a successful conclusion successfully earlier than that, we could work with additional Rust teams to adopt it further.

What is the distinction between the types of contributions? What are some examples?

Some changes originate from elsewhere within the Rust Project or the Rust community, and fall within the purview of a team of domain experts. For instance, a proposed change to the Rust type system (whether standalone or as part of a larger change) would fall within the purview of the types team. For such a change, the types team would review and approve the documentation of the proposed change.

Some changes originate from within a team of domain experts. For instance, the types team has been steadily working to make the Rust type system simpler and more robust, while maximally preserving compatibility (bolstered by crater runs). Such work typically involves changes to the language, and such changes require corresponding documentation. For such changes, the types team would review and approve the documentation of the proposed change; since the types team may also have been the on to write the change, this means the process must take particular care to maintain the constraint that the review and the author must be different people.

In both cases, the lang team would also benefit from such documentation to precisely explain the change being proposed.

Field Projections

Metadata
Point of contactBenno Lossin
StatusProposed
RoadmapBeyond the &
RoadmapRust for Linux
Tracking issuerust-lang/rust-project-goals#390
Zulip channelt-lang/custom-refs
lang championTyler Mandry
types championRémy Rakic
compiler championDing Xiang Fei
Teamscompiler, lang, libs, libs-api, opsem, types
Task owners(none)

Summary

We aim to explore and refine the virtual places approach for field projections, document its design and interactions in the beyond-refs wiki, implement it as an experiment in the compiler, and prepare RFCs based on the findings.

This is a continuing goal, see the goal document of the previous period for historical information.

Motivation

Field projections aim to provide a uniform and ergonomic way to produce pointers to fields for custom pointer types. This mirrors the operation on built-in references available today: &x.field is of type &Field given that x: &Struct. This project goal aims to make this feature generally available for all custom types and implement it for &mut MaybeUninit<T>, NonNull<T> and many more.

This feature will reduce verbosity and increase ergonomics when working with custom pointer types. It also enhances expressiveness, as it provides native borrow checker integration and allows the simultaneous usage of pointers to disjoint fields of the same struct.

The status quo

There are many examples for types that can take advantage of field projections. In its current form the design is a generalization of Deref that provides an umbrella abstraction for pointers to virtual places. As the name suggests, these places do not really need to exist, so struct MyStruct<T>(PhantomData<T>) is supported by our approach. Naturally any type that implements Deref is supported; but also types that cannot implement it, such as raw pointers, NonNull<T> and many more are covered.

In the previous goal period, we held a design meeting about the general approach to designing a solution. In it we also extensively covered many use-cases. Here is a non-exhaustive list of types that would benefit from this feature:

  • &mut MaybeUninit<T>,
  • cell::Ref[Mut]<'a, T>
  • NonNull<T> and *{const,mut} T
  • pyo3::pycell::PyRef[Mut]<'_, T>
  • Cpp[Mut]Ref<T>
  • &[mut] Cell<T>
  • &Atomic<T>
  • ArcRef<T>
  • VolatilePtr<'_, T>
  • &[mut] Untrusted<T>
  • SeqLockRef<'_, T>
  • UserPtr<T>
  • Ptr<'_, T>

We also want to note that another contributor separately (without being aware of the field projection effort) created an ACP for ArcRef<T>. Another wanted to introduce swift’s keypath feature to Rust, which is very similar to a part of field projection.

What we propose to do about it

The last goal period resulted in a new approach for field projections called virtual places. It allows customizing place operations via traits: PlaceRead, PlaceWrite, PlaceMove, and most importantly PlaceBorrow. We are missing some interactions, concrete details and a comprehensive document on this design, but the overall idea is solid. It is also much too complicated for a project goal. As part of the goal, we are writing a wiki to better explain all of the interactions with other Rust features.

Here is an example on how the current approach could look like for improving the ergonomics of NonNull:

#![allow(unused)]
fn main() {
struct Struct {
    field: Field,
}

struct Field {
    accesses: usize,
}

impl Struct {
    unsafe fn reset(this: NonNull<Self>) {
        // We can borrow using `NonNull` directly:
        let field: NonNull<Field> = unsafe { @NonNull (*this).field };
        // Note that we can omit the dereference.
        // We can also use the canonical borrow, which fills `NonNull` for us:
        let field: NonNull<Field> = unsafe { @this.field };

        // We can also borrow using a totally different pointer if that is
        // supported by the underlying type:
        unsafe { std::ptr::write(@raw mut (*field).accesses, 0) };

        // Alternatively, we could also just have written to the field directly:
        unsafe { field.accesses = 0 };
        // Note that this drops the previous value, which does nothing for `usize`.
    }
}
}

Field projections is not limited to low-level constructs like raw pointers. It can also help with smart pointers like ArcRef<T>: ArcRef<T> is like an Arc<T>, but with separate pointers to the data and the refcount. This allows us to offset the data pointer and produce ArcRef<Field> from ArcRef<Struct>.

#![allow(unused)]
fn main() {
impl Struct {
    fn get_accesses(self: ArcRef<Self>) -> ArcRef<usize> {
        // Again, we use the canonical borrow. Also note that we can
        // go through any number of fields in one borrow operation.
        @self.field.accesses
    }
}
}

The design axioms from the last period still apply and are fulfilled by the virtual places approach:

  • 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>.

Work items over the next year

TaskOwner(s)Notes
Establish a working group for field projectionsTyler MandryThe group should start out with the members: Benno Lossin, @Nadrieril, Tyler Mandry, Ding Xiang Fei. Any contributor is welcome to join if they intend to develop and design field projections.
Explore and map the solution spacefield projection working groupDiscussions in t-lang/custom-refs & meetings with members of the working group
Document the design in the wikiBenno LossinWrite it down in RFC-style, to easily extract RFCs or design meeting documents from the wiki.
Formalize the borrow checker integration in a-mir-formalityBenno Lossin, Rémy Rakic, Niko MatsakisVerify our work formally and explore the algorithms needed for implementing it in the compiler
Implement a compiler experimentBenno Lossin, Ding Xiang Fei, Oliver SchererEvaluate our current approach by creating an experiment to try out in real code. Implementers: Benno Lossin & Ding Xiang Fei; Reviewer: Oliver Scherer
Draft RFCsTyler Mandry, Benno LossinExtract the knowledge from the wiki & provide historical context as well as rationale and a contiguous & comprehensive story.

Success metric: This project goal will be successful if it can significantly advance the design and knowledge on how to implement field projections in Rust; part of that is creating a compiler experiment in nightly. If we are able to accept the required RFCs, then we have over-achieved our goal. A major setback would be if we discover the current approach untenable or find other blockers that prevent making meaningful progress in the design and experiment.

The “shiny future” we are working towards

Field projections is part of a larger idea called beyond references. There should be no built-in types in the Rust language that a library could not recreate. For example, a user should be able to implement a MyBox<T> that allows moving in and out, supports unsizing, coercions and borrowing the contents using references. Field projections enable that last feature as well as the moving out support. Ultimately, using any library declared type should feel as if it was built into the language itself. In this future, no significant compiler magic exists for references and they can be fully implemented in core.

Team asks

TeamSupport levelNotes
langLargeAiming for two design meetings; large language feature
compilerMediumReviews of big changes needed; also looking for implementation help
typesMediumCollaborating on a-mir-formality on the borrow checker integration; small reviews of RFC and/or compiler PRs
libsSmallSmall reviews of library PRs (implementing FP for core & std types)
libs-apiSmallReviews of RFC
opsemSmallSmall reviews of RFC and/or compiler PRs

The lang team support level is Large, since we could end up with an RFC review and decision at the end of the year. If not, then the input from t-lang is much more manageable and more in-line with Medium: the design meetings and the champion suffice as support.

Frequently asked questions

Project goal - High-Level ML optimizations

Metadata
Point of contactManuel Drehwald
StatusProposed
Tracking issue
Zulip channelN/A
lang championTC
compiler championOliver Scherer
Teamscompiler, infra, lang
Task owners(none)

Motivation

The status quo

rustc does an excellent job generating efficient llvm-ir, competing with languages like C++ or Fortran. Over the last years, we also started leveraging LLVM based automatic differentiation and gpu support. std::autodiff just got enabled in nightly, and std::offload wil soon follow once we update rustc to LLVM 22. We will develop further LLVM optimizations targeting offload performance in Rust, and we will continue to accept gsoc students for both projects, to grow the maintainer pool. After having worked on the autodiff frontend for 5 years, the offload frontend for 1 year, and both projects landing in nightly, I feel like this is a good moment to slow down on frontend changes for both projects, and give users a chance to catch up, test it, and provide feedback. At the same time, we can start thinking about future paths to stabilization, see Work item 3) and the FAQ [2] for details.

Together, those two projects should enable projects in the fields of high-performance computing and scientific computing, which rely on GPU support and or gradients for their workloads. However, there is still a big piece missing, which is especially relevant for Machine Learning workloads: Tensor/Matrix optimizations. I care about three specific aspects here:

  1. Run matrix operations on accelerators (e.g. TPUs, Trainium/Inferentium, LPU, etc.)
  2. Recognize individual high-level matrix operations (e.g. matmul, conv2d, etc.) in code, and replace them with more efficient implementations.
  3. Optimize sequences of high-level matrix operations, e.g. by reordering, fusing, or replacing them.

Accelerator vendors often see MLIR as the expected input format for their hardware. MLIR also has various dialects which are suitable to represent and optimize these high-level operations. LLVM has Polly as a subproject which also targets higher-level optimizations, but it is more limited as discussed in the FAQ. MLIR on the other hand has it’s own challenges, mainly related to a higher development speed and few stability guarantees.

What we propose to do about it

We are working towards a shiny future where developers are able to develop full ML models in pure Rust. Based on their available hardware, training can happen on GPUs, other accelerators like TPUs, or if desired, still CPUs. Developers don’t need to think about “gradients”, “derivatives” or a “reverse pass”, since in all cases the std::autodiff module can compute the gradients needed during the training for them. Beyond that, users can write their inference or training logic only considering a single training example, since the compiler can automatically batch their code for them, to enable vectorization or improve throughput.

We want to explore the possibility of building an MLIR based backend for rustc. This MVP intentionally limits complexity in some areas, to be able to focus on the hard parts first. We especially intend to limit us here:

  1. Target only one accelerator, since targeting the following ones should be easier. The std::offload project currently only supports AMD+NVIDIA GPUs, but this was enough to motivate a new contributor to reach out and start working on an Intel GPU target. We expect similar effects once we demonstrate how to target the first accelerator via MLIR.
  2. No bikeshedding about which dialects to target. MLIR (Multi-Level IR) lives from its dialects, it is common to raise or lower between multiple dialects in one compilation pipeline to benefit from all of them. Once we lower to one dialect it should therefore be easy to replace that dialect or add additional ones.
  3. No full Rust support. It would be infeasible for one person (plus collaborators) to achieve this in one year, but it’s also not needed, since most of the ML runtime will be focused around a quite limited set of operations.

We instead intend to tackle these hard problems first:

  1. Get the full infrastructure up. Previous experience from Enzyme and LLVMs Offload integration should help here.
  2. Enable splitting the compilation between the MLIR accelerated part and the current LLVM based backend. This has some overlap with std::offload, which uses two compilation passes to compile for the host (CPU) and the device (GPU).
  3. Support MLIR without pushing a full DSL into Rust. Targeting MLIR could be comparably easy if we would require the usage of a special Matrix type, and if we add all functions from the chosen MLIR dialects into the standard library. However, blessing one specific matrix implementation prevents competition (see e.g. faer/ndarray/nalgebra). There is also a very large number of MLIR dialects with different stability guarantees, so we would significantly bloat our standard library and might struggle with breaking changes later.
  4. Demonstrate the combination of std::autodiff, std::offload, and the new MLIR backend. We are already able to combine the first two features, but only if we can combine all three we have all the basics needed to support modern ML workloads.

There is a chance that we need to compromise on target 3), but I believe it’s in our best interest to first aim for the best case. In the case of std::autodiff and std::offload we have already demonstrated that its possible to differentiate and offload almost arbitrary Rust code. I hope that we can achieve the same with this goal and even if not, we at least have a full prototype based on which we can start a discussion about which compromises are acceptable.

Work items over the next year

  1. Continue maintaining std::autodiff (whole year).

  2. Support Karol Zwolak who is working on adding a new Intel GPU target, to allow std::offload on all three vendors (AMD, NVIDIA, Intel) (Winter+Spring).

  3. Discuss the memory model of std::offload with the lang team, to identify potential issues and stabilization blockers (whole year, “background task”).

  4. Develop the MLIR prototype (from Spring onwards, main focus). Target one accelerator and accelerate one common instruction (e.g. matmul). Demonstrate one high-level optimization.

  5. Continue growing a contributor team accross Rust and LLVM to maintain std::autodiff, std::offload, and our new MLIR backend (whole year).

Team asks

TeamSupport levelNotes
compilerMediumMy changes should be contained to few places in the compiler. Potentially one frontend macro/intrinsic, and otherwise almost exclusively in the backend.
infraSmallI will work with Jakub Beránek to add more bootstrap options to build and configure MLIR (an LLVM subproject)
langMediumDiscussions to understand which parts of gpu programming and std::offload are problematic wrt. stabilization, from a lang perspective. Non-blocking, since we are not rushing stabilization.

Frequently Asked Questions (FAQ)

Why can these features not be implemented in crates, why does it need compiler support?

A: automatic differentiation must be performed on optimized code (“Intermediate Representation”, IR) to be performant (in the general case). Crates are generally unable to modify their own IR, unless reimplementing parts of a compiler. Further, both autodiff and offload provide their own improvements to the LLVM optimization pipeline, used by the Rust compiler. Both projects further rely on various unstable compiler internals (e.g. the layout of non-repr-C types).

A: The basic features discussed (autodiff, batching, gpus, kernel optimizations) are common accross ML Compilers/Frameworks in Rust and other languages. Examples are PyTorch, JAX, Burn and Candle (Rust) and Reactant.jl.

Rust did not provide any of the required features so far, forcing Rust ML projects like Burn or Candle to call out to other languages or even reimplement aspects of a compiler, without having the full features available that we can use within rustc. Based on these limitations, their autodiff implementation is (based on previous communication) not competitive on general scientific or HPC code (like e.g. measured by ADBench). Their GPU and autodiff implementation are further tied to their own Tensor type, which significantly limits it’s reusability within the larger crates ecosystem. If we as Rust compiler start providing these features, ML framworks don’t have to keep re-implementing gradient computations anymore, won’t need to call other languages, can provide consistently good/better performance over a larger area of workloads, and interoperate better with other crates by not having to enforce the usage of specific types or traits.

Request A: Better compile time support. Users should be able to enforce that certain code sections are evaluated at compile time. This can give peace of mind to developers who want to ensure that within hot code sections, some expressions are already evaluated at compile time. It can further prevent bugs if developers can enforce that certain constraints (e.g. matrix dimensions) at compile times.

Request B: Better compile times. Training a Neural Network from scratch is going to overshadow any compile times. However, common workflows also include using a pre-trained model and tinkering with it (e.g. postprocessing some output, printing or visualizing it, updating only parts of your surrounding simulation, etc.). Such tasks are usually done in an interactive language like Python or Julia. How close can we get our compile times to such Interpreted/JIT uses? Promising candidates are Wild (a parallel linker), TPDE (a faster LLVM debug backend), the parallel Frontend/Macro Expansion, and others.

Request C (optional): The Reflection proposal might be one potential path to stabilize the autodiff and offload projects by “outsourcing” it into common crates, if we decide to previde the necessary abilities via a future reflection implementation. We should sync up!

What are the paths towards stabilization?

A) std::offload. This project is based on LLVM’s upstream offload/openmp project, which are sufficiently tested via C++ and Fortran. It also seems reasonable to support it in the GCC backend in the future. While we want to give nightly users plenty of time to test this feature and provide feedback, we also will start a discussion with the lang team to identify and hopefully remove potential stabilization blockers. We do not intend to request a stabilizatoin during this Project Goal Period.

B) std::autodiff. This project is based on an LLVM incubator project and not part of upstream LLVM yet. It is also heavily research focused, so we expect more bugs than in the std::offload project. Before discussing stabilization, we therefore want to explore paths to improve the reliability of this project. Potential paths forward include working with Enzyme developers to achieve better support with bugfixes affecting Rust, training Rust developers to improve Enzyme, or understanding that reimplementing a smaller and more production focused AD tool in the style of Enzyme (based on a potential LIR) is the most efficient path forward.

C) Both: the autodiff and offload project both can offer performance or features that are not achievable by normal crates. What if we focus on enabling normal crates to implement this type of project, instead of adding them to the library? We currently require certain abilities like looking up the layout of unstable types, or rewriting the backend representation (LLVM-IR) of certrain functions and objects. We expect that such abilities could be helpful beyond our projects. While it’s beyond the scope of the reflection MVP, we will also reach out to that project to discuss enabling these abilities for normal crates. Such advanced reflection would enable “outsourcing” autodiff and offload from the standard library into normal crates, which then would not need to follow the traditional stabilization paths. It would however introduce new problems, for example each crate release would be tied to specific Rust compiler versions, due to the LLVM version vendored by rustc.

Improve rustc_codegen_cranelift performance

Metadata
Point of contactbjorn3
StatusProposed
Tracking issue
Zulip channelN/A
Contingent onFunding
Teamscargo, compiler
Task owners(none)

Summary

This goal aims to improve the rust development experience through faster incremental code generation with rustc_codegen_cranelift. We additionally want to fix several long-standing bugs that currently prevent rustc_codegen_cranelift from being used for popular crates.

Contingent on funding: This goal is contingent on finding funding for this effort.

Motivation

The status quo

Rust compilation is slow, and despite constant monitoring and gradual improvement of rustc’s performance, the developer experience has not materially improved in recent years.

The rustc_codegen_cranelift backend has the potential to substantially improve incremental code generation time. It already outperforms the LLVM backend, but so far has not yet (fully) delivered on its promise of improving the development experience.

In local benchmarks on a 16-core machine, as of February 2026, measuring start-to-finish incremental compilation time of Zed:

  • with -Cdebug-info=none, cranelift is 5% faster than LLVM
  • with -Cdebug-info=line-tables-only, cranelift is 12% faster than LLVM

The amount of debug information is relevant. -Cdebug-info=line-tables-only is the most common during development: it provides information for detailed backtraces, but does not emit the detailed information that is useful when stepping through a program with a debugger.

With -Cdebuginfo=line-tables-only the performance benefit of the cranelift backend varies between negligible and ~30% with the average speedup around 10-15% for a single crate compilation in the rustc benchmark suite.

What we propose to do about it

We want to explore ambitious ways to substantially improve the speedup that the cranelift backend offers over LLVM, thereby increasing the utility of rustc_codegen_cranelift.

Possible projects are:

  • A persistent daemon that caches the machine code of individual compiled functions in-memory, eliminating serialization overhead with respect to caching individual functions on disk.
  • Using just-in-time (JIT) compilation for functions as they are called.
  • Interpreting Cranelift IR rather than compiling it for functions that are called infrequently.

Stability & Usability improvements

We additionally want to fix several long-standing bugs that limit rustc_codegen_cranelift’s usability today. In particular:

Work items over the next year

TaskOwner(s)Notes
Stability/usability improvementsbjorn3
Investigate ways to speedup rustc_codegen_craneliftbjorn3

Team asks

TeamSupport levelNotes
cargoSmallIn case we end up pursuing JITing as a way to improve performance that will eventually need native integration with cargo run. For now we’re just prototyping, and so the occasional vibe check should be sufficient
compilerMediumDepending on what ways we end up pursuing, we might need no rustc side changes at all or medium sized changes.

Frequently asked questions

In-place initialization

Metadata
Point of contactAlice Ryhl
StatusProposed
RoadmapBeyond the &
RoadmapRust for Linux
Tracking issuerust-lang/rust-project-goals#395
Zulip channel#t-lang/in-place-init
Teamslang
Task owners(none)

Summary

Evaluate the different approaches to in-place initialization and, together with the lang team, align on a recommended approach.

Motivation

The status quo

There are multiple projects that are running into various problems that can only be solved using a mechanism for in-place initialization. Each project has implemented their own independent and slightly different solution in external crates relying on complex macros at the cost of ergonomics.

It’s time to learn from the extensive amount of experimentation in the ecosystem and create a language feature that provides a shared solution that can be more ergonomic than what is possible in an external crate.

What we propose to do about it

A lot of the work that has happened over the last goal period has been various forms of discussion: >60 zulip threads in the #t-lang/in-place-init channel, many discussions over video call, and long conversations in-person at conferences. There are a few different “classes” of approaches that have come up in these discussions. I want to see each “class” of solution written up in a doc, perhaps using the RFC format, so that we can compare them without having to read through long conversation threads.

For this purpose, we have created a section on the beyond-refs wiki that can hold proposals in one place. We are also planning a workshop at the All-Hands.

At the end of the goal period, we would like to land a design space RFC. The goal of this RFC is to describe the design space and the tradeoffs of different solutions. If the lang team accepts this RFC, then this implies that the lang team agrees with the characterization of the tradeoffs. The RFC may also make an opinionated recommendation / narrow down the design space, but this is not required.

Work items over the next year

TaskOwner(s)Notes
Prepare design RFCAlice Ryhl, Benno Lossin, Yoshua Wuyts
Organize all-hands workshopBenno Lossin

Team asks

TeamSupport levelNotes
langMediumReview and accept a design space RFC

Incremental Systems Rethought

Metadata
Point of contactAlejandra González
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler
Task owners(none)

Summary

Design, propose, and implement a redesign of the incremental system to allow for shared common bases between different Rustc invocations with different arguments (i.e. cargo build and cargo check)

There’s already an on-going RFC, based on this blog post and talk by the same author (and this project goal’s point of contact) As my other project goals, this is a formalization of an already existing effort.

Motivation

The incremental system (i.e. the system that takes care of reusing the dep-graph and keeping track of changes on compiler invocations) does not take into account inter-activity communication. So, cargo build and cargo check, while they share a lot of common meaning and thus should share much in a perfect incremental system, in reality trigger a recompilation if performed one after the other.

This project goal will design, propose and implement the necessary changes for check, build and possibly some 3rd-parties such as clippy to share a common incremental ground when performed in a compatible way.

So, when a user runs cargo check and then cargo build, cargo build would reuse much of the work done by cargo check. cargo check and cargo clippy (if implemented) would also reuse a lot of work. cargo build and cargo test could also reuse some e.g. parsing information

The status quo

Quoting from the earlier mentioned RFC:

The current model for incremental recompilations doesn’t share progress between compiler activities, leading to unnecessary rebuilds. Users notice redundant compilations, as “Changes in workspaces trigger unnecessary rebuilds” was submitted as a big complaint in the compiler performance.


This affects all users that use a typical cargo check -> cargo build -> cargo test workflow. Even on codebases that don’t use e.g. cfg(test) or similar profile-based cfg attributes, it will rebuild the workspace 3 times.

Summing to the already slow compilation times, having to rebuild the workspace on every different command is a pain point discovered in the performance survey.

The next 6 months

Over the next 6 months the plan is to address all review comments and concerns on aforementioned RFC and via working with the compiler team, merge an unstable initial implementation on the compiler. This implementation would introduce a working base system where a cargo build -> cargo check workflow does not recompile.

After those 6 months, we’ll focus on less systematic improvements. We’ll work on starting the stabilization process and hopefully get it close to the finish line. In the stabilization process, we’ll try to make the API as expandable as possible to allow for granularity in the recompilation tracking.

TaskOwner(s)Notes
Design, proposeAlejandra González Jack Huey
ImplementationAlejandra González
ChampionJack Huey

The “shiny future” we are working towards

The end goal is to allow for smoother work-reutilization between compiler invocations with little to no overhead. With dynamic dependencies declaring which compiler flags are sensitive for the current codebase recompiling, and keeping an accurate track of macro invocations and a real and specific sense of which functions from dependencies the current crate depends on.

The shiny future, and the end goal of the whole roadmap is to avoid the following scenarios:

  • Full recompilations on cargo check -> cargo build on all scenarios. (Some will need it due to e.g. build scripts, but the majority don’t)
  • Recompilations at all on cargo build -> cargo check
  • Recompilations due to changes in unused functions from dependencies.
  • Recompilations due to CLI flags that don’t affect the current invocation (e.g. -Clto on cargo check)

The first step is completing the RFC and implementing it in an unstable stage.

Team asks

TeamSupport levelNotes
compilerMediumChampion: Jack Huey

Frequently asked questions

Interactive cargo-tree: TUI for Cargo’s dependency graph visualization

Metadata
Point of contact@orhun
StatusProposed
RoadmapBuilding blocks
Tracking issue
Other tacking issues#11213, #15473
Zulip channel[TUI for Cargo]
Teamscargo
Task owners(none)

Summary

The goal is to build an interactive terminal UI for Cargo’s dependency graph visualization based on the [cargo-tree] command.

Motivation

Cargo’s tree command is one of the crucial tools for Rust developers to understand their project’s dependency graph, debugging version conflicts and analyzing the features used in dependencies. While the current command-line interface exposes this information accurately, it is still difficult to explore large or complex dependency graphs due to the lack of interactivity. For example, users pipe the output of [cargo-tree] to other tools like less or grep to filter or search for specific dependencies, which can be cumbersome and time-consuming. Also, as the Rust ecosystem continues to grow, the complexity of dependency graphs is increasing, making this workflow even more challenging.

This project goal aims to improve the experience of exploring dependency graphs by introducing an interactive mode for the [cargo-tree] command. This interactive terminal UI will allow users to perform dependency graph operations using key bindings. These operations will be aligned with the existing command-line interface of [cargo-tree], such as focusing on a specific dependency, but will not be limited to them. With the additional capabilities and visual improvements provided by this TUI, users will be able to navigate and analyze their dependency graphs more effectively.

The status quo

The primary audience for this work is Rust developers working on medium to large projects, especially those dealing with:

  • deep dependency trees with many transitive dependencies,
  • version conflicts and duplicate dependencies,
  • complex feature sets across multiple dependencies,
  • and different dependency types in a workspace context.

Today, these developers struggle to efficiently use the existing [cargo-tree] CLI due to:

  1. The static output: once it’s printed, it cannot be interactively explored.
  2. Linear navigation: large trees require scrolling or piping to a pager.
  3. Iterative workflow: users frequently re-run the command with different flags (--invert, --edges, --target, etc.) to get answers.

These struggles were reflected in multiple issues (#11213, #15473) and the discussions suggested that an interactive terminal UI could address these pain points.

The next 6 months

The goal for the next 6 months is to design and implement an interactive terminal UI for dependency graph visualization as an alternative to the existing [cargo-tree] command. In the long term, this could be shipped as a part of Cargo and would be invoked with a command-line flag, but the initial prototyping and validation will be done externally in the [cargo-tree-tui] repository.

TaskOwner(s)Notes
Implement basic interactive tree@orhunalready done in [cargo-tree-tui]
Match [cargo-tree] semantics@orhun[cargo-tree-tui#4]
Improve the UX & styling@orhun[cargo-tree-tui#8]
Directly depend on cargo as dependency@orhunThere might be some upstream APIs need to be changed
Optimize for performance@orhun[cargo-tree-tui#37]
Prepare for inclusion in Cargo@orhunIntegration and documentation work

The “shiny future” we are working towards

The long-term goal is to make it easier to explore dependency graphs and letting Rust developers gain insights about their dependencies more effectively.

In this future, it will be easier and quicker to get answers to questions like:

  • Why is this dependency present? What is bringing it in? / What is it bringing in?
  • Where is the version conflict happening? / How can I resolve it?
  • Why is my dependency graph so large? / How can I reduce it?

without repeatedly re-running commands or restructuring their queries.

In the distant future, implementing this would open up possibilities for adding an interactive mode for other commands in Cargo as well.

Team asks

TeamSupport levelNotes
cargosmallAlignment on direction, possible integration help and review.

Frequently asked questions

n/A

#11213: https://github.com/rust-lang/cargo/issues/11213 #15473: https://github.com/rust-lang/cargo/issues/15473 [TUI for Cargo]: https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/TUI.20for.20cargo [cargo-tree]: https://doc.rust-lang.org/cargo/commands/cargo-tree.html [cargo-tree-tui]: https://github.com/orhun/cargo-tree-tui [cargo-tree-tui#4]: https://github.com/orhun/cargo-tree-tui/issues/4 [cargo-tree-tui#8]: https://github.com/orhun/cargo-tree-tui/issues/8 [cargo-tree-tui#37]: https://github.com/orhun/cargo-tree-tui/issues/37

C++/Rust Interop Problem Space Mapping

Metadata
Point of contactJon Bauman
StatusProposed
Tracking issuerust-lang/rust-project-goals#388
Zulip channelt-lang/interop
compiler championOliver Scherer
lang championTyler Mandry
libs-api championDavid Tolnay
Teamscompiler, lang, libs-api, opsem
Task owners(none)

Summary

Document a set of technical issues related to C++/Rust interoperability with broad community consensus to serve as a starting point for proposed solutions and facilitating cooperation among stakeholders in both language communities.

Motivation

C++ has been a leading systems language for most of its 40 year history. There are billions of lines of code representing trillions of dollars of value stored in C++ codebases. In domains where systems languages are required, there are very few options and even fewer with the safety properties of Rust. In the near term, it is neither feasible, nor advisable to rewrite a significant fraction of the C++ actively used today. Empirical studies have shown significantly more benefit in writing new code in memory-safe languages. This makes enabling Rust development within C++ codebases essential, and doing so requires high-performance, safe, ergonomic interop.

There are many challenges to this kind of interop, and they can be solved in many different ways. To the extent that discrete problems within the interop space can be solved in a shared way, both communities stand to benefit, but thus far there has been relatively little progress in implementing solutions other than external libraries, each of which typically have their own approach, requiring significant investment for end users. To build better solutions to foundational interop problems that may require changes to the standard libraries, toolchains or the languages themselves, we will first clearly and rigorously define the individual problems and solution requirements with input from experts from both languages including implementors of compilers and standard libraries. Achieving consensus in defining the problems will facilitate the creation and discussion of proposed solutions with the appropriate stakeholders and improve the chances that solutions succeed in broadly benefiting interop consumers.

The status quo

C++/Rust interoperation is an incredibly broad problem space owing to the fact that the C++ language has been continuously developed for 40 years and has actively maintained implementations on numerous architectures and several different toolchains. Furthermore, the requirements of interop consumers varies according to the application as well as constraints on compilers and C++ language versions. Neither Rust nor C++ has language- or standard library-level support for direct interoperation. Instead, the C system ABI is used as the lingua franca for directly calling into the opposite language. While there are ways to achieve cross-language interoperation an a language-agnostic fashion, such as interprocess communication, this proposal is concerned with high-performance, FFI-based interoperation. This is required in performance-critical domains where Rust and C++ are among the few viable language choices and the problems for this kind of interoperation may benefit from coordinated changes in both languages. For more on the domain of interest, see the C++/Rust Interoperability Problem Statement.

Currently there are a variety of approaches to this kind of interop from tools like bindgen and cbindgen which automate only the creation of type and function declarations for FFI calls, to higher-level approaches like cxx, crubit and zngur, which provide varying levels of automation to handle both binding generation and sharing of data across the FFI boundary. All differ in the specifics and though there are many elements to their approaches which are similar, they do not share any common foundation and each builds a solution supported only by the very limited facilities of Rust and C++ to declare functions and data which are compatible with the C system ABI.

Different use cases and priorities account for part of the reason there are a variety of tools. For interop that is limited to well-defined module boundaries and can exploit existing C API which are not too large, the bindgens often suffice, but sacrifice safety and ergonomics. Tools like cxx and zngur provide higher levels of abstraction and safety, but require the user to define an IDL-like interface boundary. Finally, crubit strives to be a universal tool and automatically expose all interfaces to the opposite language which entails considerably more complexity and deep integration with the build system, so it is not yet viable for general purpose use.

In the first year of the C++/Rust Interoperability Initiative, I’ve engaged with many of the parties interested in interop and facilitated direct interactions with members of the Rust Project, WG21 (the C++ ISO standardization committee) and several large tech organizations. I believe for the foreseeable future, there will be multiple approaches to interop, but owing to the very primitive language-level support all these tools are built upon, there is a significant space of shared problems which can benefit from collaboration and shared solutions. Especially when it comes to changes at the language-level, there is a heightened standard for broad utility, and coordinating work across languages with very different evolution processes will require a clear understanding of the specific problems and expert insight regarding the feasibility and impact of changes to the standard libraries, toolchains and core languages. As a member of the Rust Foundation, and a representative to WG21, I’m well-positioned to coordinate these efforts. Having seen first-hand the difficulty in agreeing on solutions and the overwhelmingly large subject area required to understand them, I think the next step is to focus on clearly defining and documenting the problems themselves. This will help identify the areas of potential cooperation, facilitate input from interested parties who may otherwise lack the full context, and sets the stage for solutions to be proposed and refined into concrete, cooperative work that may occur in a multitude of venues, including the Rust Project, WG21, LLVM or elsewhere.

What we propose to do about it

There has already been a significant discourse on the problems related to interop, but it remains diffused across the web, Zulip and other less-accessible media. Furthermore, the vast majority of this material is in the form of advocating for one tool or approach and typically comes from the perspective of a particular user or organization with specific needs and interests. During this goal period, I will organize as much of it as I can into discrete problem statements which will describe the challenges, prior attempts and current approaches and desired solution properties, but without proposing specific solutions. These will be collected under the interop initiative repo, and I will both accept and solicit input from relevant experts. The goal is achieving consensus around what the problems themselves are as objectively as possible, so parties interested in proposing, reviewing or implementing solutions can organize around the issues of relevant interest and expertise and optimize for shared solutions.

Looking further ahead, a well-defined map of the discrete problems in the interop space will allow for the creation of discrete solution proposals, which can be refined and debated by interested members of both the Rust and C++ communities and eventually turned into Rust RFCs, WG21 papers, change processes targeted at other relevant communities such as LLVM, or direct code contributions. There are already many such items of work in process such as arbitrary self types, pin ergonomics or trivial relocatability, and in the shiny future, the problem space map would elucidate the connection between such work and the problems it addresses. This would serve as the central point of collaboration between the two communities to understand the interop-related challenges and work together efficiently. Interested parties can find the problems that are relevant to them (or help define them if they are missing) and then…

  • find the shared problems and work with other interested parties towards a shared solution
  • accept with clear reasoning when different solutions are required for a shared problem
  • not waste time engaging about problems that aren’t relevant to them

Given the large investment and long time frames involved in language-level changes, it’s particular valuable to have a solid grounding in the problem itself. This space could also grow into a shared community to help determine and facilitate the process of implementing solutions, whether they be creating RFCs, WG21 proposals or something else.

Design axioms

Problem statements should…

  • define the impact, consequences and acceptance criteria for solutions
  • reference prior solution work, but without proposing or analyzing solutions
  • be based objective facts supported by expert opinions and generally strive to be informative and uncontroversial
  • provide a high-level explanation for engineers who aren’t experts in the cause, but are likely to experience the impact
  • provide references to additional background information

Work items over the next year

The output will be an interop initiative repository containing discrete problem statements.

TaskOwner(s)Notes
Author problem statementsJon Bauman

Team asks

Fundamentally, this goal is about organizing knowledge in a useful way. I will be primarily responsible for collecting and structuring it, but do not intend to do original analysis since there are greater experts to defer to. The most valuable participation from Rust teams will be in reviewing the accuracy of the collected information. I do not expect the burden to be great since the individual problems are intended to be narrowly scoped and reviewers will be experts in the domain. Demands will depend on the specific problems documented and the teams that are deemed relevant

TeamSupport levelNotes
compilerSmallReviews
langSmallReviews
libs-apiSmallReviews
opsemMediumProblem statement review

Frequently asked questions

Is this intended to be a living document or a snapshot in time?

A living document. It’s unlikely to ever be complete, especially considering both Rust and C++ continue to change, but since one of the main points of the document is to attract more input and inspire new solution proposals, openness to change is a feature.

Do you want to be the curator of all content or go for more of a wiki approach?

At least initially (and almost certainly for the lifetime of this goal), I plan to be the sole curator, but I will actively encourage and solicit contributions to ensure the content is as accurate and objective as possible. Over time, additional curators may be added, and at some point it may make sense to transition to a more wiki-like approach if curation becomes a bottleneck, but I can’t say for sure.

How should the problems be prioritized?

At the very beginning, the goal will be breadth: attempt to give a name and basic description to as many of the relevant problems as possible. This will form a sort of skeleton to aid with discoverability and motivate contribution from relevant experts. From there, priority will be given to collecting information that already exists spread across various sources such as meeting notes, conference talks, forum posts and Zulip streams. Problems which are causing people current pain and which have competing solution ideas will be especially prioritized to encourage them to be formalized in response to a common understanding of the problem. Finally, problems which are most likely to have solutions requiring longer-term processes such as RFCs and WG21 papers will be prioritized to get things moving sooner and problems with uncontroversial solutions will be prioritized because we all could use some easy wins.

If you had unlimited time and resources, wouldn’t it be advisable to rewrite all the C++ in Rust?

I don’t think it’s clear that it is! While the risk of UB goes away if you can rewrite it all in safe Rust, there are lots of other kinds of bugs that can occur, and they’re far more likely to occur in new code, so the older and more real-world use code has, the less likely it is to contain bugs, regardless of language.

I notice you wrote “implementors” above. Why not “implementers”?

This bothered me too, and this internals thread explained why it was so noticeable to me (and likely other Rustaceans).

libc 1.0 release readiness

Metadata
Point of contactYuki Okushi
StatusProposed
Tracking issue
Other tracking issuesrust-lang/libc#3248(https://github.com/rust-lang/libc/issues/3248)
Zulip channelN/A
Teamscrate-maintainers
Task owners(none)

Summary

Prepare and ship libc 1.0 by resolving long-standing ABI and API inconsistencies, finishing the new testing infrastructure rollout, and making the policy decisions required for a stable major release.

Motivation

libc is the canonical Rust FFI layer for C libraries and is widely depended on across the ecosystem. It is still 0.2 because there are outstanding ABI mismatches, unsound trait implementations, and unclear policy guarantees that make a 1.0 promise premature.

The status quo

  • On 32-bit targets, time_t and off_t can be 32- or 64-bit depending on C library headers and macro configuration, but libc can only define one variant.
  • Several early mistakes require breaking changes (e.g., iconv, vfork, placeholder constants, incorrect type definitions) and are tracked as breakage candidates.
  • musl 1.2 and time64 support is implemented but it still needs some additional work.
  • Some libc types want anonymous struct/union support that is not yet fully available in stable Rust.
  • GSoC 2025 delivered a modern replacement for the old ctest2 harness, but some issues remain.

What we propose to do about it

Focus 2026 work on the explicit 1.0 blockers in the tracking issue: land targeted breaking fixes, remove inappropriate trait impls, and complete the ctest rewrite. In parallel, we will define and publish libc’s MSRV and platform-support policies to make 1.0’s guarantees clear and durable. We also have to triage the polls on Zulip and address them.

Work items over the next year

TaskOwner(s)Notes
Define MSRV and platform-support policiesYuki Okushi Trevor Gross
Address remaining breaking changes listed in the tracking issueYuki Okushi Trevor Gross
Triage polls on ZulipYuki Okushi Trevor Gross
Complete ctest rewriteAbdul Muiz

Team asks

TeamSupport levelNotes
crate-maintainersSmall

Frequently asked questions

TODO - will fill in based on the review comments

Evolving the standard library API across editions

Metadata
Point of contactAmanieu d’Antras
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler, edition, lang, libs-api, rustdoc, types
Task owners(none)

Summary

Add a mechanism for edition-dependent re-exports which allows the standard library to make larger API changes across editions.

Motivation

The library team is generally very careful about stabilizing new APIs in the standard library because once such an API is stable, it must remain unchanged forever. This is necessary to maintain Rust’s stability guarantees which ensure that rustc is able to compile Rust code from 2015 and that new crates are able to interoperate with old crates.

However there exist several stable standard library APIs which we would wish to change to improve ergonomics and safety, if it were possible. While the library API team is not committed to making any specific change, several changes have previously been discussed:

The exact changes are outside the scope of this project goal and should be discussed elsewhere. This goal is only about giving us the tools needed to potentially make such changes.

The status quo

Currently the only existing tool for making such changes is deprecating the old API and introducing a new one with a similar name. For example, this is what was done with Command::pre_exec and Command::before_exec. However this approach has several downsides:

  • It can often be hard to pick a good alternate name for a function or type since the obvious names will have already been chosen for the original (stable) API. Consider the case of Atomic*::fetch_update which is being deprecated in favor of Atomic*::update and Atomic*::try_update: the original name was arguably better since it clarifies what value is returned.
  • A deprecation is a strong signal that effectively forces every still-maintained crate to update to the new API. This can cause a lot of ecosystem churn as everyone updates to the new API.
  • Deprecated types in the public API of a crate are particularly problematic because migrating to the new API would result in a breaking change which requires a major version bump.

What we propose to do about it

We would like the ability to make larger API breaking changes across editions. To do so we would like to add a mechanism for edition-dependent re-exports. This would allow a single path in the standard library to resolve to different items depending on the edition of the code that is referencing it. For example:

#![allow(unused)]
fn main() {
// std
mod foo {
    struct Bar2024;
    struct Bar2027;

    // Exact syntax for this is not definitive
    #[edition = "2024"]
    use Bar = Bar2024;
    #[edition = "2027"]
    use Bar = Bar2027;
}

// 2024 edition crate
use std::foo::Bar; // resolves to std::foo::Bar2024

// 2027 edition crate
use std::foo::Bar; // resolves to std::foo::Bar2027
}

This would allow for major changes in the standard library API while still allowing for backwards compatibility with older editions since the items used by older editions are still available, just through a different path. Additionally, automatic edition upgrade could automatically re-write paths to use the one for the old item, which ensures that code behavior doesn’t change during the automatic upgrade.

Work items over the next year

TaskOwner(s)Notes
Draft RFCAmanieu d’Antras
Implement compiler supportowner

Team asks

TeamSupport levelNotes
compilerMediumDesign discussions and implementation review.
langSmallReview of the feature and lang implications.
libs-apiLargeDetermine what API changes should be made across editions.
editionLargeReview the feasibility of this proposal as well as the specific API changes.
rustdocMediumFigure out how such API changes should be presented in the API docs.
typesSmallReview of any changes to HIR ty lowering or method resolution

Finish the libtest json output experiment

Metadata
Point of contactEd Page
StatusProposed
RoadmapBuilding blocks
Tracking issuerust-lang/rust-project-goals#255
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
Teamscargo, libs-api, testing-devex
Task owners(none)

Summary

Finish the libtest json experiment.

Motivation

libtest is the test harness used by default for tests in cargo projects. It provides the CLI that cargo calls into and enumerates and runs the tests discovered in that binary. It ships with rustup and has the same compatibility guarantees as the standard library.

Before 1.70, anyone could pass --format json despite it being unstable. When this was fixed to require nightly, this helped show how much people have come to rely on programmatic output.

Cargo could also benefit from programmatic test output to improve user interactions, including

Most of that involves shifting responsibilities from the test harness to the test runner which has the side effects of:

  • Allowing more powerful experiments with custom test runners (e.g. cargo nextest) as they’ll have more information to operate on
  • Lowering the barrier for custom test harnesses (like libtest-mimic) as UI responsibilities are shifted to the test runner (cargo test)

The status quo

The next 6 months

TaskOwner(s)Notes
Experiment with potential test harness featuresowner
Experiment with test reporting moving to Cargoowner
Putting forward a proposal for approvalowner

The “shiny future” we are working towards

  • Reporting shifts from test harnesses to Cargo
  • We run test harnesses in parallel

Team asks

TeamSupport levelNotes
cargoSmall
libs-apiSmall
testing-devexSmallDesign discussions and review

Frequently asked questions

Control over Drop semantics

Metadata
Point of contact@thunderseethe
StatusProposed
Contingent onContributor
Contingent onFunding
Tracking issue
Zulip channelN/A
Teamscompiler, lang, opsem, types
Task owners(none)

Summary

Allow users to easily control the drop semantics of struct fields, letting them change drop order, and disable recursive destructors to make working with cross-language bindings easier.

  • Allow cross-language bindings to expose struct fields without compatibility hazards, and
  • Make all code that disables default destructor behavior more convenient to use in Rust.

Contingent on contributor: This goal needs a contributor to implement a lang experiment in rustc and write an RFC. The work is a focused compiler feature touching drop semantics and destructor codegen. Estimated time commitment: TBD.

Motivation

The status quo

Cross-language bindings for structs with destructors requires using ManuallyDrop today. For example, this struct in C++:

struct RingState {
    Uring ring;
    std::array<UringBuf, 16> buffers;
};

Must be bound in Rust like so:

#![allow(unused)]
fn main() {
#[repr(C)]
struct UringState {
    ring: ManuallyDrop<Uring>,
    buffers: ManuallyDrop<[UringBuf; 16]>,
}
impl Drop for UringState { /* call C++ destructor */ }
}

Otherwise, two things would happen:

  1. The field destructors would be called in the opposite order from the source language. Most systems languages with destructors like C++, ObjC, and Swift drop their fields in reverse order of declaration. This is reversed in Rust. In our example there is a logical dependence between the ring and the buffers, and dropping them in the wrong order leads to errors.
  2. It’s technically undefined behavior, regardless of drop order. To destroy an object in C++, you need to call that type’s destructor instead of recursing into the fields manually.

This is unergonomic to use and prevents normal construction:

#![allow(unused)]
fn main() {
let ring = Uring::new();
let buffers = register_buffers(&ring);

UringState {
    ring: ManuallyDrop::new(ring),
    buffers: ManuallyDrop::new(buffers),
}
// ...vs...
UringState { ring, buffers }
}

With two fields it isn’t so bad, but the cost scales as the struct becomes larger.

One approach to easing this pain is to only use ManuallyDrop when binding fields whose types have destructors. But that presents a compatibility hazard: It would mean adding or removing a destructor from that C++ type becomes a breaking change to Rust code, when it is usually not a breaking change to C++ code.

What we propose to do about it

Proposal 1: Add a #[manually_drop] attribute

Add an attribute #[manually_drop] to the language that disables drop glue on a struct’s fields.

This allows us to correctly bind the UringState struct while exposing its fields safely:

#![allow(unused)]
fn main() {
#[repr(C)]
struct UringState {
    #[manually_drop]
    ring: Uring,
    #[manually_drop]
    buffers: [UringBuf; 16],
}

impl Drop for UringState {
    fn drop(&mut self) {
        // call C++ destructor
    }
}
}

Proposal 2: Add a drop_in_place method to the Drop trait

Add a drop_in_place method to the Destruct trait, which is called by the compiler instead of the normal drop glue when a type is dropped.

  1. If the type has implemented drop_in_place, it is called instead of the normal drop glue. No other code is run on drop, in particular this does not recurse into the fields.
#![allow(unused)]
fn main() {
struct UringState {
    ring: Uring,
    buffers: [UringBuf; 16],
}

impl Drop for UringState {
    /// Does the full dropping of the value.
    /// If not overridden by the user, this is compiler-
    /// generated; the default wil call `Self::drop` then drop the fields.
    /// Use this to control the drop order of the fields, or emulate `ManuallyDrop`.
    unsafe fn drop_in_place(&mut self) {
        // call C++ destructor
    }
}
}
  1. If the type does not override drop_in_place, we emit the drop glue as usual, which calls Drop::drop on the type (if implemented) then recursively drops the fields.

Work items over the next year

TaskOwner(s)Notes
Implement a lang experiment@thunderseethe to find an owner. Tyler Mandry can act as champion
Write an RFC@thunderseethe to find an owner

Team asks

TeamSupport levelNotes
compilerSmallImplementation reviews
langMediumVibe check and RFC review
opsemSmall
typesSmall

Frequently asked questions

Why not a #[reverse_drop_order] attribute instead?

The original destructor of the type still needs to be called. In C++ that destructor in turn calls the destructors of every field, so dropping the fields from the Rust side would lead to double free.

If we had #[reverse_drop_order] it might be usable for structs which themselves don’t define a destructor (only their fields have destructors), but technically it would still be UB to bypass the destructor defined by C++.

Implement and Maintain MC/DC Coverage Support

Metadata
Point of contact@RenjiSann
StatusProposed
RoadmapSafety-Critical Rust
Tracking issue
Zulip channelmc/dc-support
Teamscompiler, infra, project-stable-mir
Task owners(none)

Summary

Re-implement DC (Decision Coverage) and MC/DC (Modified Condition/Decision Coverage) instrumentation in rustc with a commitment to ongoing maintenance from AdaCore.

Motivation

MC/DC coverage is required by safety-critical standards including DO-178C (aviation, Level A), ISO 26262 (automotive, ASIL D), and IEC 61508 (industrial, SIL 3/4). Decision coverage is a less strict version of MC/DC only assessing the outcome of decisions (not looking at conditions), and required in DO-178C level B. Both criteria are different from branch coverage.

Without Decision and MC/DC support in rustc, Rust cannot be used in these domains as implementation outside of the compiler looks infeasible.

The status quo

MC/DC support has a tracking issue with initial implementation and updates in 2024 (PRs #123409mcdc-implementation-initial-pr, #126733mcdc-update-pr) under the -Zcoverage-options=mcdc flag. However, it was removed in late 2025 (commit 562222b). The removal rationale from the maintainer cited:

  • “Major burden on overall maintenance of coverage instrumentation”
  • “Major obstacle to other planned improvements” (e.g., macro expansion regions)
  • “Not yet complete, and shows little sign of being complete at an acceptable level of code quality in the foreseeable future”

This is a setback for safety-critical adoption of Rust. The previous implementation covered plain boolean expressions and nested decisions, but pattern matching support remained a draft, and there were known bugs with constant conditions (some fixed in LLVM 20).

We found that re-implementing this feature using rustc is the only viable options as to the best of our knowledge there is no way to generate valid rust sources after the expansion of macros. Macros are extensively used, even in the core library, making it unrealistic to restrict their use in safety critical applications. This thus only leaves the option to modify the intermediate representation in the compiler to introduce source coverage tracking instructions.

The next year

We acknowledge that the previous implementation was removed for valid reasons. This goal is not simply “re-land the old code” but rather “re-implement with a more sustainable architecture and dedicated maintenance commitment.”

Early discussions with both Niko Matsakis and the compiler team suggest that this effort is large enough that it should go through a Major Change Proposal (MCP) to ensure the compiler team can validate the architectural choices prior to implementation.

TaskOwner(s)Notes
Understand removal rationale in detailConsortium + compilerMeet with coverage maintainers, e.g. Oliver Scherer
Investigate potential design architecturesAdacore + Compiler teamSee Architectural options under consideration
Design revised implementation approachAdaCore engineer(s)Address code quality concerns; choose architecture based on investigation and submit a compiler MCP
Implement core MC/DC for boolean expressionsAdaCore engineer(s)Target: working -Zcoverage-options=mcdc on nightly
Establish ongoing maintenance commitmentAdaCore engineer(s)Formal agreement for long-term support
Coordinate with LLVM 20 for constant condition fixesCompiler teamUpstream bugs were blocking some functionality

The “shiny future” we are working towards

Rust has stable, well-maintained MC/DC coverage support that meets the requirements of DO-178C, ISO 26262, and IEC 61508. Safety-critical projects can use cargo llvm-cov (or similar tooling) to generate MC/DC reports suitable for certification evidence.

2026 scope: We aim for unstable (-Zcoverage-options=mcdc) support covering the core use cases. Stabilization would be a subsequent goal, contingent on demonstrated maintenance sustainability.

Design notes

Architectural options under consideration

Based on feedback from Niko Matsakis and the compiler team, we are investigating three potential architectural approaches:

  1. Extend Stable MIR: Add the syntactic structure information needed for MC/DC to the Stable MIR API. This provides a stable foundation that is less likely to conflict with other compiler changes, but requires preliminary work prior to implementation of MC/DC coverage instrumentation itself. On Paper the Stable MIR approach aligns well with the needs of a verification tool, with a stable interface usable with multiple versions of the compiler, remains to be seen if the required adaptations would fit within the goal’s timeframe.

  2. Compiler hooks approach: Use the existing mechanism for overriding compiler hooks (similar to what Kani uses today for MIR generation). This is more immediately achievable but may have similar maintenance characteristics to the previous implementation. It retains the benefit of keeping the implementation separate from the rustc codebase.

  3. Re-Implement the feature directly within rustc Add the coverage instrumentation passes directly within rustc. Like the compiler hook approach, this is more immediate, with easier access to the AST, and has the advantage of keeping the existing coverage instrumentations and the newly proposed one within the same codebase. Careful design would be needed for the instrumentation not to be too invasive, or impede development of other features.

Team asks

TeamSupport levelNotes
compilerMediumReview of implementation PRs; guidance on architecture to avoid previous maintenance issues; input on Stable MIR extension feasibility
project-stable-mirMediumConsultation on extending Stable MIR with syntactic structure; review of any proposed API additions (if this approach is chosen)
infraSmallCI support for MC/DC testing

Resources committed: AdaCore is prepared to commit engineering resources to implementation and ongoing maintenance. We understand this was the missing piece previously.

Frequently asked questions

Why should this attempt succeed when the previous one was removed?

Two key differences:

  1. Dedicated maintenance commitment. The previous implementation was primarily one person’s effort without long-term support guarantees. AdaCore can provide ongoing engineering resources specifically for coverage instrumentation maintenance.

  2. Architectural approach validation. We plan to engage with the coverage maintainers early to understand the architectural concerns and design an implementation that addresses them. This is to ensure buy-in from the compiler team before submitting PRs.

What about pattern matching?

Pattern matching MC/DC support was only at draft stage previously, the coverage criterion being still ill-defined for this language construct. Ferrous Systems have proposed one interpretations of patterns as decisions and conditions, to which we could apply MC/DC coverage, but we’re uncertain how much additional work this requires. Our initial scope focuses on boolean expressions and nested decisions, which covers the most common safety-critical use cases.

AdaCore plans to instruct customers to avoid pattern matching with an initial offering. Pattern matching support would be a stretch goal or follow-on effort.

What’s the relationship to GNATcoverage?

GNATcoverage is AdaCore’s coverage analysis tool. It can consume LLVM coverage data including MC/DC information. Having MC/DC support in rustc means GNATcoverage (and other LLVM-based coverage tools) can provide MC/DC reports for Rust code. This is valuable for organizations already using GNATcoverage for Ada/C in mixed-language safety-critical systems.

MIR move elimination

Metadata
Point of contactAmanieu d’Antras
StatusProposed
Tracking issuerust-lang/rust-project-goals#396
Zulip channelN/A
lang championAmanieu d’Antras
Teamscompiler, lang, opsem, wg-mir-opt
Task owners(none)

Summary

Add a MIR optimization which eliminates move operations. This will require changes to the MIR semantics of move to enable the optimization to cases where a value has had its address taken (LLVM already eliminates moves when this is not the case).

Motivation

One big difference between C++ and Rust is the concept of object identity: objects in C++ are always constructed at their final address through constructors while Rust objects are typically constructed by a method and then moved into their final address. While these two approaches achieve the same result in the end, in practice Rust is unable to eliminate many of these moves which leads to a lot of unnecessary memcpy calls (or in-line stack-to-stack copies).

The status quo

The following examples showcase the fundamental problem:

#![allow(unused)]
fn main() {
struct Foo([u8; 100]);

fn observe(addr: *const Foo) {
    println!("observed address {addr:?}");
}

fn example1() {
    let a = Foo([0; 100]);
    observe(&a);
    let b = a;
    observe(&b);
}

fn example2() {
    let a = (Foo([0; 100]), Foo([0; 100]));
    observe(&a.0);
    let b = a.0;
    observe(&b);
}
}

In example1, our current MIR semantics forbid a and b from being at the same address: this is because the storage lifetime of a extends to the end of its scope and therefore overlaps with that of b. This means that, according to the current tree borrows model, observe is still allowed to access the underlying allocation even after the value is moved.

example2 shows the same issue, but with partially-moved values. This is more complex since even though the first half of a has been moved, the second half must remain accessible at its current address while b is live.

What we propose to do about it

There have been some initial discussions about MIR semantics that would allow such moves to be optimized away, but this needs to be further developed into a fully-fleshed proposal. The basic idea is that, when moving a place, the portion of the allocation covered by that place is freed, which allows another allocation to take its place. This then allows for a MIR optimization that unifies 2 move-connected locals whose live range doesn’t overlap into a single local. See the Zulip thread for a further expansion of this to support partial moves as well.

The primary goal is to nail down the new semantics for MIR that will enable move elimination and write and RFC proposing these new semantics. This will primarily involve the language team (specifically the opsem team), but also the compiler team to evaluate the impact of the changes to MIR on the existing MIR optimization framework.

Once the new semantics are accepted then these would need to be implemented in Miri for checking. Finally, the new MIR optimization pass can be implemented in the compiler.

The end goal of this proposal is to be able to soundly perform move elimination as a MIR optimization. This will have the following effects:

  • Better optimized code due to the eliminated copies.
  • Shorter allocation lifetimes will mean that less state needs to be preserved at async yield points, which reduces the size of futures.
  • This RFC will address some long-standing unresolved issues around the MIR semantics of move (1 2 3 4).
  • It is possible that this even improves compilation speeds if it results in fewer copies being lowered to LLVM IR. Though this may not be guaranteed due to the additional time spent in the move elimination pass.

Design axioms

  • Teachable: the new semantics must be clear enough to be teachable to advanced users.
  • Checkable: the new semantics should remain deterministically checkable by Miri.
  • Efficient: the new MIR optimizations should not overly affect compilation time, or if they do, it should be at least justified with a significant increase in the performance of generated code.

Work items over the next year

TaskOwner(s)Notes
Author RFCAmanieu d’Antras
ImplementationAmanieu d’Antras

Team asks

TeamSupport levelNotes
langSmallRFC decision
compilerSmallRFC decision
opsemLargeDesign meeting
wg-mir-optMediumDesign meeting

Immobile types and guaranteed destructors

Metadata
Point of contactJack Huey
StatusProposed
RoadmapJust add async
Tracking issue
Other tracking issueshttps://github.com/rust-lang/rust/issues/149607
Zulip channel#t-lang/move-trait
types championlcnr
Teamslang, types
Task owners(none)

Summary

We propose to introduce new traits that describe what operations are possible on a type. Today Rust assumes all types can be moved (relocated in memory) and forgotten (via mem::forget). We will introduce traits like Move and Forget that make these capabilities explicit, allowing types to opt out. This follows the precedent set by the Sized hierarchy work, which relaxes the assumption that all types have a compile-time-known size. We will implement MVPs in the compiler, write RFCs, and validate viability through real-world testing in the Linux Kernel.

Motivation

The status quo

Rust has historically assumed that all values can be moved (relocated in memory) and forgotten (via mem::forget, without running destructors). These assumptions are baked into the language: assignment moves values, and mem::forget is safe. But some types need to opt out of these capabilities:

Immobile types: A lot of async futures want to be self-referential, but self-referential types can’t be safely moved. The current solution is Pin, which encodes immovability as a property of places rather than types. This leads to significant complexity. As The Safe Pinned Initialization Problem describes, Pin struggles to safely encode self-referential types in systems like the Linux kernel.

Guaranteed destructors: Some types need their destructors to run. A Transaction type might require commit() or rollback() before cleanup. A scoped task handle must join before the scope exits. But mem::forget is safe, so Rust can’t guarantee destructors run. This blocks patterns like safe scoped spawn for async, where the spawned task borrows from the parent scope.

What we propose to do about it

We propose to generalize Rust’s type system with new auto-traits that describe what operations are possible on a type. The framing is positive: traits represent capabilities. At the base layer, types may have no special capabilities. We then layer on the things we need:

  • Move: The type can be relocated in memory.
  • Destruct: The type can be implicitly dropped (destructor runs when it goes out of scope).
  • Forget: The type can be forgotten via mem::forget without running its destructor.

This follows the precedent set by the Sized hierarchy work. Just as that work relaxes “all types have compile-time-known size” to support scalable vectors, this work relaxes “all types can be moved” and “all types can be forgotten.”

The Move trait encodes movability as a property of types rather than places:

#![allow(unused)]
fn main() {
#[lang = "move"]
unsafe auto trait Move {}
}

Types implementing !Move cannot be moved and must keep a stable address for their entire existence. This is simpler than Pin because immovability is a type property, not a place property. Construction of !Move types will rely on work from #t-lang/in-place-init.

The Forget trait lets types opt out of being forgettable:

#![allow(unused)]
fn main() {
// Types implementing !Forget must have their destructors run
unsafe impl !Forget for ScopedTaskHandle {}
}

With !Forget, we could build safe scoped spawn: the handle’s destructor joins the task, and because the handle can’t be forgotten, the join is guaranteed. This unblocks patterns that are currently impossible in safe Rust.

Work items over the next year

TaskOwner(s)Notes
Compiler implementation for Movelcnr and Nia
Write the Move RFCYoshua Wuyts
Design exploration for guaranteed destructorsNiko MatsakisExplore trait hierarchy options and interaction with existing features
Test in Linux kernelBenno LossinRfL is an important Rust user which uses a lot of self-referential data structures.
Test interactions between Iterator and !MoveYoshua WuytsIt’s important to prove that generator-based effects can be desugared to impl Trait + !Move so they can support self-references.

What is concretely out of scope for this year is anything related to changing or updating the Future trait. This is the only stable trait in Rust which depends on Pin, and would need a migration story to be able to use Move. However depending on Pin is not the only shortcoming Future has (1 + 2 + 10 more issues), and so fixing the Future trait is best treated as a standalone project.

Team asks

TeamSupport levelNotes
langLargeDesign session needed to work through design
typesLargeInvolved in implementation + review

Frequently asked questions

How does this relate to the Sized hierarchy work?

The Sized hierarchy work establishes the pattern: Rust can relax assumptions that were previously universal by introducing trait hierarchies that let types opt out. That work relaxes “all types have compile-time-known size” to support scalable vectors and extern types. This goal applies the same pattern to “all types can be moved” and “all types can be forgotten.”

How does this relate to the “pin ergonomics” initiative?

This work is an alternative to Project Goal 2025H2: Continue Experimentation with Pin Ergonomics, which includes the following extensions:

  • A new item family pin in lvalues, e.g. &pin x, &pin mut x, &pin const x.
  • A one-off overload of Rust’s Drop trait, e.g. fn drop(&pin mut self).
  • A new item kind pin in patterns, e.g. &pin <pat>.

Notably this work does not solve pin’s duplicate definition problem, meaning that even with these extentions we still end up with Trait and PinnedTrait variants of existing traits. The Drop trait being the exception to this, since the initiative is proposing to special-case it using a one-off overload.

Rather than trying to change the language to make Pin work, we believe the problem is with Pin and we should improve the way immovable types are encoded in Rust instead. With the eventual goal to deprecate Pin in Rust entirely.

Because Rust promises to stay backwards-compatible forever, making pin a language-item on par with & and mut is something we’ll forever need to keep supporting. Given our eventual goal is to deprecate Pin, we do not believe that we should make pin a part of the language. Which is why Move is not just a complimentary proposal, but intended as an alternative.

What enables safe scoped spawn?

Safe scoped spawn requires guaranteed destructors. The pattern: spawn returns a handle whose destructor joins the task. If you could mem::forget the handle, the task could outlive the scope and access dangling references. With !Forget, the handle’s destructor is guaranteed to run, making the pattern safe. This is one of the key motivations for the guaranteed destructors portion of this goal.

Where can I read more about this design space?

Several blog posts explore this area:

Stabilize the next-generation trait solver

Metadata
Point of contactlcnr
StatusProposed
RoadmapUnblocking dormant traits
RoadmapJust add async
Tracking issuerust-lang/rust-project-goals#113
Other tracking issuesrust-lang/rust#107374
Zulip channel#t-types/trait-system-refactor
HighlightLanguage changes
types championlcnr
lang championNiko Matsakis
Teamslang, types
Task owners(none)

Summary

Stabilize -Znext-solver=globally, replacing the existing trait solver implementation entirely.

Motivation

The next-generation trait solver is intended to fully replace the existing type system components responsible for proving trait bounds, normalizing associated types, and much more. This should fix many long-standing (soundness) bugs, enable future type system improvements, and improve compile-times.

The status quo

There are multiple type system unsoundnesses blocked on the next-generation trait solver: [project board][unsoundnesses]. Desirable features such as coinductive trait semantics and perfect derive, where-bounds on binders, and better handling of higher-ranked bounds and types are also stalled due to shortcomings of the existing implementation.

Since starting to work on this at the EOY 2022, we’ve:

  • stabilized its use in coherence checking in Rust 1.84
  • replaced the use of chalk in rust-analyzer
  • done full crater runs and all large regressions are either fixed or intended
  • improved performance and diagnostics, even if they is still more work to do

What we propose to do about it

Stabilize -Znext-solver=globally and rip out the old implementation

  • finish triaging the crater and and resolve remaining issues tracked in the project board
  • achieve performance parity with the old solver
  • write an RFC for the cycle semantics used by the new trait solver
  • document the behavior of the new trait solver and write stabilization reports

Work items over the next year

TaskOwner(s)Notes
figure out and resolve remaining blockerslcnr
achieve performance paritylcnr
cycle semantics RFClcnr, Niko Matsakis
complete stabilization reportlcnr
stabilizationlcnr
remove old implementationlcnr

Team asks

TeamSupport levelNotes
langMediumStabilization decision for user facing changes
typesLargeStabilization decision, ongoing review work

Frequently asked questions

What do I do with this space?

Open Enums

Metadata
Point of contact@kupiakos
StatusProposed
Tracking issue
Zulip channel(an existing stream can be re-used or new streams can be created on request)
Teamscompiler, lang, libs, opsem, types
Task owners(none)

Summary

Merge and implement the unnamed enum variants RFC to enable ergonomic open enums in the language.

Motivation

The status quo

Rust has some mechanisms to guarantee a stable ABI for separately-compiled types:

  • #[repr(…)] controls the memory layout of types.

    The default is Rust with intentionally no stability guarantees. The C layout orders fields in memory to match declaration order.

  • extern "…" fn controls the calling convention of a function

    The default is "Rust" with intentionally no stability guarantees. The "C" ABI mirrors what is the default calling convention in C for the platform.

  • #[unsafe(no_mangle)] and unsafe extern {…} controls the symbols used for linking.

These focus on providing stability when the same type definition is separately compiled with different versions of rustc. This includes the initial proposed extern "crabi" fn and repr(crabi), which provides versioned stable layout algorithms and calling conventions.

However, these do not consider stability between separately-compiled units when a type is extended. While #[non_exhaustive] prevents breakage due to non-exhaustive matches when types compile together, it does nothing to prevent ABI breakage (and accidental UB) when a type is extended in one compiled unit and not the other.

For a struct, it is simple enough prevent known future changes to a type from affecting its layout: include an unused field to pre-allocate space of the needed size. For an enum, however, there is no mechanism to pre-declare future variants’ discriminants as valid and opt-in to ABI stability.

Consider bindgen, which has 4 different ways to interoperate with a C enum:

VariationDescriptionDrawback
ConstantsExports named integersNo strong typing or grouping - the same as #define
Module constantsThe same as above but grouped in a module; use enum_name::* brings its values into scopeNo strong typing
Newtype#[repr(transparent)] struct EnumName(Int)Harder to read, loses Rust enum features
RustA closed Rust enum with explicit reprUndefined Behavior when an invalid value is trivially produced by C

These all have their own serious drawbacks. While a newtype integer is a fine enough way to represent an open C enum, it is no longer treated as an enum by Rust. The choice of enum or struct reflects the author’s intent and informs how macros, tooling, and other features are supposed to interpret the type - a set of names with associated values, or a wrapper around a plain integer. When a struct is used to represent an open enumeration:

  • The names aren’t syntactically grouped with the type declaration.
  • Code analysis and lints specific to enums are unavailable.
    • No “fill match arms” in rust-analyzer.
    • The non-exhaustive patterns error lists only integer values, and cannot suggest the named variants of the enum.
    • The unstable non_exhaustive_omitted_patterns lint has no easy way to work with this enum-alike, even though treating it like a non_exhaustive enum would be more helpful.
  • It’s invalid to use the variants like with use EnumName::*.
    • bindgen works around this by allowing the variants to be declared globally.
  • In order for an open enum’s variant name to match the normal style for an enum variant name, allow(non_uppercase_globals) is required.
  • derives that work with names are less useful. The built-in derive(Debug) can’t know the variant names to list. Third-party macros cannot easily know the variant names. The open-enum crate, which provides an attribute macro to construct newtype integers from an enum declaration, requires a distinct derive ecosystem for operations like TryFrom, Debug, IsKnownVariant, ser/de, etc. - a worse experience than if all derives were capable of reading a first-class open enum definition.

What we propose to do about it

To focus on one missing piece of the ABI puzzle and improve C interop, we propose to merge and implement the the unnamed enum variants RFC.

This allows discriminants to be declared as valid before they are represented by a named variant in the future. By adding _ = .. to a field-less repr(C) enum, it becomes an open enum and can now be safely used with C and (ordinarily) as cast from c_int.

Design axioms

  • Stability: Provide a stable ABI when an enum is modified and across compiler versions.
  • Clarity: The valid values of an enum are unambiguously declared up-front.
  • Intent: An enum captures the intent to name a set of values that may be exhaustively matched.
  • Integration: Integrate with the rest of the language and future extensions, especially lints and warnings.
  • Ergonomics: It’s nearly as easy to use an open enum as a closed enum.

The “shiny future” we are working towards

  • Dynamically linked code is safe and ergonomic to use and extend.
  • Users can export extensible enums that may be used in dynamically-linked libraries, including enums with fields.
  • Tooling prevents accidental ABI breakage when extending any type by confirming a type’s layout and bit validity isn’t affected by a change.
  • Open enums are fully-featured enums with all of their tooling. Third-party macros recognize unnamed variants. It is just as easy to construct and manipulate open enums as closed enums are.
  • Bindgen generates repr(C) open enums by default, and there’s rarely a reason to select another variation.

Work items over the next year

TaskOwner(s)Notes
Integrate feedback and merge unnamed variants RFC@kupiakos
Implement and merge nightly implementation@kupiakos

Team asks

TeamSupport levelNotes
compilerMediumImplementation reviews
langMediumChampion and (ideally) a lang meeting
libsSmallChanges to derive
opsemSmallDoc changes if necessary
typesSmall

Frequently asked questions

Why a lang feature? Isn’t a macro good enough for open enums?

While a macro can be used to make declaring an integer newtype simpler, the drawbacks of using a struct to represent a set of enumerated values are extensive. It also cannot simply represent extensible enums with fields as described in the “shiny new future”.

We aim to make working with open enums ergonomic in a way they cannot be today, even with simpler changes to the language.

Implement Open Rust Namespace Support

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
Tracking issuerust-lang/rust-project-goals#256
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
Teamscargo, compiler
Task owners(none)

Summary

Navigate the cross-team design work to get RFC 3243 implemented.

Contingent on contributor: This goal needs contributors to help complete the implementations in Cargo, rustc, and crates.io. The work spans multiple repositories and involves cross-team coordination. Estimated time commitment: TBD.

Motivation

RFC 3243 proposed opening up namespaces in Rust to extension, managed by the package name with crates-io putting access control on who can publish to a crate’s API namespace. This covers multiple teams and needs a lot of coordination to balance the needs of each team as shown on the rustc tracking issue.

The status quo

  • Cargo support is partially implemented.
  • Compiler design is agreed on and partially implemented.
  • There is a crates-io prototype for a previous iteration of RFC 3243 but that code base has likely diverged a lot since then.

The next 6 months

  • Implement Cargo and compiler support for this to be experimented with and allow crates-io work.
  • Understand what changes are needed for crates.io support, and what it will take to implement these.

The “shiny future” we are working towards

Team asks

TeamSupport levelNotes
cargoSmall
compilerSmallDesign discussions, PR review

Frequently asked questions

Nightly support for function overloading in FFI bindings

Metadata
Point of contact@ssbr
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler, lang, libs-api, types
Task owners(none)

Summary

Design and implement a function overloading system that is suitable for FFI with languages that have overloading. In particular, we aim to make Rust more compatible with C++, so that Rust callers do not place a maintenance burden on C++ library owners due to overloading.

Motivation

The status quo

Overloading on arguments

C++ offers the ability to define and call overloaded functions (also called “overload sets”): sets of functions with the same name, which expose multiple function signatures. These can dispatch both on function arity, and on the types for functions with the same number of parameters, selecting based on both the method receiver type and the ordinary method or function argument types. Calls select the correct overload using a name resolution system that takes the function signature into account. If these functions are to be called from Rust, we need some mechanism to call them.

Rust already has overloading, in the form of trait dispatch. For example, the overloaded C++ constructor MyType(int32_t); MyType(int32_t, int32_t) can become impls of something like the Rust traits From<(i32,)> and From<(i32, i32)>.

Using Rust’s existing trait system is syntactically difficult. In order to support overloading on arity, we must use an auxiliary type for the list of arguments, such as a tuple. This means that calls like x.foo() and x.foo(1, 2) must become x.foo(()) and x.foo((1, 2)). (playground)

#![allow(unused)]
fn main() {
impl Foo<()> for MyType {
    type Return = i32;
    fn foo(&self, _args: ()) -> i32 {
        42
    }
}
impl Foo<(i32, i32)> for MyType {
    type Return = i32;
    fn foo(&self, args: (i32, i32)) -> i32 {
        args.0 + args.1
    }
}

x.foo(());
x.foo((1, 2));
}

This presents an obvious ergonomic problem. And all methods must look like this, or else there is a code maintenance and compatibility hazard: adding an overload to C++ would break Rust callers, but not equivalent C++ callers.

Secondly, Rust’s trait coherence rules severely limit the set of possible overloads compared to C++, which does not have any version of coherence. (See FAQ for details.)

At the time of writing, the only fully general solution for overloading is to manually rename each overload in the overload set, but this means that existing C++ interfaces are not callable from Rust automatically, and can mean that adding an overload can change whether existing functions get bindings. Ideally, adding or removing an overload should not be more backwards-incompatible for C++ than for Rust, and supporting Rust callers should not be a higher burden than supporting C++ callers.

Overloading on receivers

Consider the clear method on a C++ container type. If you have a unique reference to the container, this is safe, but if you have an aliasing reference – even if it is otherwise safe to call functions accepting aliasing references – this function would be unsafe.

#![allow(unused)]
fn main() {
pub fn clear(&mut self) {self.size = 0; free(self.data)}
pub unsafe fn clear(self: CMut<'_, T>) {unsafe {CMut::as_mut(self).clear();}
}

Rust and C++ have many reference types (potentially something like &T, &mut T, Pin<&mut T>, CRef<T>, CMut<T>, RvalueRef<T>, ConstRvalueRef<T>, CRvalueRef<T> and CConstRvalueRef<T> (for aliasing/safety discrimination)). It will sometimes be necessary to implement the same method for all nine or so of them: either because in C++, they are separate overloads with separate implementations, or because they need separate safety or other function properties.

There are only a finite number of reasonable receivers, so we could generate a function per receiver type, using different suffixes like _pin or _cmut. But if we can overload on the receiver, these could be compressed into an API which is much easier to work with as a human.

What we propose to do about it

We would like to implement a form of function overloading which is sufficient to seamlessly call C++ code. As part of this, there will be significant design work. Ideally, by the end of this year, there is a set of unstable features which can be trialed by existing FFI code generators to see where the pain points are, for further iteration in 2027 and onward.

Particular approaches we intend to explore:

  • Leveraging the existing trait system to perform something which is syntactically similar to C++ overloading. (For example, by extending extern "rust-call", or some other form of splatting.)
  • Integrate with existing or proposed unstable features, such as specialization, to cover as much of the C++ overload space as possible.

As an example, something like:

#![allow(unused)]
fn main() {
trait MethodArgs : Tuple {
    fn call_method(self, this: &Foo);
}

impl Foo {
    fn method(&self, #[splat] args: impl MethodArgs) { args.call_method(self) }
}

impl MethodArgs for (i32, String) {
    fn call_method(self, this: &Foo) { dbg!(self.0) }
}
}

Design Axioms

  • Be comprehensive. Overloading should not be a reason that a C++ function cannot be called.
  • Preserve maintainability across the language boundary. Adding or removing an overload should not be substantially more backwards-incompatible in Rust than it is in C++. Supporting Rust callers should not require more work than supporting C++ callers.
  • Keep Rust nice. Build on existing concepts where possible: a natural extension of existing language semantics, not a replacement for them.
  • Avoid surprises. If a function call compiles, it should pick the overload you most expect.

It is not a goal to match C++’s resolution rules exactly. Many languages implement overloading, and Rust may want to interoperate with more than one of them, even if they have conflicting resolution rules. We will not design C++’s argument-dependent lookup (ADL) for Rust. Every C++ function should be callable, but that does not mean that it has to be callable in exactly the same way with the same arguments. It is OK to require explicit conversions or markers to select an overload.

Work items over the next year

TaskOwner(s)Notes
Design an overloading mechanism that is fit for FFI@ssbrTyler Mandry to act as champion
Implement it as a lang experiment(filling in later)Tyler Mandry to act as champion

Team asks

TeamSupport levelNotes
langMediumDesign meeting Experiment
libs-apiSmallWould like to know if they have use cases for overloading in standard Rust, or if there are certain approaches they would like better. May be involved if experiment involves library surface area (e.g. Fn traits)
typesSmallNo dedicated reviewer needed/given, but tracking issue should note the needed for dedicated types review prior to stabilization
compilerSmallMost complexity is in the type system

Frequently asked questions

What do existing tools do with overloads?

Crubit: overloaded constructors and operators become trait impls. Other overloaded functions do not receive bindings unless the function has a unique Rust name specified using an attribute.

cxx: overloaded functions do not receive bindings.

autocxx and bindgen: overloaded functions receive a numbered name: func1, func2, etc.

Incoherent overload sets

The following overload set, in C++, is perfectly valid:

struct ConvertibleFromInt {
    ConvertibleFromInt(int);
};
void Foo(ConvertibleFromInt);
void Foo(int);

The first overload accepts anything which implicitly converts to a ConvertibleFromInt, while the second overload accepts anything which implicitly converts to an int. These overlap: some types implicitly convert to both, including int itself, as well as char and other integral types. C++ evaluates which overload to select using a multi-step process, but the gist is that it builds up a set of candidates (two in this case), and then selects the “best viable function” from those.

This is unlike Rust’s trait system, which fails compilation at the trait implementation if it can overlap, even if the overlap is only in theory for a type that does not exist, and even if one implementation is in some sense a better match. It is not possible to write a trait that models the above overload set for Foo. The Foo(ConvertibleFromInt) overload should apply to all types that implement something like Into<ConvertibleFromInt>, while the Foo(int) overload should take types that implement something like to Into<c_int>. Rust cannot prove these are disjoint, because they are not, and overlapping impls of the form impl<T: Into<c_int>> Foo<T> for … will fail to compile. (playground)

Similarly, it is not possible to implement an overload set that accepts multiple impl PinInit arguments for in-place initialization of non-rust-movable arguments, even if the PinInit trait used an associated type to try to disambiguate (unless/until traits get disjoint associated types).

What about extern "rust-call"?

Rust has an existing way to pack function arguments into a tuple as part of ordinary call syntax: extern "rust-call", in the Fn* family of traits. For example, the following unit struct acts like an overloaded top-level function:

#![allow(unused)]
fn main() {
struct TopLevelFunc;

impl FnOnce<(u32,)> for TopLevelFunc {
    type Output = ();
    extern "rust-call" fn call_once(self, _args: (u32,)) -> () {}
}
impl FnOnce<(u32, u32, u32)> for TopLevelFunc {
    type Output = ();
    extern "rust-call" fn call_once(self, _args: (u32, u32, u32)) -> () {}
}
TopLevelFunc(1);
TopLevelFunc(1, 2, 3);

}

(playground)

However, this is less a feature of rust-call and more a feature of Fn*. If you directly define a method using extern "rust-call", it still must be called using tuple arguments, not unpacked arguments as with the Fn* traits.

You might imagine implementing method overloading using extern "rust-call" as so:

#![allow(unused)]
fn main() {
trait Method<Args: Tuple> { extern "rust-call" fn method(&self, args: Args); }

struct MyType;
impl Method<(u32,)> for MyType { extern "rust-call" fn method(&self, args: (u32,)) {} }
impl Method<(u32, u32, u32)> for MyType { extern "rust-call" fn method(&self, args: (u32,)) {} }
}

But this does not allow calls like MyType.method(1, 2, 3). We would need an additional feature for splatting arguments outside of the Fn* traits. (playground)

Continue Experimentation with Pin Ergonomics

Metadata
Point of contactFrank King
StatusProposed
Tracking issuerust-lang/rust-project-goals#389
Zulip channelN/A
compiler championOliver Scherer
lang championTC
types championOliver Scherer
Teamscompiler, lang, types
Task owners(none)

Summary

Continue experimenting with and fleshing out the design and semantics for the pin ergonomics experiment.

Motivation

Several major Rust features, such as async and generators, depend on the ability to ensure data will not move in memory. The way Rust achieves this is through the Pin wrapper, but pinning has notoriously poor ergonomics. Exploring how the ergonomics can be improved by integrating pinning into the language better could help unblock advancements in other Rust features.

The status quo

Pinning exists but few people like it. We have an experiment for improving the ergonomics around pinning and some initial PRs have landed, but we would like to build more sustained momentum on it.

Work items over the next year

We need to finish the borrow checker support, coersion and auto borrowing. It seems the Reborrow traits goal might help/solve auto borrowing?

But there’s also broader work around describing the new borrowchk behavior and gathering feedback on it. In particular, the &pin mut borrow works differently from a normal &mut borrow.

A regular &mut takes a temporary exclusive access to the original place and releases it once the borrow’s lifetime expired.

But a &pin mut keeps the pinned effect even after the borrow’s lifetime expired. Once you pin a place, it stays pinned for the duration of the program.

This is inconsistent and user feedback will be really important here – both in terms of exploring the impact of this fully and how teachable this is.

TaskOwner(s)Notes
borrowchk for &pin .. placeFrank KingIs this still TODO?
Drop::pin_dropFrank King
&pin .. T <-> &[mut] T coercionFrank King
Auto borrowingFrank King
Collect borrowchk’s design user feedbackFrank King
update the RFCFrank King
Call for testing blog postFrank King
Stabilization?Frank King

Team asks

TeamSupport levelNotes
compilerMediumReviews
langMediumDesign meeting?
typesMediumReviews

Stabilize the polonius alpha analysis

Metadata
Point of contactRémy Rakic
StatusProposed
Tracking issuerust-lang/rust-project-goals#118
Zulip channel#t-types/polonius
types championJack Huey
Teamstypes
Task owners(none)

Summary

Stabilize the polonius alpha borrow checking analysis, which resolves common limitations of the borrow checker such as the NLL problem case #3 and lending iterator patterns (#92985). This goal covers fixing the remaining known soundness issue, expanding test coverage, building a formal model in [a-mir-formality][] and upstreaming it into the Rust reference, validating performance, and preparing a stabilization report.

#92985: https://github.com/rust-lang/rust/issues/92985 [a-mir-formality]: https://github.com/rust-lang/a-mir-formality/

Motivation

The status quo

Polonius is an improved version of the borrow checker that resolves common limitations and which is needed to support future patterns such as lending iterators. Over the past three goal periods (2025h1, 2025h2), we have:

  • Identified an actionable subset of the full polonius analysis — the “alpha” version — that handles the most impactful cases while scaling well
  • Implemented and landed a functional prototype on nightly that passes perf runs and crater runs
  • Significantly reduced overhead through a lazy constraint graph rewrite
  • Identified the remaining phases for gradually improving precision in the future

The alpha analysis is now at the point where stabilization is the natural next step. There is one known soundness issue remaining (related to dead regions outlived by opaque types), and we need to expand testing, validate performance on real-world code, and prepare the documentation and stabilization report.

What the alpha analysis accepts

The majority of open issues marked NLL-deferred and fixed-by-polonius are fixed by the alpha analysis. The most impactful example is the “NLL problem case 3” and variations:

#![allow(unused)]
fn main() {
use std::collections::HashMap;
use std::hash::Hash;

fn get_or_insert_default<'r, K: Hash + Eq + Copy, V: Default>(
    map: &'r mut HashMap<K, V>,
    key: K,
) -> &'r mut V {
    match map.get_mut(&key) {
        Some(value) => value,
        None => {
            map.insert(key, V::default());
            map.get_mut(&key).unwrap()
        }
    }
}
}

A similar variation is the filtering lending iterator pattern, where next() reborrows self in a loop — code that NLLs incorrectly rejects today. Beyond being an ergonomic hazard, this limitation is also an expressiveness gap: it blocks the ability to write [lending iterator patterns]#92985 entirely.

What the alpha analysis does not accept

Some cases that require full flow-sensitivity are left for future improvements and show the same imprecision as NLLs today. For example, certain patterns of linked-list traversal with conditional reborrowing. These cases are encountered more rarely than the new cases the alpha accepts.

What we propose to do about it

We propose to stabilize the polonius alpha analysis. This involves:

  1. Fix the remaining known soundness issue related to liveness of captured regions for opaque types.
  2. Ship a nightly preview behind a feature gate with a call for testing, to surface any unknown issues.
  3. Expand testing and validation, including adding tests from open fixed-by-polonius issues, enabling polonius testing on CI, and using [a-mir-formality][] as an oracle to validate the rustc implementation.
  4. Build a formal model and specification of the borrow checking analysis in a-mir-formality, and upstream it into the Rust reference. This ties into the experimental language specification goal as a case study for integrating formal models into the specification process.
  5. Validate performance on real-world code. We are willing to accept a performance cost in the range of 10–20% for the benefits polonius provides. We are aware of worst-case scenarios that could be larger, but do not yet know whether these occur in practice — the preview period will help answer this.
  6. Prepare for stabilization with a stabilization report, rustc dev guide documentation, and a blog post announcing the preview.

During the preview period, we will also evaluate and address diagnostics quality for the newly accepted patterns and for cases near the boundary of what the alpha accepts.

Work items over the next year

TaskOwner(s)Notes
Fix soundness issue with opaque types and dead regionsRémy Rakic, tiiftiif’s trait-system-refactor-initiative#159 is a pre-requisite for a borrowck fix
Expand test coverageRémy RakicWe’ve started doing this during the previous goal period, e.g. from open fixed-by-polonius issues in #145053(https://github.com/rust-lang/rust/pull/145053)
Enable polonius testing on CIRémy Rakic
Build formal model in a-mir-formalitytiif, Rémy RakicValidate against rustc implementation
Upstream borrow checking specification into Rust referencetiif, Rémy RakicTies to experimental language specification goal
Ship nightly preview behind feature gateRémy RakicWith blog post / call for testing
Validate performance on real-world codeRémy Rakic
Address diagnostics feedback from previewRémy Rakic
Write stabilization reportRémy Rakic
Write rustc dev guide documentationRémy Rakic

The “shiny future” we are working towards

Stable support for the polonius alpha analysis, followed by gradually improving expressiveness. Beyond the alpha, there are further phases of the analysis that can handle more exotic borrowing patterns (such as full flow-sensitivity for linked-list traversals). These future improvements can build on the stable alpha foundation and on the formal model developed as part of this goal.

Design axioms

  • Don’t let perfect be the enemy of good. The alpha analysis doesn’t handle every case the full polonius model could, but it handles the most common and impactful cases. Shipping this subset sooner is better than waiting for a complete solution.

  • Prove it formally. Building a formal model in a-mir-formality and using it as an oracle gives us confidence that the implementation matches the intended semantics, and produces a specification that lives on as documentation.

  • Accept bounded cost. We are willing to accept a compile-time overhead of 10–20% for the expressiveness gains polonius provides. Unbounded cost is not acceptable, but modest cost is a reasonable trade-off.

Team asks

TeamSupport levelNotes
typesLargeDesign review, stabilization decision, reviews from Jack Huey and Matthew Jasper

Support needed from the project

We expect most support to be needed from the types team, for design review, reviews, and the stabilization decision. We expect Niko Matsakis to provide design guidance, and Jack Huey and Matthew Jasper to help with reviews.

Frequently asked questions

What is the polonius alpha analysis?

The alpha analysis is a location-sensitive version of the borrow checker that uses reachability within a combined subset + CFG graph to determine loan liveness. It is a superset of the current NLL analysis — it accepts everything NLLs accept, plus additional patterns like NLL problem case 3 and lending iterator filtering. It does not handle full flow-sensitivity (e.g., certain linked-list traversal patterns with conditional reborrowing).

How does this relate to the original datalog-based polonius?

The original datalog implementation could handle more exotic patterns but did not scale and had no path to stabilization. The alpha analysis is a pragmatic subset that captures the most impactful improvements while being practical to ship.

What happens if the preview reveals unacceptable performance costs?

We have identified specific optimization opportunities (limiting propagation to affected blocks, unifying invariant lifetimes, activation-only invalidations) that we can pursue if needed. Performance work can also be done by others, both before and after stabilization.

Stabilize public/private dependencies

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
RoadmapSecure your supply chain
Tracking issuerust-lang/rust-project-goals#272
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
Teamscargo, compiler
Task owners(none)

Summary

Implement and stabilize the MVP of public dependencies described in RFC #3516. Public dependencies allow crates to declare dependencies whose types are meant to be exposed in the public API.

Contingent on contributor: This goal needs a contributor to work with the compiler team on identifying and implementing the minimal lint subset needed for stabilization. The work spans rustc (lint implementation) and Cargo (dependency metadata). Estimated time commitment: TBD.

Motivation

This will allow users to tell Rustc and Cargo what dependencies are private

  • Help users catch ways they unexpectedly expose their implementation details
  • Help tooling better identify what all constitutes an API
  • Speed up cargo doc by only building dependencies you can access
  • Help users keep versions between dependencies in sync

The status quo

RFC #1977(https://github.com/rust-lang/rfcs/pull/1977) has been superseded by RFC #3516(https://github.com/rust-lang/rfcs/pull/3516) to reduce complexity on the Cargo side to help get this over the line. However, there is still a lot of complexity on the compiler side to get this right ( rust#3516, rust#119428, ), keeping this feature in limbo

The next 6 months

Work with compiler to identify a minimal subset of functionality for what the lint can do and close out the remaining stabilization tasks.

The “shiny future” we are working towards

Team asks

TeamSupport levelNotes
cargoSmall
compilerMediumAn implementer, design discussions, PR review

Frequently asked questions

Reborrow traits

Metadata
Point of contactAapo Alasuutari
StatusProposed
RoadmapBeyond the &
Tracking issuerust-lang/rust-project-goals#399
Zulip channel#t-lang/custom-refs
lang championTyler Mandry
types championBoxy
Teamscompiler, lang, types
Task owners(none)

Summary

Bring the Reborrow and CoerceShared trait to nightly Rust, enabling iteration based on user feedback. Begin work on nontrivial cases where more than one lifetime is being reborrowed or coerced into shared

Motivation

Reborrowing is fundamental to Rust’s ergonomics with references. When you pass a &mut T to a function, Rust automatically reborrows it so you can use it again after the call. But this doesn’t work for user-defined types that wrap references, like Option<&mut T>, Pin<&mut T>, or custom smart pointers.

Today, users work around this with .as_deref_mut() or .reborrow() methods, but these have a critical limitation: values derived from a reborrow cannot be returned from the function that called .reborrow(). The lifetime gets constrained to the reborrow call site. True reborrowing doesn’t have this constraint.

The status quo

The 2025H2 period produced a working implementation of the Reborrow and CoerceShared traits for types with a single lifetime parameter and trivial memory layouts. The exact mechanism for expanding the implementation from trivial cases to non-trivial memory layouts and sets of reborrowed lifetimes remains an open problem.

What we propose to do about it

This year we continue iteration on the traits based on user feedback, focusing on:

  1. Gather feedback from users - Especially from reborrow crate users and the Rust for Linux project
  2. Overcome known limitations - Support types with multiple lifetime parameters where one or more of them gets reborrowed.
  3. Support non-trivial CoerceShared - Support CoerceShared operations that reorder or drop fields.
  4. Expand safety and validity checks - CoerceShared performs an implicit type transmute and must be extensively tested and validated.
  5. RFC - The draft RFC should be refined and rewritten based on implementation experience, and landed within this project goal.

The fundamental design philosophy remains:

  • Reborrowing is “a memory copy with added lifetime analysis” - no user code is run.
  • The traits must achieve true reborrowing where derived values can be returned from the function.
  • Performance cost must be trivial as reborrowing is performed at every coercion site.
  • Prevent abuse - CoerceShared must not slide into the realm of a generic Coerce trait.

Work items over the next year

TaskOwner(s)Notes
Land first implementation PR to nightlyAapo Alasuutari
Solicit wide feedback on the featureAapo Alasuutari
Continue experiment based on experienceAapo Alasuutari
Rewrite the RFCAapo Alasuutari

Team asks

TeamSupport levelNotes
langMediumContinued experiment support, design feedback
compilerSmallStandard reviews for trait implementation PRs
typesSmallStandard reviews for trait implementation PRs

Frequently asked questions

How does this relate to Pin ergonomics?

Pin currently has special-cased reborrow support in the compiler. Once reborrow traits are stable, Pin<&mut T> can be reimplemented using the general mechanism, removing the special case. The Pin ergonomics goal is proceeding in parallel.

Why the shift from associated type to type parameter for CoerceShared?

Originally CoerceShared had type Target to prevent multiple coercion targets (which could enable abuse as a general coercion trait). But the trait method that motivated this fear was found unnecessary, so allowing multiple targets via trait CoerceShared<Target: Copy> {} is now safe and enables more flexibility - like a collection of &muts all coercing to &s.

Why limit to single lifetime initially?

Supporting multiple lifetimes requires dealing with rmeta (Rust metadata) complexity. Focusing on single-lifetime reborrowing first lets us get the core functionality working before tackling that additional complexity.

rust-lang/rust-project-goals#399: https://github.com/rust-lang/rust-project-goals/issues/399 lang: https://github.com/rust-lang/lang-team compiler: https://github.com/rust-lang/compiler-team

Redesigning super let: Flexible Temporary Lifetime Extension

Metadata
Point of contactdianne
StatusProposed
Tracking issue
Zulip channelN/A
Teamscompiler, lang, libs
Task owners(none)

Summary

I aim to meet with the language team to discuss redesigning the super let feature, write an RFC for it, and work towards stabilizing it.

Motivation

super let has three main avenues of design, each with their own motivations:

  • It fills an expressiveness gap in API design space: by enabling temporaries borrowed in the result values of macros to be lifetime-extended, it becomes possible to assign the macro result to a variable with a let statement and use it later. A concrete example of this is format_args!. This allows for writing more natural code, treating these macros more like ordinary syntax.
  • It provides an explicit syntax for temporary lifetime extension. Although too-short-lived temporaries in hand-written code can have their scopes extended manually by assigning them to variables, a super let-like temporary scoping feature has the potential to improve ergonomics.
  • It has the potential to provide convenient syntax for common cases of in-place initialization, particularly on-stack pinned initialization. Emplacing into a temporary guarantees no external references to it exist, which can serve as part of a proof of pinnedness. Temporary lifetime extension then provides a way to control the lifetime of the initialized place.
    • Crubit, a bindings generator bridging C++ and Rust, currently utilizes super let in a macro for pinned initialization.

The status quo

super let is implemented in the compiler as an unstable feature backing the implementations of pin! and format_args!. This provides them with expressiveness not available to macros written in stable Rust. However, progress on super let has stalled due to unresolved design concerns.

The next 6 months

TaskOwner(s)Notes
Write a super let RFCdianne
Implement new design for super letdianne

The “shiny future” we are working towards

Making it easier to extend the lifetimes of temporaries opens up the possibility of shortening Rust’s default temporary scopes to help prevent bugs from drop-sensitive temporaries living unexpectedly long. This is a continuation of the Temporary Lifetimes 2024 effort.

super let could tie into the ongoing in-place initialization effort. In particular, one potential design direction for super let is to allow functions to produce temporaries when called, effectively extending temporary scopes across function boundaries. As a kind of placing function, these functions would desugar to initialize their temporaries in-place in a higher stack frame. Functions would then be able to return references to temporaries they defined with super let. This would allow APIs like pin! to be expressed as functions rather than as macros. Potentially with pin ergonomics, references taken with &pin mut could be returned from functions as well.

Team asks

TeamSupport levelNotes
compilersmallMay escalate to medium depending on how the feature design turns out.
langlargeWould need a design meeting and RFC review.
libssmallSince super let affects the standard library, the library team should be on-board with any new directions it takes. Additionally, library team review may be required for changes to pin!’s implementation.

Frequently asked questions

reflection and comptime

Metadata
Point of contactOliver Scherer
StatusProposed
RoadmapConstify all the things
Tracking issuerust-lang/rust-project-goals#406
Other Tracking issuerust-lang/rust#142577
Zulip channelN/A
compiler championOliver Scherer
lang championScott McMurray
libs-api championJosh Triplett
Teamscompiler, lang, libs-api, types
Task owners(none)

Summary

Finish the implemented reflection scheme based on const fn that can only be called at compile time. Valdiate it against existing reflection libraries by giving them a nightly feature that obsoletes having derives and makes the derives no-ops. Obtain T-lang and T-libs-api buy-in for the scheme and write an RFC. This proposal is solely for producing const eval values, not for putting types back into the type system. That will be a follow-up once this proposal has a merged MVP.

Motivation

Creating new general purpose crates (like serialization crates, log/tracing crates, game engine state inspection crates) that should work with almost all other data structures is nontrivial today. You either need to locally implement your new traits for other (common) crates, or the other crates need to depend on you and implement your traits. This often hinders rollout and will never reach every crate. Most crate maintainers do not want to depend on 2+ serialization crates, and 3+ logging crates, so they will instead pick one, causing everyone to either pick the large popular crates or be limited in what they can serializer/log. This is a hindrance to innovation and will (imo) long term cause the ecosystem to stop evolving even when an objectively better solution to a problem is found.

Reflection offers a way out of this dilemma, as you can write your logic for all types. You would be processing the type information at runtime (or even preprocess it at compile-time, e.g. in const blocks) without requiring trait bounds on your functions or trait impls anywhere. This means no one but consumers of your serialization/logging/game-engine will need to know about your crate, and you do not need the entire crates.io ecosystem to add derives for your traits. Your consumers immediately are able to interoperate with tuples of any size, arbitrary structs and enums from arbitrary crates that neither depend on yours nor you on theirs.

If this experiment is successful, crates like bevy will be able to “just work” with arbitrary types instead of requiring authors to #[derive(Component)], #[derive(Bundle)], or #[derive(Resource)] their types just to get the bevy_reflect information built at compile-time. Crates like bevy_reflect and facet will still exist, but only as different libraries with different goals and methods for exposing reflection information.

Furthermore it opens up new possibilities of reflection-like behaviour by

  • specializing serialization on specific formats (e.g. serde won’t support changing serialization depending on the serializer https://github.com/serde-rs/serde/issues/2877),
  • specializing trait impl method bodies to have more performant code paths for specific types, groups of types or shapes (e.g. based on the layout) of types.

I consider reflection orthogonal to derives as they solve similar problems from different directions. Reflection lets you write the logic that processes your types in a way very similar to dynamic languages, by inspecting values’ types during the execution of the reflection code, while derives generate the code that processes types ahead of time. Proc macros derives have historically been shown to be fairly hard to debug and bootstrap from scratch (we should totally also improve proc macro workflows). While reflection can get similarly complex fast, it allows for a more dynamic approach where you can easily debug the state your are in, as you do not have to pair the derive logic with the consumer logic (e.g. a serializer) and are instead directly writing just the consumer logic.

Reflection often is not as efficient as derives, as the derives can generate the ideal code ahead of time, but once a fully functioning reflection system has been written for a use case, and performance becomes a problem, it should be significantly easier to now write a derive for the performance critical cases than to have started doing so from the start.

Design axioms

  • Prefer procedural const-eval code over associated const based designs (see also “why not uwuflection” in the FAQ).
    • We picked const fn in general evaluation over associated const based designs that are equally expressive but are essentially a DSL
  • Ensure privacy is upheld, modulo things like size_of exposing whether new private fields have been added
    • This is important to ensure that we cannot break abstractions. We will experiment with allowing const items in the same module to access private fields even if the access is in a comptime fn defined in another crate. Or with a comptime fn defined in the same module of a private field accessing that private field even if called in a const item outside of it.
  • Avoid new semver hazards and document any if unavoidable.
    • e.g. do not expose private fields, methods, or types

The “shiny future” we are working towards

Create basic building blocks that allow facet, bevy-reflect and reflect to process types without requiring derives or trait bounds.

Status quo

The Reflection MVP landed. It implements a TypeId::info method that returns a Type struct. Type has fields that contain information about the type, including kind which tells you whether it’s e.g. a tuple, struct etc.

A new type kind is supported every week, with open PRs for hard ones like Adts and dyn trait

Open PRs:

What we propose to do about it

  • add an attribute for const fn that prevents them from being called from runtime code or const fn without the attribute
    • See the FAQ for why we need #[rustc_comptime] const fn() {} declarations
  • add basic datastructures to libcore that represent common information about types and the APIs to obtain that information

Work items over the next year

TaskOwner(s)Notes
Continue the experiment (land open PRs)Oliver Scherer1
Add more fields to Type and variants to TypeKindOliver Scherer
Restrict information from structs outside current moduleOliver Scherer
Author call for testing blog postOliver Scherer

Team asks

TeamSupport levelNotes
compilerMediumStandard reviews
langLargeDesign meeting, experiment
libs-apiMediumReviews
typesSmallGeneral discussion on any additional type-system changes

Frequently asked questions

Why do you need comptime in addition to reflection?

If we had a bevy_reflect::Type type in libcore and a

#![allow(unused)]
fn main() {
const fn type_of(id: TypeId) -> &'static Type;
}

function, that has the special requirement of, unlike every other const fn, not being callable at runtime, then we could work with type descriptions from normal procedural rust code.

So for this experimental impl we would do

#![allow(unused)]
fn main() {
#[compile_time_only]
const fn type_of(id: TypeId) -> &'static Type;
}

These functions can’t be run at runtime, because that would require there to be some global table somewhere that maps all TypeIds to their repr. This is an obvious no-go in my book.

an demonstration impl (absolutely not salvageable for anything that could be landed!) can be found here

Why not continue where uwuflection left off?

See https://soasis.org/posts/a-mirror-for-rust-a-plan-for-generic-compile-time-introspection-in-rust/ for details on what uwuflection is

Structural processing

it makes procedural processing of type information very hard. E.g. to get the 3rd element of a tuple you need to

#![allow(unused)]
fn main() {
<introwospect_type::<YourType> as FieldDescriptor<3>>
}

so to compute that index you need a constant. you can’t just use a for loop to iterate over the indices.

we chose const fn over associated consts and generics which could compute the same thing as the const fn, just more expensively and mostly purely functional. so going to assoc consts again seems like it goes against that

This can somewhat be resolved by adding a compile-time for loop feature to the language, that will just expand the body N times in a macro/loop-unrolling kind of way.

generic const exprs

in order to use uwuflection in types in generic code you need to either write infallible code with min const generics or you need to add uwuflection bounds (Lots, think typenum) , which defeats the purpose.

Why not go full zig-style comptime?

zig’s approach to comptime from a very high level is effectively

  • generate AST for all source files
  • pick the main function and start compiling it and looking for what it needs to be compiled
  • if a comptime function call is found, look only for what code that needs to compile, compile it and produce the resulting code of the comptime function
  • continue the main compilation, which may now invoke the generated code and start compiling that

we do not experiment with this approach at this time, because the compiler is not set up in a way to permit proc macros from accessing type information from the current crate. While there are ongoing refactorings that go into the direction of potentially allowing more of that in the future, that future seems to be more than 5 years away at my best guess.

  • the compiler is not set up to add AST nodes while type information is already available. It possibly never will, and it would be an immense amount of work to get there. I’m doing lots of refactorings that would need to be done for sth like that anyway, even if the goal is just better incremental and general compilar architecture.
  • there are too many open language questions about it that we haven’t even started to discuss
  • a hacky comptime reflection prototype that works for just tuples and that works with regular const eval exists right now, so pursueing the definitely possible implementation will pay off in a shorter term.

  1. Needs libstd data structures (lang items) to make the specialization data available

Prepare TAIT + RTN for stabilization

Metadata
Point of contactNiko Matsakis
StatusProposed
Contingent onContributor
RoadmapJust add async
Tracking issue
Zulip channel#wg-async
lang championNiko Matsakis
types championlcnr
Teamslang, types
Task owners(none)

Summary

Prepare TAIT (type alias impl trait) and return type notation (RTN) for stabilization together, giving Rust a coherent story for naming and bounding previously unnameable and unboundable types. TAIT lets users name opaque types like closures, async blocks, and complex iterators without boxing. RTN enables bounds like T::method(..): Send, solving the “Send bound” problem and unblocking widespread use of async fn in traits. This goal also extends RTN to async closures via a new RFC. Full stabilization is blocked on the next-gen trait solver work and is intended to happen late this year.

Contingent on contributor: The majority of the impl work for TAIT and RTN has been done however the syntactic design for RTN and async closures is incomplete. Niko Matsakis is seeking someone willing to help work on the RFC and explore the design space as well as to finalize impl details.

Motivation

The status quo

TAIT: naming the unnameable

Many Rust types cannot be written explicitly. Closures, async blocks, complex iterator chains, and nested combinators all produce anonymous types that have no surface syntax. Today, the only way to use these types in a type alias, struct field, or associated type is to box them (Box<dyn Trait>) or restructure code to avoid naming them entirely.

Type alias impl trait (TAIT) solves this by letting you write impl Trait in type alias position:

#![allow(unused)]
fn main() {
// Name a complex iterator type without spelling it out
type OddIntegers = impl Iterator<Item = u32>;

fn odd_integers(start: u32, stop: u32) -> OddIntegers {
    (start..stop).filter(|i| i % 2 != 0)
}
}

The concrete “hidden type” is inferred by the compiler, so callers see only the trait bounds. This is valuable for hiding implementation details, simplifying complex type signatures, and, critically, implementing associated types in traits without boxing:

#![allow(unused)]
fn main() {
impl MyTrait for MyType {
    type Output = impl Iterator<Item = u32>;  // no Box<dyn> needed

    fn produce(&self) -> Self::Output {
        self.items.iter().filter(|x| x.is_valid()).copied()
    }
}
}

TAIT is available on nightly under the feature flag type_alias_impl_trait. See the impl trait initiative for more details.

RTN: the Send bound problem

Async fn in traits (AFIT) has been stable since Rust 1.75, but when users attempt to use it in a public trait, they get a warning:

#![allow(unused)]
fn main() {
pub trait Foo {
    async fn bar();
}

// warning: use of `async fn` in public traits is discouraged as auto trait bounds cannot be specified
//  --> src/lib.rs:2:5
//   |
// 2 |     async fn bar();
//   |     ^^^^^
//   |
//   = note: you can suppress this lint if you plan to use the trait only in your own code, or do not care about auto traits like `Send` on the `Future`
//   = note: `#[warn(async_fn_in_trait)]` on by default
// help: you can alternatively desugar to a normal `fn` that returns `impl Future` and add any desired bounds such as `Send`, but these cannot be relaxed without a breaking API change
//   |
// 2 -     async fn bar();
// 2 +     fn bar() -> impl std::future::Future<Output = ()> + Send;
//   |
}

This warning is highlighting a problem known as the “Send bound” problem, which means that generic functions referencing a trait with async functions (or any impl Trait-returning function) cannot specify that this async function must return a Send future. This blocks ecosystem crates like Tower from using AFIT in their public APIs.

Return type notation (RTN), proposed in RFC #3654, solves this by letting you write:

#![allow(unused)]
fn main() {
fn spawn_service<S>(service: S)
where
    S: Service,
    S::call(..): Send,  // RTN: the future returned by `call` must be Send
{
    tokio::spawn(async move {
        service.call(request).await
    });
}
}

RTN has been fully implemented and is available on nightly under the feature flag return_type_notation.

RFC #3654: https://rust-lang.github.io/rfcs/3654-return-type-notation.html

RTN for async closures

RTN solves the Send bound problem for trait methods, but what about async closures? Consider this function:

#![allow(unused)]
fn main() {
async fn foo<F>(x: F)
where
    F: AsyncFn(&str) -> Option<()>,
{
    tokio::spawn(x("hello"));
}
}

This doesn’t compile because tokio::spawn requires a Send future, but we have no way to express that x() returns one. The F::method(..) syntax doesn’t work because there is no method name to reference.

The async closure RFC mentioned a syntax like F(..): Send, but this wasn’t widely discussed during that RFC process. We’d like to explore the syntactic design space, author an RFC, and implement this on nightly.

Why stabilize RTN and TAIT together?

TAIT and RTN are deeply connected: RTN can be used to model TAIT, and both deal with bounding and naming opaque types. A stabilization PR for RTN was opened but had to be closed because RTN’s ability to name opaque types in arbitrary positions interacts with unresolved questions around TAIT and ATPIT (associated type position impl trait). Since RTN can model TAIT, stabilizing them separately risks locking in behaviors that would be awkward or wrong to change later. Rather than rushing RTN stabilization alone, this goal focuses on getting both ready so they can stabilize together, giving Rust a coherent story for bounding opaque types regardless of how they’re expressed.

Dependency on the next-gen trait solver

Full stabilization is blocked on the next-gen trait solver work and is intended to happen late this year.

What we propose to do about it

We propose to prepare RTN for stabilization by:

  • Investigating what’s needed from the lang side for TAIT: RTN can be used to model TAIT, so it makes sense to stabilize them together. Both are very useful, and we need to understand what lang work TAIT requires.
  • Updating the stabilization report to address the concerns raised in the closed stabilization PR, so that once TAIT is resolved, RTN stabilization can proceed without delay.
  • Extending RTN to async closures via a new RFC and nightly implementation. This work is independent of the TAIT blocker and can proceed in parallel.

Looking for contributors

Niko Matsakis is looking to mentor one or more contributors on this goal. The work spans language design (RTN for async closures RFC), compiler implementation (nightly implementation of async closure RTN), and stabilization preparation (researching TAIT interactions, updating the stabilization report). This is a great opportunity to get involved in Rust’s type system and async ecosystem. Reach out to Niko Matsakis if you’re interested.

Work items over the next year

TaskOwner(s)Notes
Research lang-side requirements for TAITNiko MatsakisWhat’s needed before RTN can stabilize
Update stabilization reportAddress concerns from closed PR
RFC for RTN on async closuresNiko MatsakisF(..): Send syntax, explore design space
Implement RTN for async closuresAfter RFC acceptance

Team asks

TeamSupport levelNotes
langMediumRFC review, design discussions
typesMediumStabilization report review, TAIT interactions

Frequently asked questions

Why not stabilize RTN now?

The stabilization PR was closed because RTN allows naming opaque types in positions that weren’t previously possible. As lcnr noted:

RTN allows naming opaque types in arbitrary positions. This means we get nearly all implementation issues preventing TAIT, at least in theory.

The concern is that stabilizing RTN could lock in behaviors that would conflict with how TAIT/ATPIT need to work. Opaque types have a history of stabilizing features that “won’t affect the future” and then being wrong. Rather than risk that, we want to get everything ready for stabilization and then stabilize once TAIT is resolved.

How does this relate to the “Just add async” roadmap?

RTN is the key to making async fn in traits usable in practice. Without it, trait authors must choose between:

  • Using async fn but preventing generic code from requiring Send
  • Using explicit -> impl Future<Output=T> + Send but losing the ergonomics of async fn

RTN eliminates this tradeoff, letting patterns from sync Rust transfer naturally to async.

Stabilize Rust for Linux compiler features

Metadata
Point of contactTomas Sedovic
StatusProposed
RoadmapRust for Linux
Tracking issuerust-lang/rust-project-goals#407
Zulip channel#rust-for-linux
compiler championWesley Wiser
Teamscompiler
Task owners(none)

Summary

Develop and stabilize compiler features that Rust for Linux uses. This is a continuation of the existing Rust for Linux effort.

Motivation

Getting the Linux kernel to build with stable Rust and, more generally, supporting the needs of the Linux kernel to make Rust a success there, has been a priority for the Rust project and a previous flagship goal: 2024H2, 2025H1.

One of the key areas are compiler features, which encompass a wide range of topics: architecture/target-related flags, sanitizers, mitigations, performance/optimization-oriented flags, and so on.

The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. We’re sticking to the Don’t let perfect be the enemy of good approach. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of functionality that meets the kernel developers’ needs while leaving other aspects unstable.

The status quo

The Linux kernel, at the time of writing, relies on some Rust compiler unstable features such as:

There are others that we will want to start using in the future, such as:

There is also the build-std project goal support that we need as well (or, rather, only “build-core” for the Linux kernel), and the sanitizers project goal.

What we propose to do about it

We track each compiler feature we’re interested in and move them forward towards stabilization. Historically, this was done by either compiler developers or the Rust for Linux team members.

Work items over the next year

Ideally, the Linux kernel would not need to rely on any of the existing compiler unstable features by the time the period is over, but that is fairly unlikely. Thus, any progress on any feature (or an alternative to using a given unstable feature) would be welcome.

In particular, finishing the work and stabilizing the features that the kernel is already using upstream would be considered a major success.

Longer-term, the Linux kernel does not rely on any compiler-related unstable feature anymore, except for those that may need to be added in the future for different reasons, such as:

  • New hardware features.
  • New mitigations.
  • New sanitizers.
  • New architectures.

For that reason, this goal is conceptually never ending, even if we may reach points where no unstable compiler feature is actually used.

Team asks

TeamSupport levelNotes
compilerMediumReviews, RfL meetings

Normative Documentation for Sound unsafe Rust

Metadata
Point of contactPete LeVasseur
StatusProposed
RoadmapSafety-Critical Rust
Tracking issue
Zulip channelN/A
opsem championRalf Jung
Teamslang, lang-docs, libs-api, opsem
Task owners(none)

Summary

The Safety-Critical Rust Consortium will investigate real-world safety-critical codebases to identify common unsafe patterns, then work with t-opsem to create normative documentation in the Rust Reference and standard library docs.

Motivation

The status quo

Rust’s unsafe documentation has gaps. The Rustonomicon self-describes as “incomplete” and the Unsafe Code Guidelines Reference is “largely abandoned.” Neither is normative. When developers need to know whether a specific unsafe pattern is sound, they often find no authoritative answer.

This matters acutely in safety-critical domains. Automotive, medical, and aerospace software must demonstrate code behaves correctly. Without normative documentation, developers cannot build rigorous safety cases for unsafe code.

The zerocopy crate established a model: annotate every unsafe block with rationale citing official Rust documentation; when documentation is insufficient, work with t-opsem to improve it (e.g., rust-lang/rust#114902(https://github.com/rust-lang/rust/issues/114902) for addr_of! semantics).

What we’ll do

We’ll apply the zerocopy model systematically, starting with Eclipse iceoryx2, a zero-copy IPC framework with ~3,300 unsafe usages. The process:

  1. Catalog unsafe patterns in the codebase
  2. Identify which patterns lack normative documentation
  3. Work with t-opsem to establish correct safety contracts
  4. Submit PRs to the Rust Reference and std docs

Priority areas include cross-process synchronization, memory-mapped regions, cross-process atomics, and UnsafeCell in shared memory—patterns common in systems programming but underdocumented.

The “shiny future”

Developers writing unsafe code can cite authoritative documentation for safety contracts. Safety-critical projects can build rigorous safety cases. The patterns documented benefit the entire ecosystem, not just safety-critical users.

Team asks

TeamSupport levelNotes
opsemLargeReview unsafe patterns, establish safety contracts, guide documentation
libs-apiSmallPR reviews for core/std public documentation; feedback on approach.
langSmallFeedback on language semantics questions as needed
lang-docsSmallStandard PR reviews for Rust Reference

FAQ

Why iceoryx2?

It’s a pure-Rust safety-critical IPC framework with extensive unsafe usage (shared memory, lock-free structures, FFI). The patterns it uses appear throughout the systems programming ecosystem.

Won’t this overwhelm t-opsem?

No. Most usages fall into ~20 pattern categories, of which 5-7 need new normative documentation. We’re asking t-opsem to help with genuinely novel questions, not review thousands of individual usages.

How does this differ from cataloging undefined behavior?

We document safety contracts (what you must do to be sound), not undefined behavior (what happens when you’re unsound). The Rust Reference’s UB list is intentionally non-exhaustive; we respect that approach.

Establish a Spot for Safety-Critical Lints in Clippy

Metadata
Point of contactPete LeVasseur
StatusProposed
RoadmapSafety-Critical Rust
Tracking issue
Zulip channelN/A
Teamsclippy
Task owners(none)

Summary

Establish a sustainable arrangement for the Safety-Critical Rust Consortium to contribute and maintain lints within the Clippy ecosystem, with the goal of adding productive members of the clippy team with a focus on lints useful in functional safety.

Motivation

Safety-critical development requires enforcing project-specific coding standards. The Safety-Critical Rust Consortium is developing coding guidelines that will need to be reduced to practice through tooling. This effort will generate a significant volume of new lints, potentially 50 to 200 over the next one to two years.

Many of those lints are useful outside of safety-critical, but often in the pedantic category.

The status quo

The Consortium needs custom lints to enforce its coding guidelines. While alternative approaches exist (such as Dylint for dynamic lint loading), the Consortium prefers to work within the community embraced tool rather than maintain a fork or separate tool. This aligns with the broader goal of Rust adoption in safety-critical domains: using standard, well-supported tools rather than fragmenting the ecosystem.

The challenge is scale. The Clippy team has significant experience in lint design and review, but an organized effort to add 50 to 200 lints could potentially strain review capacity if not managed thoughtfully.

Exploratory MISRA C to FLS mapping analysis

As an exploratory measure, a mapping of 223 MISRA C:2025 guidelines to the Ferrocene Language Specification (FLS) was performed based on the MISRA C:2025 Addendum 6: Applicability of MISRA C:2025 to the Rust Programming Language. This work was done independently and is not yet normative Consortium guidance, though it may become a Consortium artifact if deemed viable and useful.

The mapping reveals the scope of potential lint needs:

CategoryCountNotes
Total guidelines223MISRA C:2025
Directly applicable to Rust68Need some form of enforcement
Already covered by rustc/Clippy13dead_code, unreachable_code, etc.
Requiring custom lint support~50Beyond current Clippy coverage

That’s leaving aside the other mapping being done to CERT C and the coding guidelines which may apply only to Rust.

The next year

The Clippy team has offered mentorship and onboarding support to help SCRC contributors become effective lint developers and reviewers. The envisioned process:

  1. Initial phase (1 to 2 months): Clippy team provides hands-on mentorship for a small group of SCRC lint developers, reviewing lint designs in issues and PRs and providing guidance on lint design and implementation patterns. Some members of the SCRC employ clippy contributors that could play the role of a mentor.

  2. Transition phase: As SCRC contributors gain experience, they take on more review responsibility for safety-critical lints, with Clippy team available for consultation on complex cases.

  3. Steady state: SCRC maintains its lints with minimal ongoing burden on the Clippy team. SCRC reviewers are members adding to general Clippy review capacity, with a focus point, as all other members.

TaskOwner(s)Notes
Finalize arrangement for SCRC lints in ClippyClippyDetermine crate/group structure (see options below)
Identify initial SCRC lint developersConsortium2–3 people to receive initial mentorship
Onboarding and mentorship periodClippy + Consortium~1–2 months of active guidance
Implement initial set of safety-critical lintsConsortiumStarting with highest-priority coding guidelines
Establish SCRC review capacityConsortiumEnable self-sufficient lint review over time
Document lint design patterns for safety-critical use casesConsortium + ClippyCapture lessons learned for future contributors

Possible arrangements

The specific structure for SCRC lints within Clippy is still under discussion. Two options are being considered:

Option A: Separate crate for SCRC lints

A dedicated crate within the Clippy repository for safety-critical lints. This approach:

  • Provides a clear boundary for SCRC-maintained code
  • Allows experimentation without affecting existing Clippy lints
  • Lints could be organized as a dedicated lint group that users can enable/disable
  • Aligns with ongoing Clippy work to split lints into multiple crates

Option B: Direct integration into Clippy

SCRC lints go directly into Clippy, potentially starting in a separate lint group (e.g., restriction or a new safety-critical group). This approach:

  • Integrates safety-critical lints into the standard tool from the start
  • Leverages existing Clippy infrastructure without additional crate boundaries
  • Lints that make sense for general use can be promoted to other groups over time

Both options share the same mentorship model and goal of building SCRC’s self-sufficiency. The choice affects organizational structure rather than the fundamental collaboration approach.

The “shiny future” we are working towards

The Clippy ecosystem accommodates safety-critical lint development as a first-class use case:

  1. SCRC can develop and maintain lints needed for coding guideline enforcement
  2. The arrangement scales without overburdening the Clippy team
  3. Safety-critical users benefit from community tooling rather than fragmented alternatives
  4. Cross-pollination between SCRC and Clippy improves both efforts

Design notes

Why not a fork or separate tool?

The Consortium considered alternatives like maintaining a Clippy fork or using Dylint, but prefers working within the community tool:

  • Forks split maintenance effort and create confusion about which tool to use.
  • Dylint requires managing lint-driver-compiler version coordination and lacks official Rust Project support
  • Community integration means safety-critical users get a standard, well-supported tool. Many safety-critical techniques are generally applicable methodologies and community exchange is worthwhile.
  • Configuration consistency All lints can be configured in one program.

Relationship to stable API investigation

The original goal proposal focused on investigating stable APIs for custom lints (via Stable MIR or other mechanisms). That investigation remains valuable for the long term, particularly for lints requiring deep analysis like whole-program call graphs, but is not a prerequisite for the immediate work of contributing lints to Clippy.

Team asks

TeamSupport levelNotes
clippySmallInitial onboarding support for SCRC contributors; guidance on lint design

Resources committed: The Consortium will commit engineering time for lint development, with the goal of becoming self-sufficient in review capacity over time. Members committment: Consortium members are willing to bring staff with experience in mentoring.

Frequently asked questions

Won’t 50–200 lints overwhelm the Clippy team?

This is exactly what the mentorship model addresses. Rather than the Clippy team reviewing all SCRC lints indefinitely, the goal is to build SCRC’s capacity to review their own lints. The Clippy team’s investment is front-loaded: intensive mentorship for 1 to 2 months, then decreasing involvement as SCRC contributors become proficient. If review capacity becomes strained, we can revisit the arrangement.

Clippy already maintains a lot of lints, so there is experience in managing the scale.

What about lints that need deep analysis (call graphs, cross-crate)?

Some safety-critical lints, like detecting recursion or tracking allocation across modules, require analysis capabilities beyond what’s easily accessible today. These lints may need to:

  • Use existing internal APIs (with the understanding that maintenance across compiler versions requires effort)
  • Wait for stable APIs (Rustc Public / Stable MIR) to mature
  • Be implemented as external tools initially

The immediate focus is on lints that can be implemented with current Clippy infrastructure. More complex lints are a longer-term challenge that may warrant separate investigation.

How does this relate to safety-qualification of Clippy?

Some safety-critical companies are exploring safety-qualification of Clippy or Clippy-like tooling. Having SCRC lints within Clippy (rather than a fork) supports this effort by:

  • Keeping the codebase unified
  • Allowing qualified toolchains to include these lints with minimal divergence from upstream
  • Building a community of reviewers familiar with safety-critical lint requirements

What specific lints will SCRC contribute?

The initial focus will be lints that enforce the Consortium’s coding guidelines. Priority will be determined by:

  1. Guidelines with highest safety impact
  2. Lints implementable with current Clippy infrastructure
  3. Lints likely useful beyond safety-critical contexts (for potential promotion to general Clippy groups)

The exploratory MISRA C:2025 mapping provides a starting point, but the Consortium will also consider domain-specific needs from automotive, aerospace, medical, and other safety-critical sectors.

Sized Hierarchy and Scalable Vectors

Metadata
Point of contactDavid Wood
StatusProposed
RoadmapUnblocking dormant traits
Tracking issuerust-lang/rust-project-goals#270
HighlightLanguage changes
compiler championDavid Wood
lang championNiko Matsakis
libs-api championAmanieu d’Antras
types championlcnr
Teamscompiler, lang, libs-api, types
Task owners(none)

Summary

Over the next year, we will build on the foundational work from 2025 to stabilize the Sized trait hierarchy and continue nightly support for scalable vectors:

  • Stabilize the refined Sized trait hierarchy (without constness), unblocking extern types
  • Propose and implement const Sized to support scalable vectors
  • Achieve RFC acceptance for rfcs#3838 (Scalable Vectors)
  • Land SVE types and intrinsics in stdarch for nightly experimentation
  • Continue addressing stabilization blockers for SVE itself
  • Begin design work for supporting the Scalable Matrix Extension (SME)

The const Sized work (Part II of rfcs#3729) is deferred to a future goal, allowing us to deliver value sooner through the trait hierarchy stabilization. This future work interacts with ongoing const generics efforts, as const Sized depends on progress in const traits.

Motivation

Arm has introduced Scalable Vector Extensions (SVE) and Scalable Matrix Extensions (SME) - powerful SIMD capabilities where vector register width depends on the CPU implementation rather than being fixed at compile time. Hardware is generally available, and key Rust stakeholders (Google, Huawei, Microsoft) have expressed urgent desire for SVE support in Rust.

The problem: Scalable vectors don’t fit Rust today for three reasons:

  1. At the language level, Rust’s Sized/?Sized distinction is too coarse - it only distinguishes between types whose “size is known at compile time” and whose “size is in metadata.” Scalable vectors need a third category: types whose size is constant at runtime but unknown at compile time.
  2. Unlike fixed-size SIMD types, using scalable vector types require the architecture support to be present for even the simplest operations to be possible (e.g. returning scalable vectors from functions). At the language level, this will necessitate some ability to require the relevant target features be present when scalable vectors are used, which is especially tricky with trait implementations and generic functions.
  3. At the compiler level, we need new infrastructure to generate code for scalable vector types and their intrinsics.

The opportunity: By extending Rust’s type system with a richer Sized hierarchy and adding support for scalable vectors, we can support SVE in AArch64 as well as support for similar features in other architectures, like RISC-V’s “V” Vector Extension; we also unblock other long-requested features like extern types.

Since SVE requires a change to the C standard, Rust has an opportunity to be the first systems programming language with native support for these hardware capabilities.

The status quo

Significant progress was made in 2025:

  • Sized Hierarchy: Part I (rust#137944) has been merged, introducing new non-const sizing traits behind the sized_hierarchy feature gate
  • Scalable vector infrastructure (rust#143924) has been merged, adding experimental rustc_scalable_vector(N) attribute support
  • Hierarchy of Sized traits (rfcs#3729) is being implemented experimentally

See the tracking issues for the Sized Hierarchy prerequisite (rust#144404) and for Scalable Vectors themselves (rust#145052).

What we propose to do about it

In 2026, we plan to factor out a subset of [RFC 3729] that can be stabilized independently: traits like SizeOfVal that don’t require const trait support. This subset unblocks extern types (RFC 1861), a long-requested feature, while the const-specific portions needed for SVE itself remain experimental pending progress on const traits.

Our design axioms:

  • Avoid overfitting. Extensions to Rust’s type system should not be narrowly tailored to SVE/SME, but should support similar extensions from other architectures and unblock other desired Rust features where practical.
  • Low-level control. Rust should leverage the full capabilities and performance of the underlying hardware features.
  • Rusty-ness. Extensions should align with Rust’s design principles and feel like natural extensions of the type system.

The ultimate goal is stable SVE support in Rust, enabling high-performance SIMD code that works across AArch64 implementations with varying vector register widths. Following SVE, adding support for Scalable Matrix Extensions (SME) is the next logical step, enabling efficient matrix processing in Rust.

Work items over the next year

TaskOwner(s) or team(s)Notes
Stabilize Sized trait hierarchyDavid WoodUnblocks extern types
Achieve RFC acceptance for rfcs#3838David WoodScalable Vectors RFC
Update and reopen stdarch SVE PRDavid WoodSVE types and intrinsics
Address SVE stabilization blockersDavid WoodIdentify and resolve blockers
SME design explorationDavid WoodUnderstand implications for Rust

Team asks

TeamSupport levelNotes
compilerSmallStandard reviews for stabilization and SVE work
langMediumRFC decision for rfcs#3838, stabilization sign-off
libs-apiMediumReview RFC; review and approve stdarch SVE APIs
typesMediumType System implementation and stabilization sign-off

Frequently asked questions

What changed from the 2025 goal?

The 2025 goal laid the groundwork: Part I of the Sized Hierarchy was merged, the core scalable vector infrastructure was merged, and RFC 3729 was accepted. The 2026 goal pivots to focus on stabilizing the Sized trait hierarchy as a standalone win that unblocks extern types, while SVE continues as a nightly experiment with stdarch intrinsics.

Why stabilize the trait hierarchy separately from const Sized?

The Sized trait hierarchy provides value independent of scalable vectors: it unblocks extern types, a long-requested feature. By stabilizing the non-const portions first, we deliver value sooner. The const Sized work (Part II of RFC 3729) has dependencies on const traits and is deferred to a future goal.

How does this unblock extern types?

Extern types need a way to express “this type has no known size, not even at runtime.” The current ?Sized bound conflates “unsized but has metadata” with “truly sizeless.” The refined trait hierarchy allows distinguishing these cases, which is the key blocker for extern types.

rust-lang/rust-project-goals#270: https://github.com/rust-lang/rust-project-goals/issues/270

Stabilize concrete type specialization

Metadata
Point of contactTyler Mandry
StatusProposed
Contingent onFunding
Tracking issue
Zulip channelN/A
Help wantedN/A
Other tracking issuesrust-lang/rust#31844
Teamscompiler, lang, libs, opsem, types
Task owners(none)

Summary

Follow stabilization of the new trait solver this year by stabilizing a subset of specializing impls: Impls that follow the always applicable rule. This roughly corresponds to specializing trait impls on concrete types.

Motivation

The status quo

Specialization has been blocked for many years for a combination of reasons:

  • Soundness issues in the original design.
  • Limitations of the trait solver causing issues like this one, preventing us from stabilizing even a subset.
  • Missing functionality, plus uncertainty about what a “minimally viable product” looks like.

The second issue may get resolved soon, with the stabilization of the next-gen trait solver.

There are many use cases for specialization that only require specializing an impl for all instances of a given type, or that otherwise follow the basic “always applicable” rule. These are widely understood to be sound, sidestepping the first issue. They also do not require lifting some of the existing limitations, including the lack of useful associated type defaults and the inability to override items together.

Math libraries

A math library might want to implement an operation that works for any type that implements Add and Mul, while still making use of specialized SIMD intrinsics for the f32 and f64 types.

Customizing Try for particular error types

Abseil has a feature to track the source location at each step an error is propagated, without relying on a much slower backtrace feature.

Today the only way to do this is with a custom try_status!() macro in place of ?. When the Try trait is stable, it will be possible with a custom StatusOr<T> type that takes the place of Result<T, StatusError>. Unfortunately, this won’t interoperate very well with everyday Rust code that expects a Result.

Specializing FromResidual on the Result<T, StatusError> would allow us to preserve the source location when ? is used anytime the error is StatusError:

#![allow(unused)]
fn main() {
impl<T> FromResidual<Result<!, StatusError>> for Result<T, StatusError> {
    #[track_caller]
    fn from_residual(residual: Result<!, StatusError>) -> Self {
        let location = Location::caller();
        residual
            .map_ok(|bang| match bang {})
            .map_err(move |err| err.with_source_location(location))
    }
}
}

In-place initialization

Crubit’s ctor crate implements a trait called Ctor that can be used to construct a value in-place. The intention is that you can write a function signature like this to accept a constructor for some type:

#![allow(unused)]
fn main() {
fn takes_foo(ctor: impl Ctor<Output = Foo>) { ... }
}

Regular types implement Ctor for themselves.

#![allow(unused)]
fn main() {
impl<T> Ctor for T {
    type Output = T;
    unsafe fn ctor(self, dest: *mut Self::Output) {
        dest.write(self);
    }
}
}

However, there are also a number of “combinator” helper types that override this default implementation. For example, FnCtor, which calls a function on the desired out pointer.

Today this is only possible with a hack, by adding an artificial T: Unpin bound on the blanket impl and artificially marking combinators as !Unpin. Besides the usual confusion of dealing with the Unpin trait, this bound is incorrect: It is entirely valid to initialize a !Unpin type by moving it, as long as you can access the type by value (in other words, as long as it isn’t pinned). This bound has led to a lot of user headaches when dealing with !Unpin types like futures.

The reason for using an associated type Output instead of a generic on the trait (Ctor<T>) is that it better expresses the intent: Every type has only one Ctor::Output type. Most types output themselves, but special combinators like FnCtor output a different type. In practice, when a feature like RFC 1672 “Disjointness based on associated types” is implemented, it would allow us to write impls like following. Note that this would not be possible with a generic trait: The trait system assumes that the same type could implement both Ctor<Foo> and Ctor<Bar>, leading to an overlap error.

#![allow(unused)]
fn main() {
impl <I: Ctor<Output = Foo>> From<I> for MyType {..}
impl <I: Ctor<Output = Bar>> From<I> for MyType {..}
}

Overriding drop glue

If Destruct were a trait that defines the “true destructor”, it could be overridden for some types. See the goal for #[manually_drop] for use cases.

This idea can potentially be extended to other builtin language behavior.

What we propose to do about it

Specialization has long been blocked on a rewrite of the trait solver, and the next-gen trait solver is set to stabilize this year. We should capitalize on this success by shipping a much-anticipated feature later this year.

Specifically, stabilize specializing impls that follow the “always applicable” rule. Leave extensions to the rule for later.

Future extensions

As part of this work we should survey unsupported use cases mentioned in the original RFC and note

  • Whether we may want to support them
  • Whether we have an idea of how to support them
  • Whether the ideas seem plausible to implement
  • Whether the ideas are true extensions of the subset being stabilized

Unresolved design concerns

Most design concerns mentioned on the original tracking issue have been resolved in follow up work like the associated type defaults RFC or concern future extensions that do not need to be shipped as part of the MVP.

While not mentioned on the tracking issue, there is a question of whether impls overriding defaults should be marked as such with #[override] or something similar.

Verifying soundness

There have been many issues found with specialization over the 10 years since the RFC was opened. While we are fairly confident this subset of specialization is sound, it would be nice if we could model it in a-mir-formality or with another formal verification tool to check our intuition. The past issues found can provide inspiration for which soundness properties to model.

Work items over the next year

TaskOwner(s)Notes
Survey use cases
Model subset in a-mir-formality
Separate out feature gate
Write stabilization report

Team asks

TeamSupport levelNotes
compilerSmall
langMediumResolve design concerns like #[override] and review stabilization
libsSmall
opsemSmall
typesLargeReview future extensions for plausibility, soundness, and stabilization

Frequently asked questions

Stabilize MemorySanitizer and ThreadSanitizer Support

Metadata
Point of contactJakob Koschel
StatusProposed
Tracking issuerust-lang/rust-project-goals#403
Zulip channelN/A
HighlightOther
Teamsbootstrap, compiler, infra, project-exploit-mitigations
Task owners(none)

Summary

Stabilize the MemorySanitizer and ThreadSanitizer support. This includes fixing open bugs for the sanitizers to open a path for stabilization and the necessary infrastructure changes to provide precompiled and instrumented standard libraries for the sanitizers.

Motivation

Sanitizers help with increasing the robustness and security of software and have been increasingly adopted as part of the software development life cycle. Even though the Rust programming language provides memory and thread safety guarantees, use of Unsafe Rust and foreign code in mixed-language binaries do not provide the same memory and thread safety guarantees. Thus, [support for sanitizers must be added to the Rust compiler for secure Rust adoption](https://hackmd.io/Ramon de C Valle/S1Ou9K6H6#Organize-and-stabilize-support-for-sanitizers).

In order for them to be properly usable, the sanitizer support should be stabilized so it is no longer required to use a nightly toolchain and build your own standard libraries.

In the future we want to stabilize all sanitizers (including memtag, cfi, kcfi, safestack, shadow-call-stack) and support them on all targets supported by the Rust compiler. In the meantime we work towards at least supporting Tier 1 targets for all of them.

The status quo

Currently, there is unstable support for several sanitizers (address, hwaddress, memtag, memory, thread, leak, cfi, kcfi, safestack, shadow-call-stack). The AddressSanitizer and LeakSanitizer (that do not require rebuilding an instrumented standard library) are close to being stabilized (https://github.com/rust-lang/rust/pull/123617). We’ve just merged a new Tier 2 target (https://github.com/rust-lang/rust/pull/149644) for AddressSanitizer to allow using it with a stable compiler and are planning to repeat same process now for MemorySanitizer and ThreadSanitizer.

What we propose to do about it

We start with stabilizing the MemorySanitizer and ThreadSanitizer and pick the rest as they come.

Work items over the next year

The goal is to stabilize MemorySanitizer and ThreadSanitizer for Tier 1 targets and provide a way to use them without rebuilding the standard library (which currently is also behind an unstable flag). This requires a way to ship sanitizer instrumented standard libraries (for Memory- and ThreadSanitizer) through rustup.

Team asks

TeamSupport levelNotes
infraSmall
compilerMediumReviews, stabilization
bootstrapMediumDedicated reviewer
project-exploit-mitigationsMediumDedicated reviewer

Stabilize Cargo SBOM precursor

Metadata
Point of contactSergey Davidoff
StatusProposed
Contingent onContributor
RoadmapSecure your supply chain
Tracking issue
Other tracking issueshttps://github.com/rust-lang/cargo/issues/16565
Zulip channelN/A
Teamscargo
Task owners(none)

Summary

Progress towards an MVP version of Cargo SBOM support by resolving known issues in Cargo’s SBOM precursor feature and finalizing the RFC.

Contingent on contributor: This goal needs contributors to help with testing, resolving known issues in Cargo’s SBOM precursor, and converting downstream tooling like cargo-cyclonedx. The work is primarily in the rust-lang/cargo repository. Estimated time commitment: TBD.

Motivation

Software Bill of Materials is a list of project dependencies and their versions, analogous to Cargo.lock, in a format standardized across programming languages. They enable supply chain transparency and allow easily identifying dependencies with known vulnerabilities.

SBOMs are turning from a best practice to being mandatory. In the US Executive Order 14028 requires the federal government to only purchase software from vendors who provide a Software Bill of Materials for each product. In the EU the Cyber Resilience Act mandates that any product with “digital elements” sold in the EU must have an SBOM as part of its technical documentation; obligations for reporting vulnerabilities begin in September 2026, with full compliance required by December 2027. Many other jurisdictions have similar regulations.

The status quo

The crucial missing piece for SBOM generation for Rust+Cargo projects is accurate reporting of the dependency tree. cargo metadata falls short in multiple ways. This results in either false negatives or false positives in the reported dependency tree.

The SBOM precursor feature in Cargo addresses this by providing a mechanism to accurately report the dependency tree used in a given build. However, it is nightly-only, not yet widely used, and has at least one known issue.

Inaccurate SBOMs lead to false positives on vulnerability scans and/or compliance issues.

What we propose to do about it

  1. Complete the RFC for this feature and get it accepted
  2. Resolve the already known issue(s) in the Cargo SBOM precursor feature
  3. Modify cargo-cyclonedx to use the Cargo SBOM precursor as a data source, to prove that it can be used to generate a complete and accurate SBOM in an industry standard format
  4. Address any issues that point 2 uncovers in the Cargo SBOM precursor feature
  5. Stabilize the MVP that is sufficient to power cargo-cyclonedx and cargo-auditable

Work items over the next year

TaskOwner(s)Notes
Complete the RFCSergey Davidoff et al.
Resolve known issuesSergey Davidoff et al.
convert cargo-cyclonedx to use the SBOM precursorSergey Davidoff et al.outside the Rust Project repositories, no Rust Project mentorship needed
Resolve newly uncovered issuesSergey Davidoff et al.
Stabilize the MVPSergey Davidoff et al.

I am in the process of applying for funding for this work, together with collaborators I’m not sure I can disclose. The amount of time we can dedicate to the project will depend on the outcome of that application. It is possible that the funding will only materialize in the second half of the year or not at all.

Team asks

We will need:

  • Guidance to get the RFC finalized and accepted
  • A handful of 30-minute design meetings with someone on the Cargo team to guide fixing the implementation issues
  • Guidance on the stabilization process
TeamSupport levelNotes
cargoMedium

Frequently asked questions

TODO - will fill in based on the review comments

Stabilize FLS Release Cadence

Metadata
Point of contactPete LeVasseur
StatusProposed
RoadmapSafety-Critical Rust
Tracking issue
Zulip channel#t-lang/fls
Teamsfls, spec
Task owners(none)

Summary

Establish a predictable release cadence for the FLS, with each version published within six weeks of the corresponding Rust stable release.

Motivation

The status quo

The FLS serves as one specification for the Rust language. For it to be useful as a reference, it needs to track stable Rust releases in a timely manner.

In 2025H2, the FLS capabilities goal explored options for sustainable FLS maintenance and established an FLS team. That exploratory work identified a six-week release cadence as achievable. This goal formalizes that cadence and demonstrates it in practice.

What we propose to do about it

We will establish a six-week release cadence: FLS version N will be published within six weeks of Rust stable version N. This means FLS N is available before Rust N+1 ships, which aligns with Rust’s release train and leaves adequate time for specification work while remaining timely.

This involves setting up the tooling and processes to sustain this cadence, then demonstrating it works by shipping on schedule for the releases in this goal period.

Design axioms

  • Predictability: Users can plan around a known schedule. FLS N arrives before Rust N+1 ships.
  • Timeliness: Six weeks balances thoroughness with relevance; the specification remains current.
  • Sustainability: The cadence is achievable with existing FLS team capacity, avoiding burnout or quality degradation.
  • Process clarity: Working on releases sequentially keeps the scope of each release well-defined.
  • Ecosystem alignment: The cadence mirrors Rust’s release train, making it easy to communicate and reason about.

The “shiny future” we are working towards

A predictable FLS release cadence is foundational infrastructure for broader goals:

  • Safety-critical adoption: Organizations pursuing certification (ISO 26262, IEC 61508, DO-178C) require specification documents that track the language version they are certifying against. Predictable FLS releases make it feasible to plan certification timelines around known specification availability.
  • Tighter integration with Rust releases: Once the six-week cadence is proven, we can explore starting specification work earlier by tracking Beta release note issues, giving a 12-week window. This may eventually enable same-week or same-day FLS releases aligned with Rust stable.
  • Tooling and automation: A consistent cadence creates opportunities for automated checks, diff generation, and integration with other Rust documentation infrastructure. One advantage of such automation could be generation of the FLS changelog, which at the moment is a manual process.

Phased approach

Phase 1: Stable release notes (this goal period)

We will target starting from when the release notes are made available for the Stable Rust compiler release. In 2025 this is how we operated and would give us a six week cycle maximum to produce FLS versions.

A benefit of this approach is that we are working on each FLS release in sequential fashion, able to keep the items to complete clear.

Phase 2: Beta release note issues (future)

Once we’ve demonstrated the ability to do releases on a consistent cadence from the Stable compiler releases, we will investigate having a 12-week lookback by starting from the release note issues opened when the Beta release of the compiler is cut.

There are benefits in examining the Beta release notes issues. For one, this will help with having more than the Rust Reference writers looking at them, to allow for questions to be raised and potentially improve the rigor of release notes. The FLS Team will become better integrated into the earlier process that the Reference writers undertake.

When we begin having 12-week lookback to Beta, it’s possible we’ll have multiple releases being worked on at a time. We’ll likely need to maintain a way of having the N and N-1 items not be mixed together in an FLS version, before it’s tagged for release. This is a solvable problem, but will require more process and enforced discipline.

Work items over the next year

TaskOwner(s)Notes
Overall coordinationPete LeVasseur
FLS authoring and reviewTeam fls
Ship FLS 1.93 through 1.101Team flsEach within 6 weeks of corresponding Rust stable
Investigate work of Beta release issues lookbackPete LeVasseurLearn how Reference writers approach, apply best practices

Team asks

TeamSupport levelNotes
specSmallAlignment on release cadence goal
flsLargeCore work of authoring and releasing FLS versions on schedule

Frequently asked questions

Why six weeks instead of same-day releases?

Specification work takes time. Six weeks provides a reasonable window to incorporate changes from a Rust release while still being timely. It also aligns neatly with Rust’s release train: FLS N is ready before Rust N+1 ships.

What if a Rust release has unusually large specification impact?

We may occasionally slip past six weeks for releases with major language changes. The goal is to establish six weeks as the norm, not as an absolute guarantee. If slips become common, we will revisit the cadence.

Does this require additional team members?

No. This goal is scoped to be achievable with existing FLS team capacity.

Stabilize the Try trait

Metadata
Point of contactTyler Mandry
StatusProposed
Contingent onFunding
Other tracking issuesrust-lang/rust#84277
Zulip channelN/A
Teamscompiler, lang, libs, types
Task owners(none)

Summary

Stabilize the Try trait, which customizes the behavior of the ? operator.

Motivation

The status quo

Today the only types that can be used with the ? are in the standard library. Most commonly these are Option<T> and Result<T, E>. While most Rust code is happy using one of these two, there are use cases not addressed by these types.

Capturing error context

A common use case is capturing the context of an error each time it is bubbled up using ?, without resorting to the use of backtraces.

enum TracedResult<T, E> {
    Err(TracedError<E>),
    Ok(T),
}
use TracedResult::Ok;

fn read_list(path: PathBuf) -> TracedResult<Vec<i32>> {
    let file = File::open(path)?;
    Ok(read_number_list(file)?)
}

fn read_number_list(file: File) -> TracedResult<Vec<i32>> {
    let mut contents = String::new();
    file.read_to_string(&mut contents)?;
    ...
}

fn main() -> TracedResult<()> {
    let list = read_list("path/to/file.txt".into())?;
    println!("{list:?}");
}

impl<T, E> FromResidual<TracedResult<!, E>> for TracedResult<T, E> {
    #[track_caller]
    fn from_residual(residual: TracedResult<!, E>) -> Self {
        let location = Location::caller();
        match residual {
            TracedResult::Err(err) => TracedResult::Err(err.with_source_location(location))
        }
    }
}

impl<T, E> FromResidual<Result<!, E>> for TracedResult<T, E> {
    #[track_caller]
    fn from_residual(residual: Result<!, E>) -> Self {
        let location = Location::caller();
        match residual {
            Result::Err(err) => TracedResult::Err(TracedError::new(err, location))
        }
    }
}

Could result in the output:

Error: Failed to read file contents
at program.rs:19:48
at program.rs:9:27
at program.rs:14:29

While this is not a user-friendly error message, some errors like internal server errors are never shown to users. In those cases it is reasonable to show only a backtrace for developers.

Capturing a backtrace at the time of initial error creation is prohibitively expensive, both because unwinding is slow and because errors are often handled higher up in the stack without being printed. Capturing a single Location<'static> pointer for each level of bubbling up can be optimized much better.

Because this functionality is so critical for Rust bindings to the Abseil Status library, their plan is to use a custom try_status!() macro to capture the location information instead of ?. This imposes a heavy burden on users, much like the try!() macro did before it.

What we propose to do about it

Stabilize the Try trait, which has been in its current form since 2021.

Because there are open design questions that haven’t yet been resolved, we should either

  • Find a way to resolve them, or
  • Stabilize in a limited way, unblocking the basic use case while leaving our options open for the future.

Work items over the next year

TaskOwner(s)Notes
Design and implement answers to the remaining unresolved questions
Lead design discussion with lang and libs-api teams
Write and shepherd a stabilization report

Team asks

TeamSupport levelNotes
compilerSmall
langMedium
libsMedium
typesSmall

Frequently asked questions

Stabilizing f16

Metadata
Point of contactFolkert de Vries
StatusProposed
Tracking issue
Other tracking issueshttps://github.com/rust-lang/rust/issues/116909
Zulip channelN/A
Stabilizationtrue
Teamscompiler, lang, libs-api
Task owners(none)

Summary

In recent years we’ve seen increasing hardware support for the f16 and f128 float types. Especially for f16 support was originally motivated by machine learning/AI, but these types have since also found applications in other domains like graphics and physics simulations.

With LLVM 22, the remaining blockers in the backends have been cleared for f16, and therefore stabilizing this type in 2026 is realistic.

Motivation

The status quo

The f16 and f128 are unstable. Their implementations are mostly complete, with some missing const support. For f128 there are still some serious ABI issues that require fixes in LLVM. For f16 LLVM 22 has the support we need.

What we propose to do about it

We will stabilize f16, and push f128 as far as we can. There is not much to design at this point.

Work items over the next year

TaskOwner(s)Notes
complete support in const-eval/miriFolkert de Vries
improve support in rustc_codegen_gccFolkert de Vries
remove cfg(target_has_reliable_f16)Folkert de Vries, Trevor Gross
write the stabilization reportFolkert de Vries, Trevor Gross

Team asks

With Trevor Gross as the dedicated reviewer, the asks of the teams are limited.

TeamSupport levelNotes
compilersmall
libs-apismall
langsmalloccasionally being fast-tracked would be nice

Frequently asked questions

What do I do with this space?

Implement Supertrait auto impl

Metadata
Point of contactTyler Mandry
StatusProposed
RoadmapUnblocking dormant traits
RoadmapRust for Linux
Tracking issue
Other tracking issuesrust-lang/rust#149556
Zulip channelN/A
types championBoxy
Teamslang, types
Task owners(none)

Summary

Within the 2026 goal period we strive for completion of the following items.

  • Implementation of the core language features stipulated by the RFC 3851. See rust-lang/rfcs#3851.
  • Continuous update on the RFC for errata to reflect necessary changes as implementation moves along.
  • Resolve the impl overlapping question, possibly as an optional feature behind an associated feature gate.
  • Field trial of the standard library trait refactoring with the supertrat_auto_impl feature gate.
  • Implementation of the optional features and lints spelled in the RFC as much as possible.

Motivation

Trait evolution and trait hierarchy refactoring is a long-time pain point for Rust crates and especially the standard library. As crates evolve and grow, needs to restructure trait hierarchy to accommodate richer functionality often arises, both in the standard library and the broader Rust ecosystem.

Supertrait auto impl has been viewed as a potential solution and a promising language feature to the trait evolution problem, such that we can avoid major and elaborate rewrites in downstream crates. In essence, the feature would avoid rewrites when associate items are moved into a new supertrait, which is a common scenario that this problem concerns about.

#![allow(unused)]
fn main() {
// Before refactoring

pub trait BigTrait {
    fn method_lower_level();
    fn method_higher_level();
}

// After refactoring

pub trait BigTrait: Supertrait {
    // This signals to the compiler that `Supertrait` implementation shall
    // be automatically derived with the right items, so that ...
    auto impl Supertrait;
    fn method_higher_level();
}

pub trait Supertrait {
    fn method_lower_level();
}

// ... this `impl BigTrait` continues to compile
impl BigTrait for MyType {
    fn method_lower_level() { .. }
    // because this method is resolved to `Supertrait::method_higher_level`
    // and used to derive the `impl Supertrait for MyType` automatically.
    fn method_higher_level() { .. }
}
}

The status quo

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

Supertrait auto impl targets library authors who needs to refactor traits or design a trait hierarchy. A recurring topic arising from this activity is that with refined trait granularity, or smaller traits in other words, also comes many required impls. The problem exacerbates when it is an upstream trait receiving a refactor. While this is rightfully a breaking change, downstream crates would also have to move trait items into new impl blocks as the original trait is broken into smaller supertraits. This major rewrite is often undesirable for library authors as this would discourage downstream users to upgrade the library. For standard library, this often means that the changes can only land on an Edition boundary.

The next 6 months

TaskOwner(s)Notes
Implementation of the language featureDing Xiang Fei

The “shiny future” we are working towards

If this goal is part of a larger plan that will extend beyond this goal period, sketch out the goal you are working towards. It may be worth adding some text about why these particular goals were chosen as the next logical step to focus on.

This text is NORMATIVE, in the sense that teams should review this and make sure they are aligned. If not, then the shiny future should be moved to frequently asked questions with a title like “what might we do next”.

However, for most proposals, alignment on exact syntax should not be required to start a goal, only alignment on the problem and the general sketch of the solution. This may vary for goals that are specifically about syntax, such as ergonomic improvements.

We would like to establish a mechanism in the language to automatically derive the required supertrait implementation using the items available in the subtrait implementation. The first step is to enable the resolution of the supertrait associated items in the subtrait implementation block to the corresponding supertraits when there is no risk of ambiguity.

auto impl blocks follows so that the default supertrait implementation could be supplied from the supertrait definition. We will also propose a feature to allow downstream trait users with explicit opt-out of the default supertrait implementation in case of overlapping implementation or need for customisation.

Team asks

TeamSupport levelNotes
cargo
compiler
infra
langMediumTeam aligned already on the shape of the feature
libs-api
opsem
typesMediumWant to ensure that the feature “fits within the lines” of a simple desugaring, still some possible type-system impl work
Feel free to add rows for other teams

Frequently asked questions

Type System Documentation

Metadata
Point of contactBoxy
StatusProposed
Tracking issuerust-lang/rust-project-goals#405
Other tracking issues[rustc-dev-guide#2663]
Zulip channelN/A
types championBoxy
Teamstypes
Task owners(none)

Summary

Improve documentation of type system components to aid in types team onboarding and communication about changes to the type system.

Motivation

The status quo

The type system is a very complex and critical component of the compiler. It is currently lacking in documentation, and the documentation that does exist is often inadequate for gaining a thorough understanding of a given part of the type system (or simply outdated as it was written many years ago).

The lack of documentation makes onboarding difficult for new contributors and require a lot of energy from experienced contributors who are now responsible for explaining everything from scratch themselves. A similar problem also occurs when reviewing changes to the type system, as there is no documentation it can be difficult to bring everything back into cache and be confident that the subtleties of the area being changed have all been taken into account.

What we propose to do about it

In the previous period, Boxy and lcnr put together a list of type system topics that should be covered: Type System Documentation Overhaul rustc-dev-guide#2663.

The next steps are to pick items from this list, check them against the rustc-dev-guide and document what’s missing.

Ultimately, all type system components should be thoroughly documented. Contributors should not find themselves in a position where knowledge of the type system is only attainable by speaking with types team members instead of having readily available documentation to read.

Work items over the next year

TaskOwner(s)Notes
Prioritise and document missing itemsBoxy

Team asks

TeamSupport levelNotes
typesSmallDiscussion and moral support

used_with_arg

Metadata
Point of contact@todo
StatusProposed
RoadmapRust for Linux
Tracking issue
Other tracking issuesrust-lang/rust#93798
Zulip channelN/A
Teamslang, lang-docs, libs, libs-api
Task owners(none)

Summary

Short description of what you will do over the next year.

Motivation

The status quo

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

What we propose to do about it

Explain your overall approach to solving the problem. Explain your design philosophy (including design axioms). Focus your discussion on what you aim to get done this year, but it is good to also give a sense for the “overall goal” you are working towards, if it extends beyond the work for this year. Team(s) should give you feedback on whether they are aligned both with your short-term and longer-term goals.

Work items over the next year

TaskOwner(s)Notes
Implementation & docs
Stabilization PR

Team asks

TeamSupport levelNotes
langMediumReviews, Lang/RfL meetings
lang-docsMediumReviews, Lang/RfL meetings
libsSmallReviews
libs-apiSmallStabilizations

Establish a User Research Team

Metadata
Point of contactNiko Matsakis
StatusProposed
Tracking issue
Zulip channel#vision-doc-2025
Teamsleadership-council
Task owners(none)

Summary

Establish a dedicated User Research Team within the Rust project to systematically gather, synthesize, and distribute insights about Rust users’ needs and experiences.

Motivation

The status quo

As Rust usage grows, it becomes harder to keep tabs on users’ experiences. Teams need to make decisions and prioritize work, but we don’t have systematic ways to understand what users actually need. As Rust expands into new areas (embedded, safety-critical systems, new platforms), each domain has particular needs that we may not understand well. We want decisions to be based on data, not vibes.

In 2025, we conducted the Vision Doc effort, gathering 4,200+ survey responses and conducting 70 in-depth interviews. This was great at getting a broad picture of Rust usage and user needs, but it also revealed the need for more in-depth analyses into specific areas and questions. One-off projects can establish long-term direction and the lay of the land, but giving fine-grained feedback on specific design questions requires dedicated people with the skills and experience to dive deep.

What we propose to do about it

Establish a User Research Team that will pick up where the Vision Doc effort left off. The mission of the User Research Team is to help the project make evidence-based decisions.

The team will do in-depth exploration of new areas, similar to the safety-critical analysis from the Vision Doc effort and the Async WG’s vision doc. But it will also serve as a consulting arm, talking to teams about specific questions coming up in RFCs and exploring how we can gather data to inform those decisions.

Over time, the team would build up a collection of raw data - interviews, survey responses, usage studies - that can be queried and analyzed as new questions arise. There is some tension with privacy that we’ll need to navigate: we want data that teams can access and discuss openly, while still respecting participants’ confidentiality.

Work items over the next year

TaskOwner(s)Notes
Draft team charter defining scope and approachVision Doc effort members
Recruit initial team membersVision Doc effort membersLooking for user research experience
Establish data sharing protocolsUser Research TeamBalance privacy with team access
Create infrastructure for distributing findingsUser Research TeamHow findings reach other teams
Conduct first targeted research studyUser Research TeamDemonstrate value with concrete output

Team asks

TeamSupport levelNotes
leadership-councilSmallOrg decision to establish team, ongoing coordination

Frequently asked questions

How does this relate to the Vision Doc?

The Vision Doc was a one-time research effort. This goal establishes permanent capacity to do user research on an ongoing basis, applying lessons learned from that process.

What skills does the team need?

Ideally a mix of user research expertise (interview design, survey methodology, qualitative analysis) and Rust community knowledge. The team doesn’t need to be large - even 2-3 dedicated people could have significant impact.

How will findings be shared?

The team will develop protocols that balance participant privacy with team access to insights. This likely means publishing aggregate findings publicly while keeping individual interview data restricted to team members.

How does this relate to the Survey Team?

The existing Survey Team runs the annual Rust survey. The User Research Team has a broader scope - interviews, targeted studies, domain explorations - but surveys are an important tool. The Survey Team might be folded into the User Research effort, or the two teams might collaborate closely with the Survey Team handling the annual survey while the User Research Team focuses on deeper investigations.

Wasm Components

Metadata
Point of contactYoshua Wuyts
StatusProposed
Tracking issue
Zulip channelN/A
HighlightOther
Teamscompiler, lang, libs
Task owners(none)

Summary

In 2026 we want to improve the state of Wasm Component support in Rust. This means adding and stabilizing three new compiler targets, as well as begin experimentation with Wasm-specific language features.

Motivation

Rust has been at the forefront of WebAssembly support since WebAssembly was incepted. The WASI 0.3 specification is expected to be released in early 2026, adding native support for async operations to Wasm Components. You can think of this as morally equivalent to support for async fn and async gen fn at the ABI level.

Native support for async operations is not only great for networked applications and plugins, but also specifically for targeting the web. Browser vendors have expressed interest in natively supporting components, which opens up the possibility for calling web APIs directly from Rust without having to roundtrip through JavaScript.

We want to make sure that Rust remains at the forefront of WebAssembly support, and so during 2026 we want to do the work to make sure that stays the case.

The status quo

There are a number of things with WebAssembly in Rust that are not ideal:

  • We don’t have a dedicated web target in Rust, instead the ecosystem primarily relies on the wasm32-unknown-unknown target which is rather brittle.
  • We have a WASI 0.3 target but it is currently tier 3, which means its unavailable via rustup
  • std::thread support is missing in all of the Wasm Component targets, which makes certain apps hard to port.
  • Creating bare Wasm Components without WASI support uses the WASI targets, which is confusing.
  • Exporting and importing WebAssembly types and functions requires third-party bindgen tooling, introducing friction.
  • There is only one possible representation for an “async fn main” in WASI 0.3 and above, yet we require third-party crates to call it.

The next 12 months

Sketch out the specific things you are trying to achieve in this goal period. This should be short and high-level – we don’t want to see the design!

TaskOwner(s)Notes
Bring wasm32-wasip3 to tier 2Alex CrichtonThis is the WASI 0.3 target, with support for component model async features. It unlocks async-async component composition, as well as cooperative threading.
Introduce wasm32-component target as tier 3Alex CrichtonThis target is very similar to wasm32-wasip3, but does not include the WASI APIs, making it #[no_std] + alloc.
Introduce wasm32-component-web target as tier 3Yoshua WuytsThis target is very similar to wasm32-component, but with a different cfg that enables an ecosystem to be built specifically targeting the web.
Implement std::thread for WASIp3@tartanllamaThis is a future extension to the component model, which will be part of a WASI 0.3.x release. Enables Wasm Components’ “cooperative multi-threading” feature.
Implement async fn main for WASIp3Yoshua Wuyts
Experiment with #[repr(wasm)] and extern "wasm"tbdThis item is more aspirational than the others. It would be good to do this, but we may not get to it.

The “shiny future” we are working towards

We would like to bring Rust up to date with async support for Wasm Components. This means adding a new WASI target (wasm32-wasip3) and bringing it to tier 2. But also adding new targets for bare components with optional async support (wasm32-component) and a variation of that specifically for the web (wasm32-component-web).

WebAssembly’s goal is to provide a general-purpose, lightweight, and sandboxed plugin model. Not just on the web, but also for databases, servers, embedded, and more. We want Rust to provide a best-in-class experience for WebAssembly, where targeting Wasm is as easy as targeting any of the native platforms. And in some cases even exceeding what other platforms are capable of, by leaning into WebAssembly’s distinct advantages.

This project goal brings us closer towards that shiny future, making sure we stay up to date with the latest WebAssembly developments. While also looking to push a little beyond that, by making WebAssembly Components easier to target from Rust.

Team asks

TeamSupport levelNotes
compilersmallNew targets will need review and approval
langsmallExperimentation with native Wasm features will need approval. May become “medium” if we are somehow really successful.
libssmallThreading support will need review

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Frequently asked questions about the 2026 goal process

How does the goal process work?

Project goals are proposed bottom-up by a point of contact, somebody who is willing to commit resources (time, money, leadership) to seeing the work get done. The point of contact identifies the problem they want to address and sketches the solution of how they want to do so. They also identify the support they will need from the Rust teams (typically things like review bandwidth or feedback on RFCs). Teams then read the goals and provide feedback. If the goal is approved, teams are committing to support the point of contact in their work.

Project goals can vary in scope from an internal refactoring that affects only one team to a larger cross-cutting initiative. No matter its scope, accepting a goal should never be interpreted as a promise that the team will make any future decision (e.g., accepting an RFC that has yet to be written). Rather, it is a promise that the team are aligned on the contents of the goal thus far (including the design axioms and other notes) and will prioritize giving feedback and support as needed.

Of the proposed goals, a small subset are selected by the roadmap owner as roadmap goals. Roadmap goals are chosen for their high impact (many Rust users will be impacted) and their shovel-ready nature (the org is well-aligned around a concrete plan). Roadmap goals are the ones that will feature most prominently in our public messaging and which should be prioritized by Rust teams where needed.

What goal were not accepted?

These goals were not accepted either for want of resources or consensus. In some cases, narrower versions of these goals were proposed instead.

GoalPoint of contactProgress

Status: Accepted RFC #3849 has been accepted, establishing 41 total Rust project goals for 2025H2. To see the latest updates go to the Reports page.

Summary

Propose a slate of 41 goals for 2025H2.

Motivation

The 2025h2 goal slate consists of 41 project goals, of which we have selected a subset as flagship goals. Flagship goals represent the highest priority being done by the various Rust teams.

Guide-level explanation

Rust’s mission

Our goals are selected to further Rust’s mission of making it dramatically more accessible to author and maintain foundational software—the software that underlies everything else. This includes the CLI tools and development infrastructure that developers rely on, the cloud platforms that run applications, the embedded systems in devices around us, and increasingly the kernels and operating systems that power it all.

Foundational software has particularly demanding requirements: reliability is paramount because when foundations fail, everything built on top fails too. Performance overhead must be minimized because it becomes a floor on what the layers above can achieve. Traditionally, meeting these requirements meant choosing between the power-but-danger of C/C++ or the safety-but-constraints of higher-level languages used in very specific ways.

Rust changes this balance by combining zero-cost abstractions with memory safety guarantees, often allowing you to write high-level code with low-level performance. While Rust’s primary focus remains foundational software, we also recognize that supporting higher-level applications helps identify ergonomic improvements that benefit all users and enables developers to use Rust throughout their entire stack.

Flagship goals

This period we have 14 flagship goals, broken out into four themes:

  • Beyond the &, making it possible to create user-defined smart pointers that are as ergonomic as Rust’s built-in references &.
  • Unblocking dormant traits, extending the core capabilities of Rust’s trait system to unblock long-desired features for language interop, lending iteration, and more.
  • Flexible, fast(er) compilation, making it faster to build Rust programs and improving support for specialized build scenarios like embedded usage and sanitizers.
  • Higher-level Rust, making higher-level usage patterns in Rust easier.

“Beyond the &

One of Rust’s core value propositions is that it’s a “library-based language”—libraries can build abstractions that feel built-in to the language even when they’re not. Smart pointer types like Rc and Arc are prime examples, implemented purely in the standard library yet feeling like native language features. However, Rust’s built-in reference types (&T and &mut T) have special capabilities that user-defined smart pointers cannot replicate. This creates a “second-class citizen” problem where custom pointer types can’t provide the same ergonomic experience as built-in references.

The “Beyond the &” initiative aims to share &’s special capabilities, allowing library authors to create smart pointers that are truly indistinguishable from built-in references in terms of syntax and ergonomics. This will enable more ergonomic smart pointers for use in cross-language interop (e.g., references to objects in other languages like C++ or Python) and for low-level projects like Rust for Linux which use smart pointers to express particular data structures.

“Unblocking dormant traits”

Rust’s trait system is one of its most powerful features, but it has a number of longstanding limitations that are preventing us from adopting new patterns. The goals in this category unblock a number of new capabilities:

  • Polonius will enable new borrowing patterns, and in particular unblock “lending iterators”. Over the last few goal periods we have identified an “alpha” version of polonius that addresses the most important cases while being relatively simple and optimizable. Our goal for 2025H2 is to implement this algorithm in a form that is ready for stabilization in 2026.
  • The next gen trait solver is a refactored trait solver that unblocks better support for numerous language features (implied bounds, negative impls, the list goes on) in addition to closing a number of existing bugs and unsoundnesses. Over the last few goal periods, the trait solver went from early prototype to being production use in coherence. The goal for 2025H2 is to prepare it for stabilization.
  • The work on evolving trait hierarchies will make it possible to refactor some parts of an existing trait out into a new supertrait so they can be used on their own. This unblocks a number of features where the existing trait is insufficiently general, in particular stabilizing support for custom receiver types, a prior project goal that wound up blocking on this refactoring. This will also make it safer to provide stable traits in the standard library, while preserving the ability to evolve them in the future.
  • The work to expand Rust’s Sized hierarchy will permit us to express types that are neither Sized nor ?Sized, such as extern types (which have no size) or Arm’s Scalable Vector Extension (which have a size that is known at runtime, but not compilation time). This goal builds on RFC #3729 and RFC #3838, authored in previous project goal periods.
  • In-place initialization allows creating structs and values that are tied to a particular place in memory. While useful directly for projects doing advanced C interop, it also unblocks expanding dyn Trait to support for async fn and -> impl Trait methods, as compiling such methods requires the ability for the callee to return a future whose size is not known to the caller.

“Flexible, fast(er) compilation”

The “Flexible, fast(er) compilation” initiative focuses on improving Rust’s build system to better serve both specialized use cases and everyday development workflows:

“Higher-level Rust”

People generally start using Rust for foundational use cases, where the requirements for performance or reliability make it an obvious choice. But once they get used to it, they often find themselves turning to Rust even for higher-level use cases, like scripting, web services, or even GUI applications. Rust is often “surprisingly tolerable” for these high-level use cases – except for some specific pain points that, while they impact everyone using Rust, hit these use cases particularly hard. We plan two flagship goals this period in this area:

  • We aim to stabilize cargo script, a feature that allows single-file Rust programs that embed their dependencies, making it much easier to write small utilities, share code examples, and create reproducible bug reports without the overhead of full Cargo projects.
  • We aim to finalize the design of ergonomic ref-counting and to finalize the experimental impl feature so it is ready for beta testing. Ergonomic ref counting makes it less cumbersome to work with ref-counted types like Rc and Arc, particularly in closures.

Project goals

The full slate of project goals are as follows. These goals all have identified points of contact who will drive the work forward as well as a viable work plan. The goals include asks from the listed Rust teams, which are cataloged in the reference-level explanation section below.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as a point of contact. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactTask Owners and Champions
Develop the capabilities to keep the FLS up to datePete LeVasseurContributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems, Jakub Beránek (bootstrap), Niko Matsakis (lang), Pete LeVasseur (spec)
Getting Rust for Linux into stable Rust: compiler featuresTomas Sedovic(depending on the flag), Wesley Wiser (compiler)
Getting Rust for Linux into stable Rust: language featuresTomas SedovicDing Xiang Fei, Josh Triplett (lang), TC (lang-docs)
Borrow checking in a-mir-formalityNiko Matsakistiif, Niko Matsakis (types)
Reborrow traitsAapo AlasuutariOliver Scherer (compiler), Tyler Mandry (lang)
build-stdDavid WoodAdam Gemmell, Eric Huss (cargo), David Wood (compiler), Amanieu d’Antras (libs)
Prototype Cargo build analysisWeihang LoHelp wanted Weihang Lo, Weihang Lo (cargo)
Rework Cargo Build Dir LayoutRoss SullivanWeihang Lo (cargo)
Prototype a new set of Cargo “plumbing” commandsHelp WantedHelp wanted, Ed Page (cargo)
Stabilize cargo-scriptEd PageEd Page (cargo), Josh Triplett (lang), Josh Triplett (lang-docs)
Continue resolving cargo-semver-checks blockers for merging into cargoPredrag GruevskiEd Page (cargo), Alona Enraght-Moony (rustdoc)
Emit Retags in CodegenIan McCormackRalf Jung (compiler), Tyler Mandry (lang), Ralf Jung (opsem)
Comprehensive niche checks for RustBastian KerstingBastian Kersting], Jakob Koschel, Ben Kimock (compiler), Ben Kimock (opsem)
Const GenericsBoxyNoah Lev, Niko Matsakis (lang)
Ergonomic ref-counting: RFC decision and previewNiko MatsakisSantiago Pastorino, Santiago Pastorino (compiler), Niko Matsakis (lang)
Evolving trait hierarchiesTaylor CramerTaylor Cramer & others, Taylor Cramer (lang), Oliver Scherer (types)
Design a language feature to solve Field ProjectionsBenno LossinTyler Mandry (lang)
Finish the std::offload moduleManuel DrehwaldLLVM offload/GPU contributors, Manuel Drehwald (compiler), TC (lang)
Run more tests for GCC backend in the Rust’s CIGuillaume GomezWesley Wiser (compiler), Marco Ieni (infra)
In-place initializationAlice RyhlBenno Lossin, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts, Taylor Cramer (lang)
C++/Rust Interop Problem Space MappingJoel MarceyOliver Scherer (compiler), Tyler Mandry (lang), David Tolnay (libs)
Finish the libtest json output experimentEd PageEd Page (cargo)
MIR move eliminationAmanieu d’AntrasAmanieu d’Antras (lang)
Next-generation trait solverlcnrBoxy, Michael Goulet, lcnr (types)
Implement Open API Namespace SupportHelp Wantedb-naber, Ed Page (cargo), b-naber (compiler), Carol Nichols (crates-io)
Promoting Parallel Front EndSparrow Li
Continue Experimentation with Pin ErgonomicsFrank KingOliver Scherer (compiler), TC (lang)
Stabilizable Polonius support on nightlyRémy RakicAmanda Stjerna, Niko Matsakis, Jack Huey (types)
Production-ready cranelift backendFolkert de Vriesbjorn3, [Trifecta Tech Foundation], bjorn3 (compiler)
Stabilize public/private dependenciesHelp WantedHelp wanted, Ed Page (cargo)
Expand the Rust Reference to specify more aspects of the Rust languageJosh TriplettAmanieu d’Antras, Guillaume Gomez, Jack Huey, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby, Josh Triplett (lang-docs), Josh Triplett (spec)
reflection and comptimeOliver SchererOliver Scherer (compiler), Scott McMurray (lang), Josh Triplett (libs)
Relink don’t RebuildJane Lusby@dropbear32, @osiewicz, Weihang Lo (cargo), Oliver Scherer (compiler)
Rust Vision DocumentNiko Matsakisvision team
rustc-perf improvementsJamesJakub Beránek, David Wood, David Wood (compiler), Jakub Beránek (infra)
Stabilize rustdoc doc_cfg featureGuillaume GomezGuillaume Gomez (rustdoc)
Add a team charter for rustdoc teamGuillaume GomezGuillaume Gomez (rustdoc)
SVE and SME on AArch64David WoodDavid Wood (compiler), Niko Matsakis (lang), Amanieu d’Antras (libs)
Rust Stabilization of MemorySanitizer and ThreadSanitizer SupportJakob Koschel[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)
Type System DocumentationBoxylcnr, Boxy (types)
Unsafe FieldsJack WrennJacob Pratt, Luca Versari, Jack Wrenn (compiler), Scott McMurray (lang)

Reference-level explanation

Goals broken out by champion

Who is championing which goals?

Champion#Goals
Amanieu d’Antras3° MIR move elimination
° SVE and SME on AArch64
° build-std
Guillaume Gomez2° Add a team charter for rustdoc team
° Stabilize rustdoc doc_cfg feature
Pete LeVasseur1° Develop the capabilities to keep the FLS up to date
Ralf Jung1° Emit Retags in Codegen
Wesley Wiser2° Getting Rust for Linux into stable Rust: compiler features
° Run more tests for GCC backend in the Rust’s CI
Manuel Drehwald1° Finish the std::offload module
Alona Enraght-Moony1° Continue resolving cargo-semver-checks blockers for merging into cargo
b-naber1° Implement Open API Namespace Support
bjorn31° Production-ready cranelift backend
Boxy1° Type System Documentation
Carol Nichols1° Implement Open API Namespace Support
Taylor Cramer2° Evolving trait hierarchies
° In-place initialization
David Wood3° SVE and SME on AArch64
° build-std
° rustc-perf improvements
David Tolnay1° C++/Rust Interop Problem Space Mapping
Eric Huss1° build-std
Ed Page6° Continue resolving cargo-semver-checks blockers for merging into cargo
° Finish the libtest json output experiment
° Implement Open API Namespace Support
° Prototype a new set of Cargo “plumbing” commands
° Stabilize cargo-script
° Stabilize public/private dependencies
Jack Huey1° Stabilizable Polonius support on nightly
Josh Triplett4° Expand the Rust Reference to specify more aspects of the Rust language
° Getting Rust for Linux into stable Rust: language features
° Stabilize cargo-script
° reflection and comptime
Jack Wrenn1° Unsafe Fields
Jakub Beránek2° Develop the capabilities to keep the FLS up to date
° rustc-perf improvements
lcnr1° Next-generation trait solver
Marco Ieni1° Run more tests for GCC backend in the Rust’s CI
Niko Matsakis5° Borrow checking in a-mir-formality
° Const Generics
° Develop the capabilities to keep the FLS up to date
° Ergonomic ref-counting: RFC decision and preview
° SVE and SME on AArch64
Oliver Scherer6° C++/Rust Interop Problem Space Mapping
° Continue Experimentation with Pin Ergonomics
° Evolving trait hierarchies
° Reborrow traits
° Relink don’t Rebuild
° reflection and comptime
Vadim Petrochenkov1° Delegation
Ben Kimock1° Comprehensive niche checks for Rust
Scott McMurray2° Unsafe Fields
° reflection and comptime
Santiago Pastorino1° Ergonomic ref-counting: RFC decision and preview
Tyler Mandry4° C++/Rust Interop Problem Space Mapping
° Design a language feature to solve Field Projections
° Emit Retags in Codegen
° Reborrow traits
TC3° Continue Experimentation with Pin Ergonomics
° Finish the std::offload module
° Getting Rust for Linux into stable Rust: language features
Weihang Lo3° Prototype Cargo build analysis
° Relink don’t Rebuild
° Rework Cargo Build Dir Layout

Team asks

The following table highlights the asks from each affected team. The “owner” in the column is the person expecting to do the design/implementation work that the team will be approving.

bootstrap team

cargo team

*1: Review initial RFC draft (from here)

compiler team

*1: Most of our changes are within rustc_codegen_ssa, but it would also be helpful to have feedback from someone familiar with how retags are handled within Miri’s borrow_tracker module. (from here)

*2: Where to insert the check / checked load (from here)

*3: Update performance regression policy (from here)

*4: Review initial RFC draft (from here)

*5: Approve experiment of [rfcs#3838] (from here)

*6: Larger changes to rustc_codegen_ssa. While not strictly required, we think having a dedicated reviewer will speed up our progress. (from here)

crates-io team

infra team

*1: rustc-perf improvements, testing infrastructure (from here)

lang team

*1: topic: adt_const_params design (from here)

*2: Needs libstd data structures (lang items) to make the specialization data available (from here)

*3: Possibly more than one required as well as discussions on zulip. (from here)

*4: Ding Xiang Fei, Benno Lossin (from here)

*5: Two meetings to evaluate both approaches (from here)

*6: Choose between maximally additive vs seamlessly integrated (from here)

*7: Language team decide whether to accept [rfcs#3729] (from here)

*8: Compiler/Library team decide whether to accept [rfcs#3838] (from here)

*9: allows coding pre-RFC; only for trusted contributors (from here)

*10: Stabilizing arbitrary_self_types. Unblocked by new Receiver API. (from here)

lang-docs team

GoalReference text
Expand the Rust Reference to specify more aspects of the Rust language
Getting Rust for Linux into stable Rust: language features
↳ Finish and stabilize arbitrary_self_types and derive_coerce_pointee
Stabilize cargo-script
↳ Stabilize language feature frontmatterEric Huss

leadership-council team

libs team

*1: Needs libstd data structures (lang items) to make the specialization data available (from here)

*2: Review initial RFC draft (from here)

*3: Approve experiment of [rfcs#3838] (from here)

libs-api team

*1: Stabilizing Receiver. Unblocked by implementation. (from here)

opsem team

*1: Most of our changes are within rustc_codegen_ssa, but it would also be helpful to have feedback from someone familiar with how retags are handled within Miri’s borrow_tracker module. (from here)

project-exploit-mitigations team

rustdoc team

spec team

testing-devex team

types team

*1: for necessary refactorings (from here)

*2: Review Part II of Sized Hierarchy implementation (from here)

*3: Assign specific reviewers for Polonius Alpha model implementation (Rémy Rakic) (from here)

wg-compiler-performance team

*1: If possible, track and show rustc_codegen_cranelift performance. See note below for more details. (from here)

wg-mir-opt team

Definitions

Definitions for terms used above:

  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

How are project goals proposed?

Project goals are proposed bottom-up by a point of contact, somebody who is willing to commit resources (time, money, leadership) to seeing the work get done. The point of contact identifies the problem they want to address and sketches the solution of how they want to do so. They also identify the support they will need from the Rust teams (typically things like review bandwidth or feedback on RFCs). Teams then read the goals and provide feedback. If the goal is approved, teams are committing to support the point of contact in their work.

What goals were not accepted?

The following goals were not accepted as nobody stepped up to champion them. This should not be taken as a rejection of the underlying idea but likely indicates bandwidth constraints or concerns about scope.

GoalPoint of contactTask Owners and Champions
DelegationVadim Petrochenkov@bryanskiy, Vadim Petrochenkov (compiler)

Does accepting a goal mean that the work is going to happen for sure?

No. Accepting a goal is not a promise to accept an RFC, stabilize a feature, or take any other binding action. Rather, it means that the team wants the goal to make progress and is committing to commit time to complete the Team Asks described in the goal. To give some concrete examples, when the compiler team accepts a goal, they are committing to make sure reviews get done, but they are not committing to give an r+ if the code doesn’t pass muster. Similarly, the lang team is agreeing to discuss an RFC and provide actionable feedback, but not necessarily to accept it.

What is a “team champion”? What do they do?

Team champions are people who have volunteered to track progress on the goal and to serve as a liaison between the goal owner(s) and the team. They are committing to support the owner to avoid the goal getting stuck in some kind of procedural limbo. For example, the goal champion might make sure the goal gets discussed in a meeting, or help to find a reviewer for a PR that is stuck in the queue. (In cases where the goal owner is also on the team, they can serve as their own champion.)

What do the column names like “Ded. r?” mean?

Those column names refer to specific things that can be asked of teams:

AskakaDescription
“Allocate funds”Alloc fundsallocate funding
“Discussion and moral support”Good vibesapprove of this direction and be prepared for light discussion on Zulip or elsewhere
“Deploy to production”Deploydeploy code to production (e.g., on crates.io
“Standard reviews”r?review PRs (PRs are not expected to be unduly large or complicated)
“Dedicated reviewer”Ded. r?assign a specific person (or people) to review a series of PRs, appropriate for large or complex asks
“Lang-team experiment”Experimentbegin a lang-team experiment authorizing experimental impl of lang changes before an RFC is written; limited to trusted contributors
“Design meeting”Design mtg.hold a synchronous meeting to review a proposal and provide feedback (no decision expected)
“RFC decision”RFCreview an RFC and deciding whether to accept
“RFC secondary review”RFC rev.briefly review an RFC without need of a formal decision
“Org decision”Orgreach a decision on an organizational or policy matter
“MCP decision”MCPaccept a Major Change Proposal
“ACP decision”ACPaccept an API Change Proposal
“Review/revise Reference PR”Reference textassign a lang-docs team liaison to finalize edits to Rust Reference
“Stabilization decision”Stabilize.reach a decision on a stabilization proposal
“Policy decision”Policymake a decision related to team policy
“FCP decision(s)”FCPmake formal decision(s) that require ‘checkboxes’ and a FCP (Final Comment Period)
“Blog post approval”Blogapprove of posting about this on the main Rust blog
“Miscellaneous”Miscdo some one-off action as described in the notes

Do goals have to have champions to be accepted?

Yes – to be accepted, a goal needs some champions. They don’t necessarily have to have a champion for every team, particularly not those with minor asks, but they do need to have enough champions that it seems the goal owner will be adequately supported. Those champions also need to not be too overloaded.

How will we avoid taking on too many goals?

That’s a tough one. Part of the reason to have champions is to help us filter out goals – if one champion has too many goals, or nobody is willing to champion the goal, that’s a bad sign.

Goals

This page lists the 41 project goals proposed for 2025h2.

Just because a goal is listed on this list does not mean the goal has been accepted. The owner of the goal process makes the final decisions on which goals to include and prepares an RFC to ask approval from the teams.

Flagship goals

Flagship goals represent the goals expected to have the broadest overall impact.

Other goals

These are the other proposed goals.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as a point of contact. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactTask Owners and Champions
Develop the capabilities to keep the FLS up to datePete LeVasseurContributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems, Jakub Beránek (bootstrap), Niko Matsakis (lang), Pete LeVasseur (spec)
Getting Rust for Linux into stable Rust: compiler featuresTomas Sedovic(depending on the flag), Wesley Wiser (compiler)
Getting Rust for Linux into stable Rust: language featuresTomas SedovicDing Xiang Fei, Josh Triplett (lang), TC (lang-docs)
Borrow checking in a-mir-formalityNiko Matsakistiif, Niko Matsakis (types)
Prototype Cargo build analysisWeihang LoHelp wanted Weihang Lo, Weihang Lo (cargo)
Rework Cargo Build Dir LayoutRoss SullivanWeihang Lo (cargo)
Prototype a new set of Cargo “plumbing” commandsHelp WantedHelp wanted, Ed Page (cargo)
Continue resolving cargo-semver-checks blockers for merging into cargoPredrag GruevskiEd Page (cargo), Alona Enraght-Moony (rustdoc)
Emit Retags in CodegenIan McCormackRalf Jung (compiler), Tyler Mandry (lang), Ralf Jung (opsem)
Comprehensive niche checks for RustBastian KerstingBastian Kersting], Jakob Koschel, Ben Kimock (compiler), Ben Kimock (opsem)
Const GenericsBoxyNoah Lev, Niko Matsakis (lang)
Finish the std::offload moduleManuel DrehwaldLLVM offload/GPU contributors, Manuel Drehwald (compiler), TC (lang)
Run more tests for GCC backend in the Rust’s CIGuillaume GomezWesley Wiser (compiler), Marco Ieni (infra)
C++/Rust Interop Problem Space MappingJoel MarceyOliver Scherer (compiler), Tyler Mandry (lang), David Tolnay (libs)
Finish the libtest json output experimentEd PageEd Page (cargo)
MIR move eliminationAmanieu d’AntrasAmanieu d’Antras (lang)
Implement Open API Namespace SupportHelp Wantedb-naber, Ed Page (cargo), b-naber (compiler), Carol Nichols (crates-io)
Stabilize public/private dependenciesHelp WantedHelp wanted, Ed Page (cargo)
Expand the Rust Reference to specify more aspects of the Rust languageJosh TriplettAmanieu d’Antras, Guillaume Gomez, Jack Huey, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby, Josh Triplett (lang-docs), Josh Triplett (spec)
reflection and comptimeOliver SchererOliver Scherer (compiler), Scott McMurray (lang), Josh Triplett (libs)
Rust Vision DocumentNiko Matsakisvision team
rustc-perf improvementsJamesJakub Beránek, David Wood, David Wood (compiler), Jakub Beránek (infra)
Stabilize rustdoc doc_cfg featureGuillaume GomezGuillaume Gomez (rustdoc)
Add a team charter for rustdoc teamGuillaume GomezGuillaume Gomez (rustdoc)
SVE and SME on AArch64David WoodDavid Wood (compiler), Niko Matsakis (lang), Amanieu d’Antras (libs)
Type System DocumentationBoxylcnr, Boxy (types)
Unsafe FieldsJack WrennJacob Pratt, Luca Versari, Jack Wrenn (compiler), Scott McMurray (lang)

Develop the capabilities to keep the FLS up to date

Metadata
Point of contactPete LeVasseur
StatusProposed
Tracking issuerust-lang/rust-project-goals#391
Zulip channel#t-spec
bootstrap championJakub Beránek
lang championNiko Matsakis
spec championPete LeVasseur
Teamsbootstrap, lang, opsem, spec, types
Task ownersPete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

Summary

Develop the capabilities and capacity to keep the FLS up to date with the Rust language.

Motivation

The FLS was graciously transferred from Ferrous Systems to the Rust Project. In 2025H1, a Project goal to bring the FLS in and publish a version under the auspicious of the Rust Project was successfully completed. Let’s now take this to the next level by ensuring that we can keep the FLS up to date with the Rust language in a sustainable manner by developing the necessary capacity and capabilities for doing so.

The status quo

The target audience here will be those that have a vested interest in Rust specification work and want to see movement forward in ensuring that our documents are as correct and complete as possible.

Keeping up with documentation is not always the most glamorous role for any project. And folks like Eric Huss and others are doing an outstanding job at trying to keep the Reference current with actual code behavior. This is a hard job just for one document like the Reference. It will be even more difficult adding another core document like the FLS. But that doesn’t necessarily mean we can’t keep the FLS as up to date as is needed by its users.

Solicitation of stakeholder involvement

The FLS is an enabler document for safety qualifying versions of the Rust compiler. The safety-critical community of Rust users actively and passively benefits from the FLS.

Active users of the FLS should be consulted on changes with a “do no harm” approach taken to ensure the capability to use the FLS for safety qualification of the Rust compiler is not disrupted. Active users consulted and contributing to maintenance will ensure the ability to achieve safety qualification from an assessor.

Passive beneficiaries of the FLS include those entities that themselves do not safety qualify a compiler, but instead because the FLS exists and can be used for that purpose, grows the safety-critical set of users of Rust. Examples of passive beneficiaries include: tool vendors, library vendors, and integrators. Those passive beneficiaries becoming involved with maintenance and enrichment of the FLS supports the capability to have safety-qualified Rust compilers. Safety-qualified Rust compilers is a prerequisite for certain levels of safety-criticality in certain industries. These passive beneficiaries contributing back to the ability to ship safety-critical Rust software is a healthy model to ensure continuity of FLS maintenance.

The next 6 months

Explore options for developing the capability to keep the FLS updated with the Rust language, in a sustainable way, at the cadence needed by its users and stakeholders.

The outcome of the next six months is variable. The entire six months could be investigative, with some prototyping. Or we could establish a concrete cadence and capacity for updating the FLS.

The “shiny future” we are working towards

The shiny future we are working towards is to ensure that we have the capability in place to keep the FLS updated at the pace needed by its users and stakeholders.

Ownership and team asks

Owner: Pete LeVasseur will champion this project goal.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam spec, lang
Adjust tooling, as neededPete LeVasseurPete to find appropriate person
Standard reviewsTeam lang,opsem, types, bootstrapFor any process changes, document updates and/or tooling integration
Continued updates for the FLSContributors from Ferrous Systems and others TBD
Review of updates to the FLSt-spec and contributors from Ferrous Systems

Frequently asked questions

Why this Project goal?

The goal is to ensure the FLS is updated sufficiently to meet the needs of its users and stakeholders.

Can this be done in six months?

Don’t know. But we need to start having the conversations with stakeholders and see where it can lead.

Getting documentation updated is hard. Who would do that work?

This may be the biggest blocker to making this goal successful. Part of this goal will be finding people who are interested in doing the work to author and review these updates or to find the budget to hire people to do this.

The safety-critical Rust community actively and passively benefits from the FLS, so it’s worthwhile to solicit engagement with the Safety-Critical Rust Consortium.

What happens if the FLS and Reference combine as one specification document?

That’s actually a potential outcome of the t-spec work in the future. So this may not be totally theoretical. Hopefully the processes we come up with are not so document specific and they can withstand such a merger.

Getting Rust for Linux into stable Rust: compiler features

Metadata
Point of contactTomas Sedovic
StatusProposed
Tracking issuerust-lang/rust-project-goals#407
Zulip channel#t-compiler, #rust-for-linux
compiler championWesley Wiser
Teamscompiler
Task owners(depending on the flag)

Summary

Continue working towards Rust for Linux on stable. In particular, this goal is focused on the compiler features.

Motivation

Getting the Linux kernel to build with stable Rust and, more generally, supporting the needs of the Linux kernel to make Rust a success there, has been a priority for the Rust project and a previous flagship goal: 2024H2, 2025H1.

One of the key areas are compiler features, which encompass a wide range of topics: architecture/target-related flags, sanitizers, mitigations, performance/optimization-oriented flags, and so on.

Thus, this project goal focuses on continuing the work that has been done in the last year around compiler features.

The status quo

The Linux kernel, at the time of writing, relies on some Rust compiler unstable features such as:

There are others that we will want to start using in the future, such as:

Relatedly, there is also the build-std project goal support that we need as well (or, rather, only “build-core” for the Linux kernel), and the sanitizers project goal.

The next 6 months

Ideally, the Linux kernel would not need to rely on any of the existing compiler unstable features by the time the period is over, but that is fairly unlikely. Thus, any progress on any feature (or an alternative to using a given unstable feature) would be welcome.

In particular, finishing the work and stabilizing the features that the kernel is already using upstream would be considered a major success.

The “shiny future” we are working towards

Longer-term, the Linux kernel does not rely on any compiler-related unstable feature anymore, except for those that may need to be added in the future for different reasons, such as:

  • New hardware features.
  • New mitigations.
  • New sanitizers.
  • New architectures.

For that reason, this goal is conceptually never ending, even if we may reach points where no unstable compiler feature is actually used.

Design axioms

An important design axiom that still applies from previous iterations is “Don’t let perfect be the enemy of good”. The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of functionality that meets the kernel developers’ needs while leaving other aspects unstable.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compilerContinue the Rust for Linux <-> Rust calls

Which flags get finished and stabilized depends on bandwidth and other constraints on both the Rust and the Rust for Linux sides, but generally we expect they will follow the usual pattern as we have done before.

Finish and stabilize a given -Z... flag

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler
Finalize remaining work(depending on the flag)
Author stabilization report(depending on the flag)
Author stabilization PR(depending on the flag)
Stabilization decisionTeam compiler

Frequently asked questions

Getting Rust for Linux into stable Rust: language features

Metadata
Point of contactTomas Sedovic
StatusProposed
Tracking issuerust-lang/rust-project-goals#116
Zulip channel#t-lang, #rust-for-linux
lang championJosh Triplett
lang-docs championTC
Teamslang, lang-docs
Task ownersDing Xiang Fei

Summary

Continue working towards Rust for Linux on stable. In particular, this goal is focused on the language features.

Motivation

Getting the Linux kernel to build with stable Rust and, more generally, supporting the needs of the Linux kernel to make Rust a success there, has been a priority for the Rust project and a previous flagship goal: 2024H2, 2025H1.

One of the key areas are language features, given the impact they could have on the kernel if they were to change, especially those that may require changes on potentially many source files and/or that may not be easy to workaround with conditional compilation.

Thus, this project goal focuses on continuing the work that has been done in the last year around those language features.

The status quo

The Linux kernel, at the time of writing, relies on a few Rust language unstable features:

In addition, there are others that we will likely want to start using in the future, such as:

For completeness, on the library side, we use:

Furthermore, on the compiler side, we use:

As well as a set of compiler flags and other features which have their own project goal.

The next 6 months

Ideally, the Linux kernel will not need to rely on any of the existing language unstable features, nor the related library and compiler features mentioned above, by the time the period is over. This would be a major milestone for both the Rust Project and Rust for Linux.

However, any progress on any feature (or an alternative to using a given unstable feature) would be welcome. In particular, finishing the work around arbitrary_self_types and derive_coerce_pointee and stabilizing them would be considered a major success.

The “shiny future” we are working towards

Longer-term, the Linux kernel does not rely on any language-related unstable feature anymore, including possible future ones that the kernel may need to start using, such as the others listed above.

Design axioms

An important design axiom that still applies from previous iterations is “Don’t let perfect be the enemy of good”. The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of functionality that meets the kernel developers’ needs while leaving other aspects unstable.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam langContinue the Rust for Linux <-> Rust calls

Which features get finished and stabilized depends on bandwidth and other constraints on both the Rust and the Rust for Linux sides, but generally we expect they will follow the usual pattern as we have done before.

Finish and stabilize arbitrary_self_types and derive_coerce_pointee

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Finalize remaining workDing Xiang Fei
Author Reference PRDing Xiang Fei
Review/revise Reference PRTeam lang-docs
Author stabilization reportDing Xiang Fei
Author stabilization PRDing Xiang Fei
Stabilization decisionTeam lang

Frequently asked questions

Borrow checking in a-mir-formality

Metadata
Point of contactNiko Matsakis
StatusProposed
Tracking issuerust-lang/rust-project-goals#122
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
types championNiko Matsakis
Teamstypes
Task ownersNiko Matsakis, tiif

Summary

Extend a-mir-formality with the ability to represent function bodies as MiniRust programs; a type checker based on the MIR type checker from the compiler; and a model that covers key parts of the the Polonius Alpha proposal.

Motivation

The goal of the a-mir-formality project is to (a) share and capture knowledge of how Rust’s static type checking works, including the type checker, trait checker, borrow checker, and in-progress areas like const generics; (b) enable prototyping and exploration of new ideas in a lighterweight environment that still exposes the “inherent complexity” of the feature while avoiding the “accidental complexity” of building a full-featured implementation in the compiler; (c) be a middle ground that can help us validate and prove Rust’s type safety. Achieving that last bullet requires integrating with MiniRust, which models the behavior of a Rust program when executed (“operational semantics”) and provides rules for what constitutes undefined behavior. If we align these two models, we should be able to test with fuzzing that, e.g., no fully safe program that passes the type check can, when executed with MiniRust, cause undefined behavior.

The status quo

Currently, a-mir-formality provides a partial formalization of Rust’s type and trait system, but it has significant limitations:

  1. No function body representation: The current model doesn’t include function bodies at all, focusing primarily on types and traits. This prevents modeling program execution and control flow.

  2. Absence of type checker: a-mir-formality doesn’t yet include an implementation of a type checker, which is essential for validating that programs conform to Rust’s type rules.

  3. No borrow checking model: The model doesn’t include any representation of Rust’s borrow checking system, including the newer Polonius approach.

  4. Gaps in the type system model: While the model covers key parts of Rust’s type and trait system, there are still notable gaps that limit its completeness.

  5. Limited knowledge sharing: Knowledge and understanding of a-mir-formality are fairly limited. We need more people to familiarize themselves with the setup to broaden expertise and ensure sustainability.

These limitations affect several key stakeholders:

  • Rust language designers who need a lightweight environment to prototype and explore new ideas without the accidental complexity of the full compiler
  • Compiler contributors who would benefit from shared, accessible knowledge about how Rust’s static type checking works
  • Researchers and educators who need formal models to validate Rust’s type safety claims and teach its concepts
  • Tool developers who could leverage formal models to build more accurate analysis tools

The next 6 months

Over the next 6 months, we will focus on three key extensions to a-mir-formality:

  1. MiniRust Integration: Implement the ability to represent function bodies as MiniRust programs, creating a bridge between static and dynamic semantics.

  2. MIR Type Checker: Develop a type checker based on the MIR type checker from the compiler, ensuring alignment between the formal model and actual implementation.

  3. Polonius Alpha Model: Create a model covering key parts of the Polonius Alpha proposal, advancing our ability to formalize and reason about Rust’s borrow checking.

The “shiny future” we are working towards

The long-term vision for a-mir-formality is to develop a comprehensive formal model covering the key components of Rust’s type system, trait resolution, and borrow checking. This model will evolve alongside the language, being maintained as new features are added to Rust and serving as a platform for prototyping language extensions. Additionally, a-mir-formality will integrate with complementary models like MiniRust and the Rust specification, creating a foundation for validating Rust’s type safety guarantees and sharing knowledge about the language’s semantics.

Design axioms

The goal of a-mir-formality is to be a step in between a high-level, mathematical description of Rust’s system (as one might find when doing proofs) and the full details of the compiler (which include significant additional complexity for performance, diagnostics, etc). It should be reasonable to assert that if a-mir-formality is sound, then the compiler is sound modulo small implementation bugs.

  • Recognizably the compiler. The goal of a-mir-formality is that the algorithms can be mapped to the compiler’s algorithms in a fairly straightforward way (though the compiler will have additional optimizations, caching, and all kinds of concerns that don’t matter to a-mir-formality).
  • Capture what’s essential. a-mir-formality doesn’t need to cover every detail of Rust but it should capture the ones that are important when reasoning about soundness and safety or the type system.
  • The compiler should be a sound, but incomplete version of a-mir-formality. Given some program P that falls within the scope of what a-mir-formality models, if the compiler accepts P, then a-mir-formality should accept P. But there may be some programs that the compiler refuses to accept because of implementation limitations that a-mir-formality would accept because it is willing to (for example) explore a larger search space.

Ownership and team asks

This section outlines the work to be done and the specific asks from Rust teams. A key challenge we face is limited knowledge and understanding of a-mir-formality’s setup. To address this, we’re asking for standard reviews from types team members and dedicated review for Polonius-related work.

TaskOwner(s) or team(s)Notes
Implementation of MiniRust integrationtiifExtending a-mir-formality to represent function bodies as MiniRust programs
Implementation of MIR type checkertiifCreating a type checker based on the compiler’s MIR type checker
Implementation of Polonius Alpha modeltiifModeling key parts of the Polonius Alpha proposal
Standard reviewsTeam typesHelp familiarize more people with the a-mir-formality setup through PR reviews
Dedicated reviewerTeam typesAssign specific reviewers for Polonius Alpha model implementation (Rémy Rakic)
MentorshipNiko MatsakisProviding guidance and mentorship for the implementation work

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.

Frequently asked questions

What is a-mir-formality?

a-mir-formality is a formal model of Rust’s type system, available at github.com/rust-lang/a-mir-formality/. It aims to provide a rigorous mathematical foundation for understanding Rust’s type system and semantics.

What is MiniRust?

MiniRust is a model of the behavior of a Rust program when executed (“operational semantics”) and provides rules for what constitutes undefined behavior. Integrating a-mir-formality with MiniRust will allow us to verify that programs that pass the type check don’t cause undefined behavior when executed.

Reborrow traits

Metadata
Point of contactAapo Alasuutari
StatusProposed
FlagshipBeyond the &
Tracking issuerust-lang/rust-project-goals#399
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
compiler championOliver Scherer
lang championTyler Mandry
Teamscompiler, lang
Task ownersAapo Alasuutari

Summary

Bring up a language RFC for autoreborrow traits and land nightly support for the traits.

Motivation

Reborrowing is an important feature of the Rust ecosystem, underpinning much of the borrow checker’s work and enabling ergonomic usage of references. The built-in, automatic handling of reborrows as a language feature is, arguably, one of the many keys to Rust’s success. Autoreborrowing is not available for user-space types to take advantage of, which hinders their ergonomics and usage.

Autoreborrowing is a necessary feature for both niche use-cases around lifetime trickery, and for flagship goals like Pin-ergonomics and the Rust for Linux project. As both of these are proceeding, a parallel track to pre-empt reborrowing becoming a sticking point seems wise. Luckily, reborrowing is arguably a solved problem that mostly needs a formal definition and a implementation choice to enter the language formally.

The status quo

Today, when an Option<&mut T> or Pin<&mut T> is passed as a parameter, it becomes unavailable to the caller because it gets moved out of. This makes sense insofar as Option<T> only being Copy if T: Copy, which &mut T is not. But it makes no sense from the point of view of &mut T specifically: passing an exclusive reference does not move the reference but instead reborrows it, allowing the &mut T to be reused after the call finishes. Since an Option<&mut T> is simply a maybe-null &mut T it would make sense that it would have the same semantics.

The lack of autoreborrowing is why this is not the case. This can be overcome by using the .as_deref_mut() method but it suffers from lifetime issues when the callee returns a value derived from the &mut T: that returned value cannot be returned again from the caller as its lifetime is bound to the .as_deref_mut() call. For Pin<&mut T> this problem has been side-stepped by adding Pin-specific nightly support of reborrowing pinned exclusive references.

But the same issue pops up again for any user-defined exclusive reference types, such as Mut<'_, T>. The user can define this type as having exclusive semantics by not making the type Copy, but they cannot opt into automatic reborrowing. The best they can hope is to implement a custom .reborrow_mut() method similar to the Option::as_deref_mut from above. Here again they run into the issue that the lifetime of a Mut<'_, T> always gets constrained to the .reborrow_mut() call, making it impossible to return values derived from a Mut<'_, T> from the function that called .reborrow_mut().

An improvement is needed.

The next 6 months

  • Bring up an RFC for autoreborrowing: a draft exists.
  • Choose the internal logic of recursive reborrowing: based on core marker types, or on interaction with Copy?
  • Implement nightly support for non-recursive reborrowing.
  • Gather feedback from users, especially reborrow crate users.
  • Implement nightly support for recursive reborrowing.

The basic idea of autoreborrowing is simple enough: when a reborrowable type is encountered at a coercion site, attempt a reborrow operation. The Pin<&mut T> special-case in the compiler already exists and could probably be reimagined to rely on a Reborrow trait.

Complications arise when reborrowing becomes recursive: if a struct X { a: A, b: B } contains two reborrowable types A and B, then we’d want the reborrow of X to be performed “piecewise”. As an example, the following type should, upon reborrow, only invalidate any values that depend on the 'a lifetime while any values dependent on the 'b lifetime should still be usable as normal.

#![allow(unused)]
fn main() {
struct X<'a, 'b> {
    a: &'a mut A,
    b: &'b B,
}
}

To enable this, reborrowing needs to be defined as a recursive operation but what the “bottom-case” is, that is the question. One option would be to use !Copy + Reborrow fields, another would use core marker types like PhantomExclusive<'a> and PhantomShared<'b> to discern the difference.

The “shiny future” we are working towards

Pin ergonomics group should be able to get rid of special-casing of Pin reborrowing in rustc.

Rust for Linux project should be enabled to experiment with custom reborrowable reference types in earnest.

Users of reborrow crate and similar should be enabled to move to core solution.

Design axioms

  • Accept the definition of reborrowing as “a memory copy with added lifetime analysis”.
    • This disallows running user code on reborrow.
    • “Reborrow-as-shared” likely needs to run user code; this’d preferably be ignored where possible.
  • Must achieve true reborrowing, not a fascimile.
    • Current userland reborrowing uses T::reborrow_mut functions that achieve the most important part of reborrowing, temporarily disabled T upon reborrow.
    • Userland cannot achieve true reborrowing: true reborrowing does not constrain the lifetime of T, whereas userland fascimile does.
    • Difference is in whether values derived from a reborrow can be returned past the point of the reborrow.
  • Performance of the solution must be trivial: reborrow is checked for at every coercion site. This cannot be slow.
  • Make sure autoreborrowing doesn’t become a vehicle for implicit type coercion. Allowing autoreborrowing from T to multiple values could be abused to define a CustomInt(int128) that coerces to all integer types.
    • Autoreborrow traits should use an associated type instead of a type parameter.
    • Autoreborrowing at coercion sites should not dovetail into eg. an Into::into call.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam langNormal RFC process
Standard reviewsTeam compilerTrait-impl querying in rustc to replace Pin<&mut T> special case
Lang-team experimentTeam langallows coding pre-RFC; only for trusted contributors
Do the workAapo Alasuutari

Frequently asked questions

build-std

Metadata
Point of contactDavid Wood
StatusProposed
FlagshipFlexible, fast(er) compilation
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#274
cargo championEric Huss
compiler championDavid Wood
libs championAmanieu d’Antras
Teamscargo, compiler, libs
Task ownersAdam Gemmell, David Wood

Summary

Over the next six months, we will continue our efforts to write an RFC for a minimum viable product (MVP) of build-std which has the potential to be stabilised once implemented (as opposed to the currently implemented MVP which is only suitable for experimentation and testing), and then implement it.

Motivation

build-std is a well-known unstable feature in Cargo which enables Cargo to re-build the standard library, this is useful for a variety of reasons:

  • Building the standard library for targets which do not ship with a pre-compiled standard library.
  • Optimising the standard library for known hardware, such as with non-baseline target features or options which optimise for code size. This is a common use case for embedded developers.
  • Re-building the standard library with different configuration options (e.g. changing the optimisation level, using flags which change the ABI, or which add additional exploit mitigations).
  • Re-building the standard library with different cfgs (e.g. disabling backtrace in std), to the extent that such configurations are supported by the standard library.
  • Stabilisation of various compiler flags which change the ABI, add additional exploit mitigations (such as -Zsanitizers=cfi or -Zbranch-protection), or which otherwise only make sense to use when the entire program is compiled with the flag (including std) is blocked on these being unable to be used properly without being able to rebuild std.

These features are more useful for some subsets of the Rust community, such as embedded developers where optimising for size can be more important and where the targets often don’t ship with a pre-compiled std.

The fifty-thousand foot view of the work involved in this feature is:

  • Having the standard library sources readily available that match the compiler.
  • Being able to build those sources without using a nightly toolchain, which has many possible solutions.
  • Having a blessed way to build at least core without Cargo, which some users like Rust for Linux would like.
    • This would be optional but may be a side-effect of whatever mechanism for build-std the MVP RFC eventually proposes.
  • Being able to tell the compiler to use the resulting prebuilt standard library sources instead of the built-in standard library, in a standard way.
  • Integrating all of the above into Cargo.
  • Making sure all of this works for targets that don’t have a pre-built std.

Rust for Linux and some other projects have a requirement to build core themselves without Cargo (ideally using the same stable compiler they use for the rest of their project), which is a shared requirement with build-std, as whatever mechanism these projects end up using could be re-used by the implementation of build-std and vice-versa.

The status quo

build-std is currently an unstable feature in Cargo which hasn’t seen much development or progress since its initial development in 2019/2020. There are a variety of issues in the wg-cargo-std-aware repository which vary from concrete bugs in the current experimental implementation to vague “investigate and think about this” issues, which make the feature difficult to make progress on.

Some of the work required for this exists in the current perma-unstable -Zbuild-std implementation, which may be re-used if appropriate.

In 2025H1, the goal owners established a regular sync meeting with liaisons from the library, compiler and Cargo teams which have been successful in creating a draft RFC that continues to be iterated on and refined before being shared with the broader project.

The next 6 months

There are two primary objectives of this goal in its first six months:

  • Continue to refine and draft a complete RFC for build-std, including a detailed history of the feature and surrounding discussions going back to its origins in 2015.
  • Next, after and conditional on acceptance of the RFC, proceed with its implementation.

As part of the goal, the goal owners will regularly be in contact with representatives from relevant teams in our regular sync call established during the 2025H1 goal period, and will commit to posting updates on our progress on a monthly basis.

The “shiny future” we are working towards

After the approval and implementation of the MVP RFC, there will naturally be follow-up use cases which can be designed and implemented to complete the build-std feature.

Design axioms

  • Enabling build-std without changing any compilation options or configuration should produce an equivalent library to that distributed by the project.
  • Avoid precluding future extensions to build-std.
  • build-std should allow std/alloc/core to be treated more like other dependencies than currently.
    • This represents a general move away from treating std/alloc/core as a special case.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, libs, compilerEric Huss, Josh Triplett and Wesley Wiser already regularly contribute
Author RFCDavid Wood, Adam GemmellContinue draft produced in 2025H1
Design meetingTeam cargo, libs, compilerReview initial RFC draft
RFC decisionTeam cargo, libs, compiler
ImplementationDavid Wood, Adam Gemmell
Standard reviewsTeam cargo, libs, compiler

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Prototype Cargo build analysis

Metadata
Point of contactWeihang Lo
StatusProposed
Tracking issuerust-lang/rust-project-goals#398
Zulip channelN/A
cargo championWeihang Lo
Teamscargo
Task ownersHelp wanted Weihang Lo, Weihang Lo

Summary

Prototype support for build analysis in Cargo by recording build metadata across invocations. This will introduce unstable subcommands in cargo report to explain why crates were rebuilt and to surface timing data from past builds, helping developers diagnose and improve their build performance.

Motivation

As Rust’s popularity grows and projects increase in size and complexity, long build times have become a growing pain point for the community and industry alike. Understanding why builds behave the way they do and why they slow down over time is critical to improving the developer experience of Rust and Cargo.

The status quo

Other than caching build artifacts and future-incompatibility reports, Cargo does not persist information about previous builds. While the --timings flag provides per-build data on how long each unit takes to compile, this information:

  • You have to know you will care about a timings report and can’t look it up afterwards
  • Exists primarily in HTML form, which is not suited for machine analysis

Additionally, Cargo does not track:

  • Build cache effectiveness and rebuild reasons
  • Invocation metadata (e.g., CLI flags, profiles, environment variables)
  • System resources usage (e.g., memory and CPU)

This limits our ability to:

  • Understand real-world build behavior over time
  • Explain why crates were rebuilt between builds
  • Experiment with performance optimizations, such as adaptive scheduling

The next 6 months

Cargo will provide an opt-in unstable configuration option to collect the following data:

  • The existing metrics collected by the --timings flag
  • Rebuild reasons and related information
  • CLI arguments for each build

Each data record will be associated with a build identifier, such as CARGO_RUN_ID, to make it possible to link related data within the same Cargo invocation.

Two new unstable commands in cargo report will be introduced (command name TBD):

  • cargo report rebuild-reasons: Show which crates were rebuilt for a specific Cargo run and why.
  • cargo report timing: Display timing data for a specific build, including per-crate compile times.

During the prototyping phase, the data may be stored as JSON blobs in a simple database format, such as SQLite. This approach allows schema evolution without committing to a stable format.

The “shiny future” we are working towards

  • Experiment with adaptive scheduling to reduce critical path length in builds
  • Extend cargo report with richer insights, such as:
    • Highlighting frequently rebuilt crates and their triggers
    • Summarizing build metrics and offering actionable suggestions
  • Enable external tooling to:
    • Analyze historical trends and identify performance bottlenecks
    • Provide live insights into slow build steps during development
  • Record additional build metrics to unlock more future capabilities and analysis, such as build replay for debugging and CI reproducibility

Design axioms

  • The changes to Cargo should not impede the development of Cargo
  • Metric collection must avoid introducing privacy or performance concerns
  • No user-facing stability guarantees during the prototyping phase
  • Data collection is opt-in and disabled by default

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo
ImplementationHelp wanted Weihang Lo
Standard reviewsTeam cargo
Author call for testing blog postWeihang Lo

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Is this telemetry?

No. This is not. Cargo follows the principles described in http://esteban.kuber.com.ar/rustc-metrics.html and does not send data anywhere. All metrics are stored locally and remain under the user’s control.

Rework Cargo Build Dir Layout

Metadata
Point of contactRoss Sullivan
StatusProposed
Tracking issuerust-lang/rust-project-goals#401
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
cargo championWeihang Lo
Teamscargo
Task ownersRoss Sullivan

Summary

Rework the Cargo build directory layout to have smaller self contained “units”

Motivation

Reworking the build directory layout into units will allow us to work to greater Cargo goals.

Notably

  • Fine grain locking within the build directory
    • Reducing build dir lock contention between Cargo and Rust Analyzer
  • GC of target directories
  • A cross workspace shared build cache

The status quo

When Cargo performs a build, it will build the package you requested and all dependencies individually, linking them in the end. These build results (intermediate build artifacts) are stored in the Cargo build cache. (commonly referred to as build-dir)

The build cache organizes files in a way that is not easily broken down into smaller units. Due to this Cargo will lock the entire build cache when operating to prevent multiple Cargo processes from interfering with each other. This locking is commonly felt by users when Rust Analyzer triggers a cargo check while the user is attempting to build the project with cargo build, resulting in the build needing to wait for cargo check to finish.

The build cache layout is also makes caching in CI difficult as the intermediate build artifacts for each crate are scattered across many subdirectories. Users will often cache the entire target directory or attempt selectively cache build cache internals by making assumptions about Cargo implementation details.

The build cache is shared for projects in a Cargo workspace, however some users share the build cache by setting a shared CARGO_TARGET_DIR. This comes with some limitations like running cargo clean will remove the build cache for all workspaces.

For more information about the pain points with the status quo see the following issues:

The next 6 months

  • Rework the build directory layout so that we have more easily cacheable/lockable “units” (rust-lang/cargo#15010)
  • Rework the build directory locking to avoid locking the entire build directory.

The “shiny future” we are working towards

The build directory layout is reorganized in a way that makes fine grain caching and locking easier. Tools that leverage Cargo (like Rust Analyzer) have reduced lock contention and generally are able to operate in parallel on a shared build cache.

A new “user wide” cache is created as a first class solution for sharing build cache artifacts across workspaces.

The cache lookup will be extended with plugins to read and/or write to different sources. Open source projects and companies can have their CI read from and write to their cache. Individuals who trust the CI can then configure their plugin to read from the CI cache.

A cooperating CI service could provide their own plugin that, instead of caching everything used in the last job and unpacking it in the next, their plugin could download only the entries that will be needed for the current build (e.g. say a dependency changed) and only upload the cache entries that were freshly built. Fine grain caching like this would save the CI service on bandwidth, storage, and the compute time from copying, decompressing, and compressing the cache. Users would have faster CI time and save money on their CI service, minus any induced demand that faster builds creates.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Standard reviewsTeam cargo
ImplementationRoss Sullivan

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Why not pre-built packages?

Pre-built packages requires guessing

  • CPU Architecture
  • Feature flags
  • RUSTFLAGS
  • Dependency versions

If there are any mismatches there, then the pre-built package can’t be used.

A build cache can be populated with pre-built packages and react to the unique circumstances of the user.

Why not sccache?

Tools like sccache try to infer inputs for hashing a cache key from command-line arguments. This has us reusing the extra knowledge Cargo has to get more accurate cache key generation.

Prototype a new set of Cargo “plumbing” commands

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#264
cargo championEd Page
Teamscargo
Task ownersHelp wanted, Ed Page

Summary

Create a third-party cargo subcommand that has “plumbing” (programmatic) subcommands for different phases of Cargo operations to experiment with what Cargo should integrate.

Motivation

Cargo is a “porcelain” (UX) focused command and is highly opinionated which can work well for common cases. However, as Cargo scales into larger applications, users need the ability to adapt Cargo to their specific processes and needs.

The status quo

While most Cargo commands can be used programmatically, they still only operate at the porcelain level. Currently, Cargo’s plumbing commands are

  • cargo read-manifest:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • deprecated
  • cargo locate-project:
    • works off of a Cargo.toml file on disk
    • text or json output, undocumented json schema
    • uses a pre-1.0 term for package
  • cargo metadata:
    • works off of Cargo.toml, Cargo.lock files on disk
    • uses a custom json schema
    • can include dependency resolution but excludes feature resolution
    • some users want this faster
    • some users want this to report more information
    • See also open issues
  • cargo pkgid:
    • works off of Cargo.toml, Cargo.lock files on disk
    • text output
  • cargo verify-project:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • uses a pre-1.0 term for package
    • deprecated

There have been experiments for a plumbing for builds

  • --build-plan attempts to report what commands will be run so external build tools can manage them.
    • The actual commands to be run is dynamic, based on the output of build scripts from build graph dependencies
    • Difficulty in supporting build pipelining
  • --unit-graph reports the graph the build operates off of which corresponds to calls to the compiler and build scripts
    • Also provides a way to get the results of feature resolution

The next 6 months

Continue on the third-party subcommand to experiment with plumbing commands (source).

A build in Cargo can roughly be split into

  1. Locate project
  2. Read the manifests for a workspace
  3. Read lockfile
  4. Lock dependencies
  5. Write lockfile
  6. Resolve features
  7. Plan a build, including reading manifests for transitive dependencies
  8. Execute a build
  9. Stage final artifacts

These could serve as starting points for experimenting with plumbing commands. Staging of final artifacts may not be worth having a dedicated command for. This is exclusively focused on build while other operations may be of interest to users. We can evaluate those commands in the future as they tend to still build off of these same core primitives.

At minimum, later commands in the process would accept output from earlier commands, allowing the caller to either replace commands (e.g. custom dependency resolver) or customize the output (e.g. remove dev-dependencies from manifests).

Encapsulating stabilized file formats can serve as a starting point for output schemas as we already output those and have to deal with stability guarantees around these.

Between planning a build and executing a build is likely to look like --unit-graph and a plan will need to be put forward for how to work through the open issues. There will likely be similar issues for any other output that can’t leverage existing formats.

Cargo’s APIs may not be able to expose each of these stages and work may need to be done to adapt it to support these divisions.

The performance of piping output between these commands may be sub-par, coming from a combination of at least

  • Cargo’s APIs may require doing more work than is needed for these stages
  • Cargo focuses on json for programmatic output which may prove sub-par (see also zulip)
  • Cargo’s serde structures may not be optimized
  • If customizing only a single step in this process, requiring serializing and deserializing through all of the other stages may be superfluous

Low hanging or egregious bottlenecks may need to be addressed. Otherwise, performance should wait on user feedback.

A schema evolution plan will need to be considered with the design of the schema. How Cargo deals with evolution of existing output could serve as potential starting points:

  • Cargo.toml (generated by cargo package) should still be readable by cargo versions within the specified package.rust-version
    • In the absence of a package.rust-version, Cargo.toml should only represent features the user explicitly used or optional features that were always allowed on stable cargo
  • Cargo.lock (generated by most commands) is strictly versioned: all versions of Cargo should output a lockfile that works in all other versions of Cargo for that given version and changing Cargo versions should not cause the output to change
    • Cargo bumps the default format version after it has been stabilized for a “sufficient period of time”
    • The default is capped by what is supported by the lowest package.rust-version in the workspace
  • cargo metadata --format-version: defaults to “latest” with a warning
    • We attempt to follow the same practice as Cargo.toml
  • --message-format: no versioning currently
    • We attempt to follow the same practice as Cargo.toml

The “shiny future” we are working towards

  • Collect user feedback on these commands and iterate on them for eventual inclusion into Cargo
  • Evaluate refactoring Cargo to better align with these plumbing commands to have better boundaries between subsystems
  • Evaluate splitting the cargo [lib] into crates for each of these plumbing commands as smaller, more approachable, more “blessed” Rust APIs for users to call into

Design axioms

  • The changes to Cargo should not impede the development of Cargo
  • The schemas and planned evolution should not impede the development of Cargo
  • The plumbing commands should be focused on solving expected or known needs, avoiding speculation.

Ownership and team asks

Owner: Identify a specific person or small group of people if possible, else the group that will provide the owner. GitHub user names are commonly used to remove ambiguity.

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo
ImplementationHelp wanted
Optimizing CargoHelp wanted, Ed Page
Inside Rust blog post inviting feedbackEd Page

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Stabilize cargo-script

Metadata
Point of contactEd Page
StatusProposed
FlagshipHigher-level Rust
Tracking issuerust-lang/rust-project-goals#119
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
cargo championEd Page
lang championJosh Triplett
lang-docs championJosh Triplett
Teamscargo, compiler, lang, lang-docs
Task ownersEd Page

Summary

Stabilize support for “cargo script”, the ability to have a single file that contains both Rust code and a Cargo.toml.

Motivation

Being able to have a Cargo package in a single file can reduce friction in development and communication, improving bug reports, educational material, prototyping, and development of small utilities.

The status quo

Today, at minimum a Cargo package is at least two files (Cargo.toml and either main.rs or lib.rs). The Cargo.toml has several required fields.

To share this in a bug report, people resort to

  • Creating a repo and sharing it
  • A shell script that cats out to multiple files
  • Manually specifying each file
  • Under-specifying the reproduction case (likely the most common due to being the easiest)

To create a utility, a developer will need to run cargo new, update the Cargo.toml and main.rs, and decide on a strategy to run this (e.g. a shell script in the path that calls cargo run --manifest-path ...).

The next 6 months

Cargo and basic rustc support is already implemented on nightly. The goal is to finalize things within the rust repo and stabilize. With RFC #3502 and RFC #3503 approved, the next steps are being tracked in rust-lang/cargo#12207 and rust-lang/rust#136889(https://github.com/rust-lang/rust/issues/136889).

At a high-level, this is

  • rustfmt gracefully handling the presence of a frontmatter
  • r-a gracefully handling the presence of a frontmatter
  • Fix a known bug in rustc’s lexer (rust-lang/rust#141367(https://github.com/rust-lang/rust/issues/141367)).
  • Improve error messages in Cargo

The “shiny future” we are working towards

Design axioms

  • In the trivial case, there should be no boilerplate. The boilerplate should scale with the application’s complexity.
  • A script with a couple of dependencies should feel pleasant to develop without copy/pasting or scaffolding generators.
  • We don’t need to support everything that exists today because we have multi-file packages.

Ownership and team asks

Tracking issue cargo#12207:

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler
Ensure Cargo implementationEd Page

Implement language feature frontmatter

Tracking issue #136889(https://github.com/rust-lang/rust/issues/136889):

TaskOwner(s) or team(s)Notes
Rust-analyzer implementationEd Page
rustfmt implementationEd Page
Standard reviewsTeam compiler
Author call for testing blog postEd Page

Stabilize language feature frontmatter

TaskOwner(s) or team(s)Notes
Author Reference PREd Page
Review/revise Reference PRTeam lang-docsEric Huss
Author stabilization reportEd Page
Author stabilization PREd Page
Stabilization decisionTeam lang

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Continue resolving cargo-semver-checks blockers for merging into cargo

Metadata
Point of contactPredrag Gruevski
StatusProposed
Tracking issuerust-lang/rust-project-goals#104
Zulip channelN/A
cargo championEd Page
rustdoc championAlona Enraght-Moony
Teamscargo, rustdoc
Task ownersPredrag Gruevski

Summary

Design and implement cargo-semver-checks functionality that lies on the critical path for merging the tool into cargo itself. Continues the work of the 2025h1 goal.

Motivation

Cargo assumes that all packages adhere to semantic versioning (SemVer). However, SemVer adherence is quite hard in practice: research shows that accidental SemVer violations are relatively common (lower-bound: in 3% of releases) and happen to Rustaceans of all skill levels. Given the significant complexity of the Rust SemVer rules, improvements here require better tooling.

cargo-semver-checks is a linter for semantic versioning (SemVer) in Rust. It is broadly adopted by the Rust community, and the cargo team has expressed interest in merging it into cargo itself as part of the existing cargo publish workflow. By default, cargo publish would require SemVer compliance, but offer a flag (analogous to the --allow-dirty flag for uncommitted changes) to override the SemVer check and proceed with publishing anyway.

The cargo team has identified a set of milestones and blockers that must be resolved before cargo-semver-checks can be integrated into the cargo publish workflow. Our goal here is to make steady progress toward resolving them.

The status quo after the 2025h1 goal period

The 2025h1 goal targeted work in two major areas:

  • Checking of cross-crate items
  • SemVer linting of type information

While meaningful progress was achieved, significant work remains to be done.

'static bounds were discovered to be able to be implied, meaning that the bound is not syntactically present at the public API definition site, but is nevertheless part of the public API via being implied by another bound (or by a bound implied by such a bound, etc.). Conversely, ?Sized was discovered to possibly not apply even when syntactically present, as an implied bound elsewhere may imply Sized and take precedence over ?Sized. SemVer linting requires precise—not just syntactic—information in both of these cases. Failure to obtain precise information would lead to both false-positives and false-negatives, which would be an unacceptable user experience. Rustdoc JSON today does not include such precise information; the addition of such information is currently under discussion with the rustdoc team.

Outside of these special cases of type-checking lints, some progress was made on a concrete plan for more general type-checking lints. The current plan is to make use of Rust’s only stable API: “please compile this program for me.” Whenever types in any public API location might appear to have changed, cargo-semver-checks would generate a witness program and check it via cargo check, such that compilation would only succeed if the type change is backward-compatible. This is an extension of the same technique we used several years ago in our survey of SemVer compliance and breakage in the Rust ecosystem. One of Rust’s Google Summer of Code participants is working toward making witness generation work end-to-end, and we’re thrilled to be working together!

As part of the All Hands at RustWeek, we also made progress toward enabling cross-crate linting. We identified a set of changes in Rust tooling that, when implemented, will result in cargo-semver-checks being able to uniquely determine which crate and version a given item came from. While all stakeholders are aligned on the idea and have reasonable confidence that it will work as planned, much more implementation work remains to be done and it’s possible additional obstacles may be identified along the way.

Checking of cross-crate items

This section is background information and is unchanged from the 2024h2 goal.

Currently, cargo-semver-checks performs linting by only using the rustdoc JSON of the target package being checked. However, the public API of a package may expose items from other crates. Since rustdoc no longer inlines the definitions of such foreign items into the JSON of the crate whose public API relies on them, cargo-semver-checks cannot see or analyze them.

This causes a massive number of false-positives (“breakage reported incorrectly”) and false-negatives (“lint for issue X fails to spot an instance of issue X”). In excess of 90% of real-world false-positives are traceable back to a cross-crate item, as measured by our SemVer study!

For example, the following change is not breaking but cargo-semver-checks will incorrectly report it as breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example() {}

// in the new release, imagine this function moved to `another_crate`:
pub use another_crate::example;
}

This is because the rustdoc JSON that cargo-semver-checks sees indeed does not contain a function named example. Currently, cargo-semver-checks is incapable of following the cross-crate connection to another_crate, generating its rustdoc JSON, and continuing its analysis there.

Resolving this limitation will require changes to how cargo-semver-checks generates and handles rustdoc JSON, since the set of required rustdoc JSON files will no longer be fully known ahead of time. It will also require CLI changes in the same area as the changes required to support manifest linting.

While there may be other challenges on rustc and rustdoc’s side before this feature could be fully implemented, we consider those out of scope here since there are parallel efforts to resolve them. The goal here is for cargo-semver-checks to have its own story straight and do the best it can.

SemVer linting of type information

This section is background information and is unchanged from the 2024h2 goal.

In general, at the moment cargo-semver-checks lints cannot represent or examine type information. For example, the following change is breaking but cargo-semver-checks will not detect or report it:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: i64) {}
}

Analogous breaking changes to function return values, struct fields, and associated types would also be missed by cargo-semver-checks today.

The main difficulty here lies with the expressiveness of the Rust type system. For example, none of the following changes are breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: impl Into<String>) {}

// subsequent release:
pub fn example<S: Into<String>>(value: S) {}
}

Similar challenges exist with lifetimes, variance, trait solving, async fn versus fn() -> impl Future, etc.

While some promising preliminary work has been done toward resolving this challenge, more in-depth design work is necessary to determine the best path forward.

The next 6 months

  • Expose precise information regarding 'static and ?Sized, then make use of it in lints.
  • Audit our current set of lints related to trait and lifetime bounds, aiming to create a comprehensive list of what lints we still need to add.
  • Support our GSoC contributor in building witness program generation and type-checking infrastructure.
  • Support the rustdoc team in exposing additional information we require, by contributing ideas and pull requests as needed while seeking to minimize the review and maintenance burden thus applied.

The “shiny future” we are working towards

This section is unchanged from the 2024h2 goal.

Accidentally publishing SemVer violations that break the ecosystem is never fun for anyone involved.

From a user perspective, we want a fearless cargo update: one’s project should never be broken by updating dependences without changing major versions.

From a maintainer perspective, we want a fearless cargo publish: we want to prevent breakage, not to find out about it when a frustrated user opens a GitHub issue. Just like cargo flags uncommitted changes in the publish flow, it should also quickly and accurately flag breaking changes in non-major releases. Then the maintainer may choose to release a major version instead, or acknowledge and explicitly override the check to proceed with publishing as-is.

To accomplish this, cargo-semver-checks needs the ability to express more kinds of lints (including manifest and type-based ones), eliminate false-positives, and stabilize its public interfaces (e.g. the CLI). At that point, we’ll have lifted the main merge-blockers and we can consider making it a first-party component of cargo itself.

Ownership and team asks

Owner: Predrag Gruevski, as maintainer of cargo-semver-checks

I (Predrag Gruevski) will be working on this effort. The only other resource request would be occasional discussions and moral support from the cargo and rustdoc teams, of which I already have the privilege as maintainer of a popular cargo plugin that makes extensive use of rustdoc JSON.

TaskOwner(s) or team(s)Notes
Expose precise 'static and ?Sized infoPredrag Gruevski
Lints for 'static and ?SizedPredrag Gruevski
Audit lints for lifetime and trait boundsPredrag Gruevski
Support our GSoC contributor’s work on witness programs and type-checking infraPredrag Gruevski
Discussion and moral supportTeam cargo rustdoc

Frequently asked questions

This section is unchanged from the 2024h2 goal.

Why not use semverver instead?

Semverver is a prior attempt at enforcing SemVer compliance, but has been deprecated and is no longer developed or maintained. It relied on compiler-internal APIs, which are much more unstable than rustdoc JSON and required much more maintenance to “keep the lights on.” This also meant that semverver required users to install a specific nightly versions that were known to be compatible with their version of semverver.

While cargo-semver-checks relies on rustdoc JSON which is also an unstable nightly-only interface, its changes are much less frequent and less severe. By using the Trustfall query engine, cargo-semver-checks can simultaneously support a range of rustdoc JSON formats (and therefore Rust versions) within the same tool. On the maintenance side, cargo-semver-checks lints are written in a declarative manner that is oblivious to the details of the underlying data format, and do not need to be updated when the rustdoc JSON format changes. This makes maintenance much easier: updating to a new rustdoc JSON format usually requires just a few lines of code, instead of “a few lines of code apiece in each of hundreds of lints.”

Emit Retags in Codegen

Metadata
Point of contactIan McCormack
StatusProposed
Tracking issuerust-lang/rust-project-goals#392
Zulip channelN/A
compiler championRalf Jung
lang championTyler Mandry
opsem championRalf Jung
Teamscompiler, opsem
Task ownersIan McCormack

Summary

Allow codegen backends to implement the MIR Retag intrinsic, and add a similar intrinsic to the LLVM backend.

Motivation

Miri uses Rust’s Retag intrinsics to find aliasing bugs, but they are only available in the MIR. This limits the category of tools that can use this information to find Rust-specific forms of undefined behavior. We propose making these intrinsics available to codegen backends so that it can be possible to find these bugs using native instrumentation. We aim at having both an RFC and experimental nightly implementation in this period.

The status quo

Miri has a unique role for the Rust community as the only tool that can find violations of Rust’s evolving aliasing models. However, Miri is significantly slower than native execution, and it does not support finding aliasing violations triggered by foreign function calls. Lack of FFI support has prevented developers from finding aliasing bugs in real-world libraries—including one maintained by the Rust project (flate2-rs)! We need a new approach for finding these bugs in the large-scale, multi-language projects where Rust is being adopted.

We could provide both better performance and support for multilanguage applications by inserting native run-time checks into shared formats like LLVM IR. These checks could be implemented in several different ways, possibly as an extension to Valgrind or a new LLVM sanitizer. However, before we can fully prototype any of these approaches, we need a way to take the type information that Miri uses to find aliasing violations and lower it into Rust’s codegen backends, where it can be used to determine where and how to insert these run-time checks.

Luckily, there’s already a mechanism that we can extend to provide everything that we need to support these tools. Miri configures the compiler to emit Retag intrinsics in the MIR. These are used to update the permissions associated with pointers under each aliasing model (see Tree Borrows for a deeper dive into the role of a retag). However, at the moment, retags are discarded once they reach codegen.

The next 6 months

We are creating a proof-of-concept extension that allows codegen backends to implement custom behavior for retags. Our changes include a new @llvm.retag intrinsic within the LLVM backend. Dynamic instrumentation tools can replace this intrinsic with concrete run-time checks. We plan on taking our current implementation and refinining it over this development period with feedback from the compiler and opsem teams.

This is not quite as simple as emitting an LLVM intrinsic for each MIR intrinsic, though. Miri executes some retags implicitly as side-effects of interpreting other instructions, and it determines the effect of a retag at run-time using type information that we will not have access to at the LLVM level. We need to emit all of these implicit retags ahead of time, along with the permissions that they carry under the aliasing model that’s being targeted.

The “shiny future” we are working towards

These changes will be necessary to support BorrowSanitizer: an out-of-tree LLVM instrumentation tool for finding violations of Rust’s aliasing model. BorrowSanitizer will be capable of finding aliasing violations, as well as other classic memory safety issues. Our tool is not fully functional yet, but we aspire for it to become a production-ready solution for developers who are integrating Rust components into large-scale C++ applications. You can read more about our goals at our website or in the abstract that we submitted for the 2025 Rust Verification Workshop.

However, beyond BorrowSanitizer, we believe that the these changes will be necessary to support any kind of tool for finding aliasing bugs with native instrumentation. Model-checkers for Rust (see SEABMC) will also benefit from having additional ownership information from the frontend.

Design axioms

Avoid targeting any particular aliasing model

Rust’s aliasing model is still evolving, and both Stacked and Tree Borrows require different types of retags in different places (e.g. Stacked Borrows retags raw pointers after they are cast from references, but Tree Borrows does not). Ralf Jung has indicated that there will still be significant changes coming—potentially as a part of a third aliasing model. In anticipation of these changes, we need make these backend retags configurable to support all of the features of Stacked and Tree Borrows. To make this easy to maintain, we should allow third-party compiler plugins to override the behavior of a retag at this level, so that tools can adapt quickly to changes in Rust’s aliasing model while it remains unstable.

Make changes as minimal as possible

We should avoid making changes that substantially impact any component of the compiler or Miri. We would benefit from having guidance from the Miri team, but we do not think that it will be necessary to make any changes to Miri.

Ownership and team asks

TaskOwner(s) or team(s)Notes
ImplementationIan McCormackproof-of-concept
Author RFCIan McCormack
Design meetingTeam opsem, compiler
Standard reviewsTeam opsem, compiler
Dedicated reviewerTeam opsem, compilerMost of our changes are within rustc_codegen_ssa, but it would also be helpful to have feedback from someone familiar with how retags are handled within Miri’s borrow_tracker module.
RFC decisionTeam opsem, compiler
Discussion and moral supportTeam opsem, compiler

Definitions

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.

Frequently asked questions

None yet.

Comprehensive niche checks for Rust

Metadata
Point of contactBastian Kersting
StatusProposed
Tracking issuerust-lang/rust-project-goals#262
Zulip channelhttps://rust-lang.zulipchat.com/#narrow/channel/435869-project-goals/topic/Null.20and.20enum-discriminant.20runtime.20checks.20in.20.28goals.23262.29/with/508256920
compiler championBen Kimock
opsem championBen Kimock
Teamscompiler, opsem
Task ownersBastian Kersting], Jakob Koschel

Summary

Add runtime checks to rustc that check for valid niche values. This is an extension of a previous project goal that added null pointer and enum checks and generally works towards checking for Undefined behavior at runtime (in debug builds / behind compiler flags).

The check should fire for invalid values that are already created by inserting a check at load-time / on function entry.

Motivation

Rust has a few types that specify “invalid values” for themselves, which means values that can never be occupied by an instance of this type. An example of that would be 0 for std::num::NonZeroUsize, or null for std::ptr::NonNull. These so called niches are used for optimizations, for example when being used together with Option, where Option<NonNull<T>> has the same size as *mut T.

In safe Rust it is never possible to construct such values, but that is different for unsafe Rust or FFI. E.g. with Rusts growing interop with C (e.g. in the Linux Kernel) and C++ it makes sense to expose such types over the language boundary. That can make for situations where a valid C or C++ value becomes an invalid Rust value.

The status quo

While Miri exists and does a great job at catching various types of UB in unsafe Rust code, it has the downside of only working on pure Rust code. Extern functions can not be called and a mixed language binary is unable to be executed in Miri.

We already added support for checking enum discriminants which is somewhat related, but this does not cover general niches.

Selecting where to insert these runtime checks for UB can be tricky. For example, if we want to detect a call in C++ which passes a null pointer to a Rust function that takes a reference (which thus gets the LLVM nonnull attribute), we cannot just insert a check inside the Rust function, because our check would be trivially optimized out (the parameter is guaranteed to not be null!). At a minimum, codegen needs to also not use such parameter attributes when niche checks are enabled then also insert the checks in a new block at the start of the function before the parameter is used.

In addition, technically any typed copy asserts the validity of the copied value as the type in question. But naively inserting a runtime check before every typed copy of a value with a niche can more than double compile time: https://github.com/rust-lang/rust/pull/104862#issuecomment-1773363404.

Thus validating all niches will require something more strategic, such as only inserting checks when SSA values are loaded from memory.

The next 6 months

Within the next six months we would like to do the following things:

  1. Develop a comprehensive niche value check for all niches.
  2. Insert it ideally when values are loaded from memory (e.g. a “checked-load”) or on function entry.
  3. Migrate the enum check to the same system mentioned in 2.

The “shiny future” we are working towards

Similar to how UBSan exists in Clang, we would like to see an option in Rust to detect undefined behavior at runtime. As mentioned above, this is critical for cross-language interoperability and can help catch UB before it reaches production.

The extension of these checks can be done step-by-step, keeping in mind the overhead. Different checks can be enabled by separate flags (like in UBSan). Eventually we would like to check (sanitize) most items listed as UB in Rust.

Ownership and team asks

Owner: [Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler, opsem
ImplementationBastian Kersting], Jakob Koschel
MCP decisionTeam compilerWhere to insert the check / checked load
Dedicated reviewerTeam compiler, opsemBen Kimock

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Const Generics

Metadata
Point of contactBoxy
StatusProposed
Tracking issuerust-lang/rust-project-goals#100
Zulip channelN/A
lang championNiko Matsakis
Teamslang
Task ownersBoxy, Noah Lev

Summary

Work towards stabilizing the remaining const generics functionality that was left out of the original min_const_generics feature.

Motivation & Status Quo

The min_const_generics feature was stabilized with a number of limitations, while some have since been lifted there are still some things we do not support:

  • Inferred arguments to const parameters (feature(generic_arg_infer))
  • Const parameters with arbitrary user-defined types (feature(adt_const_params))
  • Non-concrete uses of associated constants in the type system (feature(min_generic_const_args)/feature(associated_const_equality))

When using const generics it is common to run into these limitations and be unable to move forwards, having to rewrite your code to use workarounds or not use const generics at all. This is a poor user experience and makes the language feel incomplete.

The next 6 months

  • Write a document outlining the main design decisions of adt_const_params and discuss it with the lang team, follow up with an RFC
  • Finish implementing the min_generic_const_args (mgca) feature prototype

The “shiny future” we are working towards

All parts of the const generics feature that were left out of the minimum stabilization have now been stabilized. Users do not encounter “functionality cliffs” where const generics suddenly stops working as well as type generics, forcing code to be rewritten to work around language limitations.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Design meetingTeam langtopic: adt_const_params design
adt_const_params RFC draftBoxy
Finish mgca prototypeBoxy, Noah Lev

Ergonomic ref-counting: RFC decision and preview

Metadata
Point of contactNiko Matsakis
StatusProposed
FlagshipHigher-level Rust
Tracking issuerust-lang/rust-project-goals#107
Zulip channelN/A
compiler championSantiago Pastorino
lang championNiko Matsakis
Teamscompiler, lang
Task ownersNiko Matsakis, Santiago Pastorino

Summary

We propose to write an alternative RFC for ergonomic ref-counting that makes lightweight cloning automatic and hold design meetings so the lang team can compare both approaches. This work builds on RFC #3680, which proposed a new keyword, use, that could be used with closures (use || ...) and expressions like x.use to help address a longstanding problem: working with ref-counted data structures like Arc<T> is verbose and confusing.

The 2025H1 work delivered .use syntax that works technically, but community feedback on the RFC pointed out a tension: if we’re trying to improve ergonomics, why add more required syntax? We’ll write an RFC exploring the automatic approach, complete the implementation work needed to support it, and run design meetings to help the lang team decide. This will tell us about the impact on user experience and performance, how well we can catch problematic cases, and which approach works better for Rust developers working with ref-counted data.

Motivation: Reference counting is a common pain point across many kinds of Rust applications

The status quo

Working with ref-counted data structures creates verbose and confusing patterns that affect most non-trivial Rust applications. The friction appears not just with user-facing Arc<T> and Rc<T>, but throughout Rust’s ecosystem where ref-counting is pervasive but often hidden.

Consider this common pattern when spawning async tasks:

#![allow(unused)]
fn main() {
// Today: verbose and repetitive
let config = Arc::new(load_config());
let database = Arc::new(connect_db());
let metrics = Arc::new(MetricsCollector::new());

let config_clone = config.clone();
let database_clone = database.clone(); 
let metrics_clone = metrics.clone();
spawn(async move {
    process_request(config_clone, database_clone, metrics_clone).await;
});
}

This pattern appears throughout Rust codebases, particularly in async and concurrent code. The repetitive cloning obscures the actual logic and creates maintenance burden when adding or removing shared data.

Applies to high- and low-level code

Explicit cloning friction affects all kinds of Rust projects. This is most apparent in higher-level applications, where the need for explicit cloning (particularly in closures) emerges as one of the largest pain points, but it applies to lower-level development too, particularly async network services. Ref-counting is also applicable beyond Rc or Arc, as numerous types (e.g., the channel channel handles found in libstd and tokio) are ref-counted under the hood. Improving the ergonomics of working with ref-counted data is one of those rare cases to simultaneously improve the lives of developers using interop crates like PyO3, GUI crates like Sycamore and dioxus, and tokio simultaneously. As the blog post from Dioxus labs put it:

While working at Cloudflare, I had to work with a struct with nearly 30 fields of Arced data. Spawning tokio tasks looked like:

#![allow(unused)]
fn main() {
// listen for dns connections
let _some_a = self.some_a.clone();
let _some_b = self.some_b.clone();
let _some_c = self.some_c.clone();
let _some_d = self.some_d.clone();
let _some_e = self.some_e.clone();
let _some_f = self.some_f.clone();
let _some_g = self.some_g.clone();
let _some_h = self.some_h.clone();
let _some_i = self.some_i.clone();
let _some_j = self.some_j.clone();
tokio::task::spawn(async move {
  	// do something with all the values
});
}

Working on this codebase was demoralizing. We could think of no better way to architect things - we needed listeners for basically everything that filtered their updates based on the state of the app. You could say “lol get gud,” but the engineers on this team were the sharpest people I’ve ever worked with. Cloudflare is all-in on Rust. They’re willing to throw money at codebases like this. Nuclear fusion won’t be solved with Rust if this is how sharing state works.

Projects go great lengths to avoid the need for clone

Projects today structure their APIs in part to avoid the need for users to call clone. Dioxus’s 0.5.0 release pivoted their framework around implicit runtime arenas; Sycamore did the same in 0.9 and Leptos uses a similar approach. In the compiler, where the use of arenas allows most types to be Copy, we’ve encountered resistance to extracting libraries out for wider reuse due to the need to add clone calls which obscure the logi, and projects like MiniRust and a-mir-formality have built elaborate facades primarily to avoid having to call clone.

At the same time, there is a time and a place for explicit ref-counting

There are applications where explicit ref-counting is important. Methods like Rc::make_ref or Arc::make_ref, for example, have very different cost depending on whether the ref-count is 1 or 2, so knowing when ref-counts are incremented or decremented can be relevant. Naive and widespread use of atomic reference counting can have measurable impact on optimized applications, so avoiding reference-counts when not needed (or preferring non-atomic reference counting) is worthwhile.

The story so far

This work builds on RFC #3680 and the 2025H1 ergonomic ref-counting goal, which delivered a working nightly implementation of .use syntax and generated extensive community feedback that revealed an important design question.

RFC #3680 and experimental implementation

RFC #3680, titled “Simplify lightweight clones, including into closures and async blocks,” proposed a feature to simplify performing lightweight clones (such as of Arc/Rc), particularly cloning them into closures or async blocks, while still keeping such cloning visible and explicit.

The RFC identified common friction patterns where developers need to clone Arc<T> reference-counted objects into async blocks or tasks, showing examples of the verbose workarounds currently required. The proposal aimed to “minimize the syntactic weight of lightweight-cloning objects, particularly cloning objects into a closure or async block, while still keeping an indication of this operation.”

The core approach was to introduce a Use trait that types like Arc<T> and Rc<T> could implement to opt into lightweight cloning behavior, along with new syntax (x.use and use || { ... }) to make this cloning more ergonomic while keeping it explicit.

Experimental implementation available on Nightly

Nightly Rust now has an experimental implementation of RFC #3680 (modulo the caveats in the FAQ):

#![allow(unused)]
fn main() {
let config = Arc::new(load_config());
let database = Arc::new(connect_db());
let metrics = Arc::new(MetricsCollector::new());

spawn(use async {
    // config, database, metrics are automatically cloned into the block
    process_request(config, database, metrics).await;
});
}

RFC feedback: positive on the idea, but concerns on the details

RFC #3680 generated extensive discussion with over 80 comments of feedback (summarized here) that showed both support for addressing the ergonomics problem and concerns about the specific solution. Contributors from projects like PyO3 highlighted the real-world impact of the current friction, particularly in domains that make heavy use of reference counting.

The discussion covered several themes: concerns about defining what constitutes “cheap” cloning, questions about compiler optimizations that could lead to behavioral differences, debates about keyword overloading with use, and various alternative syntax proposals. However, one critique stood out as particularly compelling and worth deeper exploration. Outside of the RFC thread, concerns were raised about compilation time impact, since, at least if naively implemented, this new approach involves more use of the trait system than is currently the case.

Key design question: will this make Rust easier?

Among the various concerns raised, the most hard-hitting critique questioned whether explicit .use syntax actually serves the stated ergonomic goals. Diggsey’s comment articulated this view:

Having to navigate a codebase filled with this strange .use keyword, which is hard to explain (it copies the value.. except when it doesn’t, and it can be used on Use types, but not Clone types, but Use is not Copy, it’s different… When is something Use? What makes something lightweight? Uh… read this essay. Why do I need to make this closure use but this one doesn’t need to be? Ahahaha, yeah this is going to take a while to explain…) is more of a blocker than clone-into-closure ever was.

This critique suggests that if the goal is ergonomics, requiring more explicit syntax may be counterproductive. We propose to explore an alternative approach that makes lightweight cloning automatic by default, with optional warnings for non-trivial cases. This would allow the lang team to evaluate both the maximally explicit approach (current RFC) and the seamlessly integrated approach before deciding on Rust’s direction for ergonomic improvements.

The next 6 months

To explore the automatic alternative, we will:

  • Author an alternative RFC that avoids new keywords and includes a lint of help catch potentially incorrect usage.
  • Implement the new design (feature-gated, natch) to support experimentation and measure compilation overhead.
  • Estimate the prevalence of code that benefits or is complicated by this change using Crater runs or other experiments.
  • Conduct design reviews with the lang team to compare/contrast the two approaches.

The “shiny future” we are working towards

Ergonomic ref-counting represents a friction point in multiple domains. Async Rust programs frequently have context shared across multiple tasks (e.g., server state) that is managed via reference counting. GUI applications also have callbacks and data patterns that do not correlate well to the stack. In these domains, the existence of .clone() calls (or .use notation) represents syntactic noise that distracts from the essential data flow patterns.

Removing barriers in existing domains: In network services and async applications where Rust already excels, eliminating explicit cloning friction will make complex architectures more maintainable and readable. Developers won’t need to choose between ergonomic APIs and performance, or resort to arena allocation patterns primarily for ergonomic reasons.

Opening new application domains: More significantly, this change opens up domains where Rust would otherwise be an excellent choice but where cloning friction currently tips the cost-benefit analysis against adoption. GUI applications, reactive programming, data processing pipelines, and other high-level domains become viable when the ergonomic barrier is removed.

Enabling natural architectural patterns: Projects like Dioxus won’t need to build custom unsafe abstractions to avoid ref-counting friction. Mathematical formalism projects won’t need preprocessors to eliminate distracting .clone() calls. The Rust compiler and other complex applications can use ref-counting patterns more naturally without relying primarily on arenas for ergonomic relief.

This isn’t about making Rust easier for beginners (though it will) - it’s about removing a pervasive friction point that affects most non-trivial Rust applications and currently blocks adoption in domains where Rust’s performance and safety would otherwise be compelling. The lang team’s decision between explicit and seamless approaches will establish important precedent for how Rust balances ergonomics with explicitness in future language evolution.

Design axioms

The design axioms for this alternative RFC are as follows:

  • Clarity of purpose. Although experienced users have learned to live with it, we believe that the current copy/clone introduces noise that distracts from being able to read the code (and, along the way, blocks new user adoption). Our top goal is to encourage Rust code that is clearer of purpose, no matters its domain.
  • Competitive or improved performance. Using this feature should lead to code which is either as efficient or, in some cases, more efficient that you get today.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Author alternative RFCNiko MatsakisSeamlessly integrated approach
Complete seamless implementationSantiago PastorinoMake x equivalent to x.use with optional linting
Standard reviewsTeam compiler
Design meetingTeam langTwo meetings to evaluate both approaches
RFC decisionTeam langChoose between maximally additive vs seamlessly integrated

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What is the current status of the implementation?

The implementation plan for the feature gate ergonomic_clones (experimental version of RFC #3680) is as follows. The following steps are considered required for the basic feature functionality. A step is checked if it is present in nightly.

  • Introduce a UseCloned type implemented for Rc and Arc and possibly other types
    • The RFC called this trait Use; the names will have to be reconciled. We deviated because x.use can be applies to values of any type, including things that do not implement this trait, so the previous name felt confusing. The intention of UseCloned is “when a value of this type is used, it will (if necessary) be cloned”.
  • Introduce the use keyword as an operator on places, e.g., some_place.use
  • Introduce use || /* body */ closures. These are equivalent to move closures except that, where each captured place place is stored into a move closure with an initializer like f: place, use closures contain fields initialized with f: place.use.
  • In MIR Build, place.use is compiled as a call to clone with a call_source of CallSource::Use:
    • As a compile-time optimization, the MIR build for place.use depends on the traits implemented by the type T of place:
      • If the type T is known to implement Copy (modulo regions), then we compile place.use to a copy like place.
      • If the type T is known to implement UseCloned (modulo regions), then we compile it to a call with call_source as described above.
      • Otherwise, place.use is compiled to a move.
      • This is a compile-time optimization because, if we didn’t do this, it would be optimized later by the monorphization-time optimization, but we would spend more effort in the meantime.
    • If the type of x is NOT known to implement UseCloned, then x will be compiled as a move.
  • Integrate some_place.use into borrow check (fairly trivial)
  • Identity candidates for “last-use” optimization (some_place.use is a last use if some_place is never used again)
  • At code generation time, the semantics of some_place.use depends on the type T of some_place:
    • If T implements Copy, then some_place.use is a copy
    • If T implements UseCloned (and is not a last-use), then some_place.use is compiled as a call to some_place.clone()
    • Otherwise, some_place.use is a move.

The following features are not planned for implementation until the future; they are a “nice to have”:

  • Implement use-elision and inter-procedural optimization
    • If some_place.use never escapes the current stack frame and no mutation is occurring, we can forego the call to clone().

How does this goal relate to stabilization?

This goal is explicitly not about stabilization - it’s about getting to a clear decision point. The chosen approach and its implementation will represent a step toward eventual stabilization, but the focus here is on resolving the fundamental design question that emerged from 2025H1.

Once the lang team chooses a direction, subsequent work can focus on refinement, community testing, and the stabilization process without the uncertainty of fundamental design questions.

What is the relationship to the 2025H1 ergonomic ref-counting goal?

This goal builds on the 2025H1 implementation work and the feedback from the RFC. The current implementation already includes most of the infrastructure needed for both approaches - the remaining technical work is primarily about completing the seamless integration option.

Evolving trait hierarchies

Metadata
Point of contactTaylor Cramer
StatusProposed
FlagshipUnblocking dormant traits
Tracking issuerust-lang/rust-project-goals#393
Zulip channel
lang championTaylor Cramer
types championOliver Scherer
Teamscompiler, lang, libs-api, types
Task ownersTaylor Cramer, Taylor Cramer & others

Summary

Unblock the evolution of key trait hierarchies:

  • Adding Receiver as a supertrait of Deref.
  • Allow the tower::Service trait to be split into a non-Sync supertrait and a Sync (thread-safe) subtrait.

The design should incorporate the feedback from the Evolving trait hierarchies language design meeting. The design should also set the stage for future changes to allow for the more general case of splitting items out into supertraits.

Motivation

Two significant motivating cases are discussed in RFC 3437 “Implementable trait alias” under the heading “splitting a trait”.

Conceptual supertrait: Deref: Receiver

The Deref trait currently looks like this:

#![allow(unused)]
fn main() {
pub trait Deref {
    type Target: ?Sized;

    fn deref(&self) -> &Self::Target;
}
}

More recently, the arbitrary_self_types feature has motivated a more general Receiver trait:

#![allow(unused)]
fn main() {
pub trait Receiver {
    type Target: ?Sized;
}
}

Ideally, Receiver would be a supertrait of Deref:

#![allow(unused)]
fn main() {
pub trait Receiver {
    type Target: ?Sized;
}

pub trait Deref: Receiver {
    fn deref(&self) -> &Self::Target;
}
}

but this cannot be done today without a breaking change.

More details are in this Pre-RFC: Supertrait associated items in subtrait impl

Conceptual supertrait: Iterator: LendingIterator

Similarly, every type that implements today’s Iterator trait could also (conceptually) be a LendingIterator:

#![allow(unused)]
fn main() {
pub trait LendingIterator {
    type Item<'a> where Self: 'a;
    fn next(&mut self) -> Option<Self::Item<'_>>;
}

pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}
}

Missing or misnamed parent trait items

Note that, unlike Deref and Receiver, the names and signatures of the associated items in LendingIterator do not match those in Iterator. For existing Iterator types to implement LendingIterator, some bridge code between the two implementations must exist.

Conceptual supertrait: relaxed bounds

A common practice in the async world is to use the trait_variant crate to make two versions of a trait, one with Send bounds on the futures, and one without:

#![allow(unused)]
fn main() {
#[trait_variant::make(IntFactory: Send)]
trait LocalIntFactory {
    async fn make(&self) -> i32;
    fn stream(&self) -> impl Iterator<Item = i32>;
    fn call(&self) -> u32;
}

// `trait_variant` will generate a conceptual subtrait:

trait IntFactory: Send {
    fn make(&self) -> impl Future<Output = i32> + Send;
    fn stream(&self) -> impl Iterator<Item = i32> + Send;
    fn call(&self) -> u32;
}
}

In this example, a type that implements IntFactory also satisfies the requirements for LocalIntFactory, but additionally guarantees that the returned types are Send.

The status quo

Today’s solutions include:

Add a supertrait

Pros

  • Matches the conceptual pattern between the traits: one clearly implies the other.
  • The “standard” Rust way of doing things.

Cons

  • Breaking change.
  • Requires implementors to split out the implementation into separate impl blocks for each trait.

Add a blanket impl

Rather than declaring trait A: B, one can create sibling traits with a blanket impl:

#![allow(unused)]
fn main() {
trait Supertrait {
  // supertrait items
}

trait Subtrait {
  // supertrait items + subtrait items
}

impl<T: Subtrait> Supertrait for T {
  // impl supertrait items using subtrait items
}
}

Pros

  • Backwards compatible to introduce Supertrait

Cons

  • Middleware impls are impossible! We’d like to write:
#![allow(unused)]
fn main() {
struct Middeware<T>(T);

impl<T: Supertrait> Supertrait for Middleware<T> { ... }

impl<T: Subtrait> Subtrait for Middleware<T> { ... }
}

but this overlaps with the blanket impl, and is rejected by the Rust compiler! This is a critical issue for async bridge APIs such as tower’s Service trait, which wants to provide wrappers which implement the trait_variant-style Send-able when the underlying type implements the Send version (see these notes from a previous design meeting).

Other nits:

  • The directionality of the impl is less clear.
  • Every shared item has two names: <T as Supertrait>::Item and <T as Subtrait>::Item. Relatedly, the bridge impl must exist even if items are identical.

Provide no bridging

Another alternative is to provide two totally separate traits with no bridging, requiring users to manually implement both versions of the trait:

#![allow(unused)]
fn main() {
trait Supertrait { ... }
trait Subtrait { ... }

struct Impl { ... }

impl Supertrait for T { ... }
impl Subtrait for T { ... }
}

Pros

  • Backwards compatible
  • Middleware can be written to bridge either impl

Cons

  • Requires duplication
  • Requires users to restate bounds
  • Existing code which implements Subtrait cannot be used as Supertrait, so APIs which require Subtrait cannot be relaxed to Supertrait

The next 6 months

In the next six months, we aim to ship a solution which addresses the Service and Receiver use-cases by allowing trait impls to implement supertraits if the impl itself contains a definition of an item from the supertrait.

Traits will have to opt their impls into this behavior, possibly through the use of a keyword. auto is used below as an example keyword:

#![allow(unused)]
fn main() {
// Library code:
trait Subtrait {
    fn supertrait_item();
    fn subtrait_item();
}
// User code:
impl Subtrait for MyType {
    fn supertrait_item() { ... }
    fn subtrait_item() { ... }
}

// -- can become --

// Library code:
trait Supertrait {
    fn supertrait_item();
}
trait Subtrait: auto Supertrait {
    fn subtrait_item();
}
// User code is unchanged from above, no separate `Supertrait`
// impl required
impl Subtrait for MyType {
    fn supertrait_item() { ... }
    fn subtrait_item() { ... }
}
}

The “shiny future” we are working towards

In the future, we’d like it to be backwards-compatible for traits to split out arbitrary, possibly defaulted items into supertraits.

This will be challenging, as it won’t be obvious syntactically whether an impl intends to provide a supertrait impl– some degree of coherence / overlap resolution will be required. However, this feature will provide library authors a great deal of flexibility while allowing for more ergonomic end-user implementations.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Discussion and moral supportTeam compiler
Discussion and moral supportTeam types
Author RFCTaylor Cramer
ImplementationTaylor Cramer & others
Stabilization decisionTeam libs-apiStabilizing Receiver. Unblocked by implementation.
Stabilization decisionTeam langStabilizing arbitrary_self_types. Unblocked by new Receiver API.

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Design a language feature to solve Field Projections

Metadata
Point of contactBenno Lossin
StatusProposed
FlagshipBeyond the &
Tracking issuerust-lang/rust-project-goals#390
Zulip channelN/A
lang championTyler Mandry
Teamslang
Task ownersBenno Lossin

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.

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.

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 pointers very often where we could use NonNull<T> instead if they had better field access.

Current proposals

In addition to Field Projections RFC v2 already mentioned above, there is a newer proposal that improves upon it.

For historical context, there also is the Field Projections RFC v1.

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

TaskOwner(s) or team(s)Notes
Design meetingTeam langPossibly more than one required as well as discussions on zulip.
Lang-team experimentTeam langDing Xiang Fei, Benno Lossin
Author RFCBenno Lossin

Frequently asked questions

Why not push for RFC decision?

The design is still too early to expect a final decision on the RFC.

Finish the std::offload module

Metadata
Point of contactManuel Drehwald
StatusProposed
Tracking issuerust-lang/rust-project-goals#109
Other tracking issuesrust-lang/rust#124509
Zulip channel#wg-autodiff
compiler championManuel Drehwald
lang championTC
Teamscompiler, lang
Task ownersManuel Drehwald, LLVM offload/GPU contributors

Summary

This project aims to get the std::offload module finished. We currently have the ability to automatically move data to and from a GPU, but we can not launch kernels yet. We will add this ability during the next project goal period.

Motivation

Scientific computing, high performance computing (HPC), and machine learning (ML) all share the interesting challenge in that they each, to different degrees, care about highly efficient library and algorithm implementations, but that these libraries and algorithms are not always used by people with deep experience in computer science. Rust is in a unique position because ownership, lifetimes, and the strong type system can prevent many bugs. At the same time strong alias information allows compelling performance optimizations in these fields, with performance gains well beyond that otherwise seen when comparing C++ with Rust. This is due to how automatic differentiation and GPU offloading strongly benefit from aliasing information.

Status quo

The std::autodiff module is fully upstreamed, but not shipped on nightly yet to open CI questions. “Batched” autodiff, which supports array-of-struct or struct-of-array style code generation is also mostly upstreamed, but not yet publicly advertised due to some open design questions and requested changes. The standalone std::batching feature is mostly implemented in a PR, but not yet upstreamed due to requested changes, to better interact with Rust’s SIMD types. I hope to train a contributor to implement the requested changes to increase the bus factor. The std::offload feature is partly upstreamed. The “host” side, which handles the CPU code is ready. For the “device” side, a first PR exists, but is not yet reviewed or sufficiently tested. We also expect further follow-up PRs to expose more GPU features.

Oliver Scherer has done a great job reviewing my offload host PR to make sure that code quality matches rustc standards, but expressed that he isn’t comfortable reviewing it on a technical side for correct LLVM/offload usage. For that I collaborated with @jdoerfert and @kevinsala from the LLVM side. Further, individuals at both AMD and NVIDIA gave feedback on my design and will continue to do so. In general, the design is somewhat different from what we have in other languages, so we will likely run into some challenges and keep iterating.

The next 6 months

I will spend most of my time on the offload “Backend”, especially the device side, to improve how we lower Rust code to GPUs. To verify the progress, I will add increasingly more complex gpu compute kernels to the rust test suite. Similar to the autodiff work, I will spend a significant fraction of my time with onboarding new contributors, to increase the bus factor. So far I already have one offer from a potential contributor, which is interested in developing the offload frontend. Due to the popularity of GPU programming, I expect even more support than for the autodiff work and hope to have a solid contributor base by the end of the project goal.

One of the lessons learned from the std::autodiff work is the challenge of enabling a new feature in CI. While autodiff has been usable for more 6 months, we still do not ship it on nightly. The two main challenges were A) challenges of reproducing CI issues locally B) enabling autodiff in CI increases the binary size.

Due to the lack of GPUs in CI we will not run GPU binaries in CI, which should avoid issue A) To prevent issue B) I already opened a PR to enable std::offload in CI. This allows us to test the binary size increase early, and gives the infra team more time to provide feedback.

I expect that we will find a solution with the infra team at some point within the next 6 months to enable std::autodiff in CI. Once that happens, I will likely take a one month break from std::offload to clean up autodiff docs and finish the upstreaming of std::batching, which is based on the same LLVM plugin as autodiff (Enzyme).

The “shiny future” we are working towards

In the future, developers will be able to write a single Rust function and use std::batching to get a SIMD/fused version of it, use std::autodiff to differentiate it, and std::offload to run the resulting code on their GPUs. Authors of Machine Learning or Linear Algebra libraries will further be able to optimize their libraries performance by opting into a new MLIR based compiler backend, which automatically rewrites their compute heavy operations for better performance.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Lang-team experimentTeam langComplete
Standard reviewsTeam compilerReview contributions to rustc_codegen_llvm and other parts of the backend
LLVM reviewsLLVM offload/GPU contributorsIndividual contributors at AMD/NVIDIA/LLNL agreed to review my code from the LLVM or GPU side
Do the workManuel Drehwald

Frequently asked questions

Run more tests for GCC backend in the Rust’s CI

Metadata
Point of contactGuillaume Gomez
StatusProposed
Other tracking issuesrust-lang/compiler-team#891
Zulip channel#rustc-codegen-gcc
compiler championWesley Wiser
infra championMarco Ieni
Tracking issuerust-lang/rust-project-goals#402
Teamscompiler, infra
Task ownersGuillaume Gomez

rust-lang/compiler-team#891: https://github.com/rust-lang/compiler-team/issues/891

Summary

Over the next six months, we will do the following:

  • Run GCC backend’s test with GCC backend built sysroot
  • Add new ui tests annotations (//@ ignore-backend and //@ needs-backend)
  • Run tests with GCC backend:
  • Add documentation in dev guide about how to run tests with the GCC backend

To be noted: this goal is only for linux x86_64 target.

Motivation

Currently, most of the time spent on work on the GCC backend is to keep up to date with Rust’s changes: we need to figure out which changes broke things on our side. And with a higher number of changes, this makes this process a lot longer. Running more GCC backend tests directly in Rust CI would allow to detect regressions directly when a change is made, making it much simpler to figure out what went wrong.

The status quo

We want to make the GCC backend a first-class option for Rust developers. Many things remain to be done for us to reach this point, and reducing the time spent on syncs would allow us to focus on adding the missing parts and improve generated code.

Adding new ui tests annotations

The new ui tests annotations (//@ ignore-backend and //@ needs-backend) will allow to run directly the ui tests without all the current filtering processes we put in place in the rustc_codegen_gcc repository. They are needed because a lot of tests are simply not possible to pass since they’re tied to LLVM (like generated assembly code). It will also make it easier for Rust’s developers to check if their changes work with GCC.

As a reminder, this goal will only target linux x86_64.

Running more tests

Currently, only a few tests are run, and if they fail, they are not blocking a PR from being merged. The goal is to make them mandatory to succeed and also to run more tests:

Adding documentation

It is important for rust developers to be able to test how changes impact the GCC backend. To do so, documentation is a must have and will be added as part of this goal.

Ownership and team asks

This section lists out the work to be done and the asks from Rust teams. Every row in the table should either correspond to something done by a contributor or something asked of a team.

For most goals, a single table will suffice, but you can also add subsections with ###. We give several example subsections below that also demonstrate the most common kinds of goals. Remember that the items in the table only corresponds to what you plan to do over the next 6 months.

For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. The owner is ideally identified as a github username like @ghost.

For items asked of teams, list Team and the name of the team, e.g. ![Team][] [compiler] or ![Team][] [compiler], [lang] (note the trailing [] in ![Team][], that is needed for markdown to parse correctly). For team asks, the “task” must be one of the tasks defined in rust-project-goals.toml or cargo rpg check will error.

TaskOwner(s) or team(s)Notes
Adding new ui annotationsGuillaume Gomez
Running more GCC backend testsGuillaume Gomez
Standard reviewsTeam infra, compilerwith the help of t-infra and t-compiler for reviews and ensuring is done as they want

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

In-place initialization

Metadata
Point of contactAlice Ryhl
StatusProposed
FlagshipUnblocking dormant traits
Tracking issuerust-lang/rust-project-goals#395
Zulip channel#t-lang
lang championTaylor Cramer
Teamslang
Task ownersBenno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

Summary

Evaluate approaches for in-place initialization and pick one.

Motivation

This project goal aims to find an ergonomic mechanism for in-place initialization so that we can add it to the language.

The status quo

There are multiple projects that are running into various problems that can only be solved using a mechanism for in-place initialization. Each project has implemented their own independent and slightly different solution in external crates relying on complex macros at the cost of ergonomics.

It’s time to learn from the extensive amount of experimentation in the ecosystem and create a language feature that provides a shared solution that can be more ergonomic than what is possible in an external crate.

Current proposals and implementations

The next 6 months

Today, there are multiple different competing proposals for how in-place initialization should work. For the next 6 months, the primary aim of this goal is to figure out which proposal (or combination of proposals!) is best and pick one.

There may also be some amount of experimentation with the proposals as part of the lang experiment. This may also involve experiments to refactor e.g. the Linux Kernel or Crubit to use a proposal to see how well it works in the real world. Actually attempting to land the feature is out of scope for the next six months.

The “shiny future” we are working towards

In the shiny future, Rust will be a language that supports in-place initialization in a way that is efficient, ergonomic, easy-to-use. The language may utilize in-place initialization to provide the following five features:

Avoid stack overflow when creating values on the heap

When creating a boxed value, in-place initialization allows you to construct the value in-place directly in the location on the heap. This avoids stack overflow crashes when the value is large.

C++ interop

Most values in C++ are not trivially relocatable. This means that you must run user-defined code (the move constructor) to move them from one address to another. Pinned in-place initialization provides a natural way to translate C++ constructors into Rust.

Constructors returning pinned values

When interacting with C code such as the Linux kernel, constructors for C types often take an out pointer to initialize the value in. It’s usually not safe to memcpy the resulting C value to a different location, which means that the value must be pinned immediately on creation. By using pinned in-place initialization, it is natural to work with this kind of value in Rust.

For this to be ergonomic, it’s important that you can embed these values as fields in your own Rust structs, and that initialization can be fallible.

Async fn in dyn Trait

Trait objects can have async functions. When an async function is called, the future is initialized in-place into a user-provided location. The same feature also extends to other -> impl Trait return types in trait objects.

The same feature could potentially extend to any function returning an unsized type.

Custom self-referential types

In the constructor for your custom struct, you know the final address of each field, so you can safely create a situation where one field borrows from another field. Since the struct being initialized is immediately pinned, there is no risk that the caller will memcpy the value to a different location and invalidate internal references.

Design axioms

We must remember to take advantage of the language. It has already been proven multiple times that in-place initialization can be implemented in an external crate with macros. Are there any possible ergonomics wins that are possible only by adding a real language feature?

Ownership and team asks

Since the primary objective of this project goal is to choose a solution, this project goals asks the lang-team for two design meetings. There is already a meeting scheduled on July 30th, which is at the beginning of the goal period. This project goal asks the lang team for a second meeting near the end of the goal period, in addition to the one that has already been scheduled.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Design meetingTeam langTwo design meetings
Be the main author of an RFCAlice Ryhl
Contribute to the RFCTaylor Cramer, Yoshua Wuyts, Benno Lossin, Gary Guo
Lang-team liaisonJosh Triplett
Dedicated reviewerMichael GouletOf lang experiments

C++/Rust Interop Problem Space Mapping

Metadata
Point of contactJoel Marcey
StatusProposed
Tracking issuerust-lang/rust-project-goals#388
Zulip channelt-lang/interop
compiler championOliver Scherer
lang championTyler Mandry
libs championDavid Tolnay
Teamscompiler, lang, libs, opsem
Task ownersJoel Marcey

Summary

Document a set of technical issues related to C++/Rust interoperability with broad community consensus to serve as a starting point for proposed solutions and facilitating cooperation among stakeholders in both language communities.

Motivation

C++ has been a leading systems language for most of its 40 year history. There are billions of lines of code representing trillions of dollars of value stored in C++ codebases. In domains where systems languages are required, there are very few options and even fewer with the safety properties of Rust. In the near term, it is neither feasible, nor advisable to rewrite a significant fraction of the C++ actively used today. Empirical studies have shown significantly more benefit in writing new code in memory-safe languages. This makes enabling Rust development within C++ codebases essential, and doing so requires high-performance, safe, ergonomic interop.

There are many challenges to this kind of interop, and they can be solved in many different ways. To the extent that discrete problems within the interop space can be solved in a shared way, both communities stand to benefit, but thus far there has been relatively little progress in implementing solutions other than external libraries, each of which typically have their own approach, requiring significant investment for end users. To build better solutions to foundational interop problems that may require changes to the standard libraries, toolchains or the languages themselves, we will first clearly and rigorously define the individual problems and solution requirements with input from experts from both languages including implementors of compilers and standard libraries. Achieving consensus in defining the problems will facilitate the creation and discussion of proposed solutions with the appropriate stakeholders and improve the chances that solutions succeed in broadly benefiting interop consumers.

The status quo

C++/Rust interoperation is an incredibly broad problem space owing to the fact that the C++ language has been continuously developed for 40 years and has actively maintained implementations on numerous architectures and several different toolchains. Furthermore, the requirements of interop consumers varies according to the application as well as constraints on compilers and C++ language versions. Neither Rust nor C++ has language- or standard library-level support for direct interoperation. Instead, the C system ABI is used as the lingua franca for directly calling into the opposite language. While there are ways to achieve cross-language interoperation an a language-agnostic fashion, such as interprocess communication, this proposal is concerned with high-performance, FFI-based interoperation. This is required in performance-critical domains where Rust and C++ are among the few viable language choices and the problems for this kind of interoperation may benefit from coordinated changes in both languages. For more on the domain of interest, see the C++/Rust Interoperability Problem Statement.

Currently there are a variety of approaches to this kind of interop from tools like bindgen and cbindgen which automate only the creation of type and function declarations for FFI calls, to higher-level approaches like cxx, crubit and zngur, which provide varying levels of automation to handle both binding generation and sharing of data across the FFI boundary. All differ in the specifics and though there are many elements to their approaches which are similar, they do not share any common foundation and each builds a solution supported only by the very limited facilities of Rust and C++ to declare functions and data which are compatible with the C system ABI.

Different use cases and priorities account for part of the reason there are a variety of tools. For interop that is limited to well-defined module boundaries and can exploit existing C API which are not too large, the bindgens often suffice, but sacrifice safety and ergonomics. Tools like cxx and zngur provide higher levels of abstraction and safety, but require the user to define an IDL-like interface boundary. Finally, crubit strives to be a universal tool and automatically expose all interfaces to the opposite language which entails considerably more complexity and deep integration with the build system, so it is not yet viable for general purpose use.

In the first year of the C++/Rust Interoperability Initiative, I’ve engaged with many of the parties interested in interop and facilitated direct interactions with members of the Rust Project, WG21 (the C++ ISO standardization committee) and several large tech organizations. I believe for the foreseeable future, there will be multiple approaches to interop, but owing to the very primitive language-level support all these tools are built upon, there is a significant space of shared problems which can benefit from collaboration and shared solutions. Especially when it comes to changes at the language-level, there is a heightened standard for broad utility, and coordinating work across languages with very different evolution processes will require a clear understanding of the specific problems and expert insight regarding the feasibility and impact of changes to the standard libraries, toolchains and core languages. As a member of the Rust Foundation, and a representative to WG21, I’m well-positioned to coordinate these efforts. Having seen first-hand the difficulty in agreeing on solutions and the overwhelmingly large subject area required to understand them, I think the next step is to focus on clearly defining and documenting the problems themselves. This will help identify the areas of potential cooperation, facilitate input from interested parties who may otherwise lack the full context, and sets the stage for solutions to be proposed and refined into concrete, cooperative work that may occur in a multitude of venues, including the Rust Project, WG21, LLVM or elsewhere.

The next 6 months

There has already been a significant discourse on the problems related to interop, but it remains diffused across the web, Zulip and other less-accessible media. Furthermore, the vast majority of this material is in the form of advocating for one tool or approach and typically comes from the perspective of a particular user or organization with specific needs and interests. During this goal period, I will organize as much of it as I can into discrete problem statements which will describe the challenges, prior attempts and current approaches and desired solution properties, but without proposing specific solutions. These will be collected under the interop initiative repo, and I will both accept and solicit input from relevant experts. The goal is achieving consensus around what the problems themselves are as objectively as possible, so parties interested in proposing, reviewing or implementing solutions can organize around the issues of relevant interest and expertise and optimize for shared solutions.

The “shiny future” we are working towards

A well-defined map of the discrete problems in the interop space will allow for the creation of discrete solution proposals, which can be refined and debated by interested members of both the Rust and C++ communities and eventually turned into Rust RFCs, WG21 papers, change processes targeted at other relevant communities such as LLVM, or direct code contributions. There are already many such items of work in process such as arbitrary self types, pin ergonomics or trivial relocatability, and in the shiny future, the problem space map would elucidate the connection between such work and the problems it addresses. This would serve as the central point of collaboration between the two communities to understand the interop-related challenges and work together efficiently. Interested parties can find the problems that are relevant to them (or help define them if they are missing) and then…

  • find the shared problems and work with other interested parties towards a shared solution
  • accept with clear reasoning when different solutions are required for a shared problem
  • not waste time engaging about problems that aren’t relevant to them

Given the large investment and long time frames involved in language-level changes, it’s particular valuable to have a solid grounding in the problem itself. This space could also grow into a shared community to help determine and facilitate the process of implementing solutions, whether they be creating RFCs, WG21 proposals or something else.

Design axioms

Problem statements should…

  • define the impact, consequences and acceptance criteria for solutions
  • reference prior solution work, but without proposing or analyzing solutions
  • be based objective facts supported by expert opinions and generally strive to be informative and uncontroversial
  • provide a high-level explanation for engineers who aren’t experts in the cause, but are likely to experience the impact
  • provide references to additional background information

Ownership and team asks

Fundamentally, this goal is about organizing knowledge in a useful way. I will be primarily responsible for collecting and structuring it, but do not intend to do original analysis since there are greater experts to defer to. The most valuable participation from Rust teams will be in reviewing the accuracy of the collected information. I do not expect the burden to be great since the individual problems are intended to be narrowly scoped and reviewers will be experts in the domain. Demands will depend on the specific problems documented and the teams that are deemed relevant

TaskOwner(s) or team(s)Notes
Author problem statementsJoel MarceyExternal contributions welcome and anticipated
Standard reviewsTeam lang, compiler, libs, opsemProblem statement review

Frequently asked questions

Is this intended to be a living document or a snapshot in time?

A living document. It’s unlikely to ever be complete, especially considering both Rust and C++ continue to change, but since one of the main points of the document is to attract more input and inspire new solution proposals, openness to change is a feature.

Do you want to be the curator of all content or go for more of a wiki approach?

At least initially (and almost certainly for the lifetime of this goal), I plan to be the sole curator, but I will actively encourage and solicit contributions to ensure the content is as accurate and objective as possible. Over time, additional curators may be added, and at some point it may make sense to transition to a more wiki-like approach if curation becomes a bottleneck, but I can’t say for sure.

How should the problems be prioritized?

At the very beginning, the goal will be breadth: attempt to give a name and basic description to as many of the relevant problems as possible. This will form a sort of skeleton to aid with discoverability and motivate contribution from relevant experts. From there, priority will be given to collecting information that already exists spread across various sources such as meeting notes, conference talks, forum posts and Zulip streams. Problems which are causing people current pain and which have competing solution ideas will be especially prioritized to encourage them to be formalized in response to a common understanding of the problem. Finally, problems which are most likely to have solutions requiring longer-term processes such as RFCs and WG21 papers will be prioritized to get things moving sooner and problems with uncontroversial solutions will be prioritized because we all could use some easy wins.

If you had unlimited time and resources, wouldn’t it be advisable to rewrite all the C++ in Rust?

I don’t think it’s clear that it is! While the risk of UB goes away if you can rewrite it all in safe Rust, there are lots of other kinds of bugs that can occur, and they’re far more likely to occur in new code, so the older and more real-world use code has, the less likely it is to contain bugs, regardless of language.

I notice you wrote “implementors” above. Why not “implementers”?

This bothered me too, and this internals thread explained why it was so noticeable to me (and likely other Rustaceans).

Finish the libtest json output experiment

Metadata
Point of contactEd Page
StatusProposed
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#255
cargo championEd Page
Teamscargo, libs-api, testing-devex
Task ownersEd Page

Summary

Finish the libtest json experiment.

Motivation

libtest is the test harness used by default for tests in cargo projects. It provides the CLI that cargo calls into and enumerates and runs the tests discovered in that binary. It ships with rustup and has the same compatibility guarantees as the standard library.

Before 1.70, anyone could pass --format json despite it being unstable. When this was fixed to require nightly, this helped show how much people have come to rely on programmatic output.

Cargo could also benefit from programmatic test output to improve user interactions, including

Most of that involves shifting responsibilities from the test harness to the test runner which has the side effects of:

  • Allowing more powerful experiments with custom test runners (e.g. cargo nextest) as they’ll have more information to operate on
  • Lowering the barrier for custom test harnesses (like libtest-mimic) as UI responsibilities are shifted to the test runner (cargo test)

The status quo

The next 6 months

  1. Experiment with potential test harness features
  2. Experiment with test reporting moving to Cargo
  3. Putting forward a proposal for approval

The “shiny future” we are working towards

  • Reporting shifts from test harnesses to Cargo
  • We run test harnesses in parallel

Design axioms

  • Low complexity for third-party test harnesses so its feasible to implement them
  • Low compile-time overhead for third-party test harnesses so users are willing to take the compile-time hit to use them
  • Format can meet expected future needs
    • Expected is determined by looking at what other test harnesses can do (e.g. fixture, paramertized tests)
  • Format can evolve with unexpected needs
  • Cargo perform all reporting for tests and benches

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam testing-devex, cargo, libs-api
Prototype harnessEd Page
Prototype Cargo reporting supportEd Page
Write stabilization reportEd Page

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

MIR move elimination

Metadata
Point of contactAmanieu d’Antras
StatusProposed
Tracking issuerust-lang/rust-project-goals#396
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
lang championAmanieu d’Antras
Teamscompiler, lang, opsem, wg-mir-opt
Task ownersAmanieu d’Antras

Summary

Add a MIR optimization which eliminates move operations. This will require changes to the MIR semantics of move to enable the optimization to cases where a value has had its address taken (LLVM already eliminates moves when this is not the case).

Motivation

One big difference between C++ and Rust is the concept of object identity: objects in C++ are always constructed at their final address through constructors while Rust objects are typically constructed by a method and then moved into their final address. While these two approaches achieve the same result in the end, in practice Rust is unable to eliminate many of these moves which leads to a lot of unnecessary memcpy calls (or in-line stack-to-stack copies).

The status quo

The following examples showcase the fundamental problem:

#![allow(unused)]
fn main() {
struct Foo([u8; 100]);

fn observe(addr: *const Foo) {
    println!("observed address {addr:?}");
}

fn example1() {
    let a = Foo([0; 100]);
    observe(&a);
    let b = a;
    observe(&b);
}

fn example2() {
    let a = (Foo([0; 100]), Foo([0; 100]));
    observe(&a.0);
    let b = a.0;
    observe(&b);
}
}

In example1, our current MIR semantics forbid a and b from being at the same address: this is because the storage lifetime of a extends to the end of its scope and therefore overlaps with that of b. This means that, according to the current tree borrows model, observe is still allowed to access the underlying allocation even after the value is moved.

example2 shows the same issue, but with partially-moved values. This is more complex since even though the first half of a has been moved, the second half must remain accessible at its current address while b is live.

The next 6 months

There have been some [initial discussions] about MIR semantics that would allow such moves to be optimized away, but this needs to be further developed into a fully-fleshed proposal. The basic idea is that, when moving a place, the portion of the allocation covered by that place is freed, which allows another allocation to take its place. This then allows for a MIR optimization that unifies 2 move-connected locals whose live range doesn’t overlap into a single local. See the Zulip thread for a further expansion of this to support partial moves as well.

The primary goal for the next 6 months is to nail down the new semantics for MIR that will enable move elimination and write and RFC proposing these new semantics. This will primarily involve the language team (specifically the opsem team), but also the compiler team to evaluate the impact of the changes to MIR on the existing MIR optimization framework.

Once the new semantics are accepted then these would need to be implemented in Miri for checking. Finally, the new MIR optimization pass can be implemented in the compiler.

The “shiny future” we are working towards

The end goal of this proposal is to be able to soundly perform move elimination as a MIR optimization. This will have the following effects:

  • Better optimized code due to the eliminated copies.
  • Shorter allocation lifetimes will mean that less state needs to be preserved at async yield points, which reduces the size of futures.
  • This RFC will address some long-standing unresolved issues around the MIR semantics of move (1 2 3 4).
  • It is possible that this even improves compilation speeds if it results in fewer copies being lowered to LLVM IR. Though this may not be guaranteed due to the additional time spent in the move elimination pass.

Design axioms

  • Teachable: the new semantics must be clear enough to be teachable to advanced users.
  • Checkable: the new semantics should remain deterministically checkable by Miri.
  • Efficient: the new MIR optimizations should not overly affect compilation time, or if they do, it should be at least justified with a significant increase in the performance of generated code.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang, compiler
Author RFCAmanieu d’Antras
Design meetingTeam opsem, wg-mir-opt
RFC decisionTeam lang, compiler
ImplementationAmanieu d’Antras

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Next-generation trait solver

Metadata
Point of contactlcnr
StatusProposed
FlagshipUnblocking dormant traits
Tracking issuerust-lang/rust-project-goals#113
Zulip channel#t-types/trait-system-refactor
types championlcnr
Teamstypes
Task ownersBoxy, Michael Goulet, lcnr

Summary

Continue work towards the stabilization of -Znext-solver=globally, collecting and resolving remaining blockers. Extend its use in lints and rustdoc.

Motivation

The next-generation trait solver is intended to fully replace the existing type system components responsible for proving trait bounds, normalizing associated types, and much more. This should fix many long-standing (soundness) bugs, enable future type system improvements, and improve compile-times. It’s tracking issue is #107374(https://github.com/rust-lang/rust/issues/107374).

The status quo

There are multiple type system unsoundnesses blocked on the next-generation trait solver: project board. Desirable features such as coinductive trait semantics and perfect derive, where-bounds on binders, and better handling of higher-ranked bounds and types are also stalled due to shortcomings of the existing implementation.

Fixing these issues in the existing implementation is prohibitively difficult as the required changes are interconnected and require major changes to the underlying structure of the trait solver. The Types Team therefore decided to rewrite the trait solver in-tree, and has been working on it since EOY 2022.

The next six months

  • finish and merge in-flight opaque types changes: #139587(https://github.com/rust-lang/rust/pull/139587) and #140497(https://github.com/rust-lang/rust/pull/140497)
    • decide and document inference guidance for unconstrained opaques in the defining scope
  • continue work on performance
    • fix last known exponential slowdown when reevaluating goals due to changed provisional results
    • get all benchmarks to be neutral or improvements
  • fix remaining minor issues from user reports, crater, and our test suite
  • move additional lints and rustdoc to use the new solver by default
  • document the new solver and work on the stabilization report
  • publicly ask for testing of -Znext-solver=globally

The “shiny future” we are working towards

  • we are able to remove the existing trait solver implementation and significantly cleanup the type system in general, e.g. removing most normalize in the caller by handling unnormalized types in the trait system
  • all remaining type system unsoundnesses are fixed
  • many future type system improvements are unblocked and get implemented
  • the type system is more performant, resulting in better compile times

Design axioms

In order of importance, the next-generation trait solver should be:

  • sound: the new trait solver is sound and its design enables us to fix all known type system unsoundnesses
  • backwards-compatible: the breakage caused by the switch to the new solver should be minimal
  • maintainable: the implementation is maintainable, extensible, and approachable to new contributors
  • performant: the implementation is efficient, improving compile-times

Ownership and team asks

Owner: lcnr

Add’l implementation work: Michael Goulet

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam types
Implementationlcnr, Michael Goulet, Boxy
Standard reviewsTeam types
FCP decision(s)Team typesfor necessary refactorings

Support needed from the project

  • Types team
    • review design decisions
    • provide technical feedback and suggestion

Outputs and milestones

See next few steps :3 while we don’t expect to fully stabilize the new solver this year, we expect to get quite close.

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Implement Open API Namespace Support

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#256
cargo championEd Page
compiler championb-naber
crates-io championCarol Nichols
Teamscargo, compiler, crates-io
Task ownersb-naber, Ed Page

Summary

Navigate the cross-team design work to get RFC 3243 implemented.

Motivation

RFC 3243 proposed opening up namespaces in Rust to extension, managed by the package name with crates-io putting access control on who can publish to a crate’s API namespace. This covers multiple teams and needs a lot of coordination to balance the needs of each team as shown on the rustc tracking issue.

The status quo

  • Cargo support is partially implemented.
  • Compiler design is agreed on and partially implemented.
  • There is a crates-io prototype for a previous iteration of RFC 3243 but that code base has likely diverged a lot since then.

The next 6 months

  • Implement Cargo and compiler support for this to be experimented with and allow crates-io work.
  • Understand what changes are needed for crates.io support, and what it will take to implement these.

The “shiny future” we are working towards

Design axioms

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler, crates-io
Compiler implementationb-naber
Work through lingering cargo issuesEd Page, b-naber

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Promoting Parallel Front End

Metadata
Point of contactSparrow Li
StatusProposed
FlagshipFlexible, fast(er) compilation
Tracking issuerust-lang/rust-project-goals#121
See alsorust-lang/rust#113349
Zulip channel[#t-compiler/wg-parallel-rustc][channel]
Teamscompiler
Task ownersSparrow Li

| compiler champion | @SparrowLi | [channel]: https://rust-lang.zulipchat.com/#narrow/channel/187679-t-compiler.2Fwg-parallel-rustc/

Summary

Continue with stabilization and performance improvements to parallel front-end, continuing from the 2025h1 goal.

Motivation

Verify and resolve the few remaining deadlock and other issues, stabilize the feature, and try to further improve parallel compilation performance through various means.

The status quo

Parallel front end progressed well in the first half of the year. We resolved the deadlock issue caused by the deadlock handler, added the rustc-rayon dependency of the parallel front end to the rustc working tree, and changed the work-stealing scheduling algorithm to avoid deadlocks in parallel execution of rustc queries.

Next we need to resolve and verify the remaining issue list, improve the parallel front end test suite, and include all known issues into the ui tests to ensure stability of the feature.

Then we will start the feature stabilization process to push parallel front end into the stable version.

In addition, there are already contributors working on improving the performance of the parallel front end, such as trying to parallelize the macro expansion process, analysing data contention in query calls, etc. (thank you very much). We will conduct more detailed analysis and implementation of these directions in the second half of the year.

In addition, we need to document and enhance the support of surrounding tools for the parallel frontend, such as bootstrap, rustc-perf, and Cargo.

The next 6 months

  • Resolve the remaining issues in the issue list. Most of them have been solved, but are missing tests ensuring that the code won’t regress again.
  • Land the parallel front end test suite to ensure the robustness and prevent various issues from occurring again.
  • Enable parallel front end in bootstrap.
  • Continue to improve parallel compilation performance, by parallelizing macro expansion and reducing data contention.
  • Enable parallel front end in Cargo.
  • Add more benchmarks for the parallel front end to rustc-perf
  • Write stabilization report for the feature and submit it for compiler FCP

The “shiny future” we are working towards

We will ensure robustness of the parallel front end and push it to stabilization.

The current parallelization front end can already reduce the overall compilation time by 20~30+ percent, but we will continue to optimize it so that this number continues to grow.

Design axioms

The parallel front end should be:

  • safe: Ensure the safe and correct execution of the compilation process
  • consistent: The compilation result should be consistent with that in single thread by default
  • maintainable: The implementation should be easy to maintain and extend, and not cause confusion to developers who are not familiar with it.

Ownership and team asks

Owner: Sparrow Li and Parallel Rustc WG own this goal

TaskOwner(s) or team(s)Notes
ImplementationSparrow Li
Author testsSparrow Li
Discussion and moral supportTeam compiler

Frequently asked questions

Continue Experimentation with Pin Ergonomics

Metadata
Point of contactFrank King
StatusProposed
FlagshipBeyond the &
Tracking issuerust-lang/rust-project-goals#389
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
compiler championOliver Scherer
lang championTC
Teamscompiler, lang
Task ownersFrank King

Summary

Continue experimenting with and fleshing out the design and semantics for the pin ergonomics experiment.

Motivation

Several flagship Rust features, such as async and generators, depend on the ability to ensure data will not move in memory. The way Rust achieves this is through the Pin wrapper, but pinning has notoriously poor ergonomics. Exploring how the ergonomics can be improved by integrating pinning into the language better could help unblock advancements in other Rust features.

The status quo

Pinning exists but few people like it. We have an experiment for improving the ergonomics around pinning and some initial PRs have landed, but we would like to build more sustained momentum on it.

The next 6 months

  • introduce &pin mut|const place borrowing syntax (parsing #135731 ready to merge, lowering and borrowck not started yet)
  • pattern matching of &pin mut|const T types (#139751 under review)
  • introduce &pin pat pattern syntax
  • support &pin mut|const T -> &|&mut T coercion (requires T: Unpin of &pin mut T -> &mut T)
  • support auto borrowing of &pin mut|const place in method calls with &pin mut|const self receivers

The “shiny future” we are working towards

Design axioms

Ownership and team asks

TaskOwner(s) or team(s)Notes
ImplementationFrank King
Standard reviewsTeam compiler
Design meetingTeam lang
Author call for testing blog postFrank King

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What do I do with this space?

Stabilizable Polonius support on nightly

Metadata
Point of contactRémy Rakic
StatusProposed
FlagshipUnblocking dormant traits
Tracking issuerust-lang/rust-project-goals#118
Zulip channel[#t-types/polonius][channel]
types championJack Huey
Teamstypes
Task ownersAmanda Stjerna, Rémy Rakic, Niko Matsakis
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/186049-t-types.2Fpolonius

Summary

Make a stabilizable version of the polonius next generation borrow checking “alpha” algorithm. This revision of the analysis, while less powerful than we hoped, currently scales better than the previous datalog implementation, and accepts the main problem case we deferred from NLLs: it handles almost all our in-tree tests, passes perf runs (but is still too slow) and crater runs without issues. It’s therefore a worthwhile step to ship to users, but needs more work to be properly usable on nightly.

This goal is a continuation of the 2025h1 goal.

Motivation

Polonius is an improved version of the borrow checker that resolves common limitations of the borrow checker and which is needed to support future patterns such as “lending iterators” (see #92985). Its model also prepares us for further improvements in the future.

In the previous goal periods, we have landed prototypes of the analysis on nightly, and have a functional version that we think is worthwhile to stabilize, even if it’s not the full version handling all issues related to flow-sensitivity during borrow-checking.

The key achievements from our past work are:

  • identifying this actionable subset
  • implementing and evaluating a functional prototype
  • identifying other phases we wish to explore later, to gradually improve the precision of the analysis

#92985: https://github.com/rust-lang/rust/issues/92985

The design for the polonius $\alpha$ analysis (modulo SCCs) can be summarized as:

  • with the CFG $\mathcal{C}$, and the subset graph
  • compute a “unified graph” $\mathcal{U}$ where
    • nodes are “region $r$ at point $p$”
    • add outlives edges from type-checking: subset edges between regions $r_0 \subseteq r_1$, at the point $p$ where the constraint occurs
    • add liveness edges: if there is an edge $p\rightarrow q \in \mathcal{C}$ and the region $r_1$ is live at $q$
      • make an edge $r_1$ at $p$ to $r_1$ at $q$
      • respecting variance (forward, backward, or bidirectional)
  • “liveness” of a variable is from standard compiler analysis
    • with subtleties about “use” liveness and “drop” liveness
  • “liveness” of a region $r$ at point $p$ is:
    • $r$ is in the type of a variable $v$ live at $p$
  • “liveness” of a loan $l$ at point $p$ is:
    • there exists a live region $r$ where the loan $l$ can reach $r$ in the “unified graph” $\mathcal{U}$ from its introduction region/point node.
  • then we do the usual loans-in-scope computation where a
    • GEN is the loan being introduced
    • KILL is the loan stops being live and/or the place is overwritten
  • and using these loans in scope when checking for place invalidations

The alpha version of the analysis uses reachability within the subset+cfg graph to approximate liveness, and uses the same loan-in-scope computation to handle kills as NLLs.

Examples that the alpha analysis accepts

The majority of open issues marked NLL-deferred, and fixed-by-polonius, would be fixed: their MCVEs are now being accepted by the alpha analysis.

The most impactful example is the “NLL problem case 3” and variations of it, that were deferred from the NLL implementation.

#![allow(unused)]
fn main() {
use std::collections::HashMap;
use std::hash::Hash;

fn from_the_nll_rfc<'r, K: Hash + Eq + Copy, V: Default>(
    map: &'r mut HashMap<K, V>,
    key: K,
) -> &'r mut V {
    match map.get_mut(&key) {
        Some(value) => value,
        None => {
            map.insert(key, V::default());
            map.get_mut(&key).unwrap()
        }
    }
}
}

A similar variation is the filtering lending iterator.

#![allow(unused)]
fn main() {
trait LendingIterator {
    type Item<'a>
    where
        Self: 'a;
    fn next(&mut self) -> Option<Self::Item<'_>>;

    fn filter<P>(self, predicate: P) -> Filter<Self, P>
    where
        Self: Sized,
        P: FnMut(&Self::Item<'_>) -> bool,
    {
        Filter { iter: self, predicate }
    }
}

pub struct Filter<I, P> {
    iter: I,
    predicate: P,
}
impl<I: LendingIterator, P> LendingIterator for Filter<I, P>
where
    P: FnMut(&I::Item<'_>) -> bool,
{
    type Item<'a>
        = I::Item<'a>
    where
        Self: 'a;

    // This is now accepted
    fn next(&mut self) -> Option<I::Item<'_>> {
        while let Some(item) = self.iter.next() {
            if (self.predicate)(&item) {
                return Some(item);
            }
        }
        return None;
    }
}
}

(Note that this doesn’t make lending iterators themselves easier to use, due to the unrelated limitations in GATs themselves.)

Examples that the alpha analysis does not accept

Some cases that require full flow-sensitivity are left for future improvements, and show the same imprecision as NLLs today. For example, some patterns of linked-list traversals with a cursor. There are a handful of open issues like these.

#![allow(unused)]
fn main() {
struct X {
    next: Option<Box<X>>,
}
}

This is showing the same imprecision as NLLs discussed above:

#![allow(unused)]
fn main() {
fn conditional() {
    let mut b = Some(Box::new(X { next: None }));
    let mut p = &mut b;
    while let Some(now) = p {
        // ^ ERROR: cannot use `*p` because it was mutably borrowed
        if true {
            p = &mut now.next;
        }
    }
}
}

While this is still accepted:

#![allow(unused)]
fn main() {
fn no_control_flow() {
    let mut b = Some(Box::new(X { next: None }));
    let mut p = &mut b;
    while let Some(now) = p {
        p = &mut now.next;
    }
}

fn conditional_with_indirection() {
    let mut b = Some(Box::new(X { next: None }));
    let mut p = &mut b;
    while let Some(now) = p {
        if true {
            p = &mut p.as_mut().unwrap().next;
        }
    }
}
}

Similarly,

#![allow(unused)]
fn main() {
struct Node<T> {
    value: T,
    next: Option<Box<Self>>,
}

type List<T> = Option<Box<Node<T>>>;

fn remove_last_node_recursive<T>(node_ref: &mut List<T>) {
    let next_ref = &mut node_ref.as_mut().unwrap().next;

    if next_ref.is_some() {
        remove_last_node_recursive(next_ref);
    } else {
        *node_ref = None;
    }
}

fn remove_last_node_iterative<T>(mut node_ref: &mut List<T>) {
    loop {
        let next_ref = &mut node_ref.as_mut().unwrap().next;

        if next_ref.is_some() {
            node_ref = next_ref;
        } else {
            break;
        }
    }

    *node_ref = None;
    // ^ ERROR cannot assign to `*node_ref` because it is borrowed
}
}

Or another pattern requiring full flow-sensitivity like the following

#![allow(unused)]
fn main() {
use std::cell::Cell;

struct Invariant<'l>(Cell<&'l ()>);

fn create_invariant<'l>() -> Invariant<'l> {
    Invariant(Cell::new(&()))
}

// Fails
fn use_it<'a, 'b>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
    let returned_value = create_invariant();
    if choice { Ok(returned_value) } else { Err(returned_value) }
}

// OK
fn use_it2<'a: 'b, 'b: 'a>(choice: bool) -> Result<Invariant<'a>, Invariant<'b>> {
    let returned_value = create_invariant();
    if choice { Ok(returned_value) } else { Err(returned_value) }
}
}

The next six months

  • Complete the remaining features we need to support, like member constraints, and fix the last couple diagnostics differences with NLLs
  • Keep improving testing and validation
    • continue to expand our test coverage
    • validate and triage open issues marked as NLL-deferred and fixed-by-polonius for the alpha-version of the analysis
    • hopefully compare behavior with future formal works, e.g. in a-mir-formality
    • maybe identify interesting benchmarks or stress tests
  • Refactor, or rewrite, the implementation to reduce overhead, for example by:
    • doing reachability analysis over the CFG + subset graph separately, versus building an entirely new graph like we do today
    • making the algorithm incremental, or lazy, so that more complicated walks only do a subset of the entire graph and incrementally build the same data for every place that is invalidated
    • reworking the analysis to use the region graph SCCs, which is also needed to support member constraints
  • Make that overhead visible in fewer cases
    • either by making NLLs itself more lazy, and reducing its own overhead,
    • or computing “possible errors” cheaply,
    • or having a good way to switch from one analysis to the other, e.g. only do the more expensive analysis if there’s an NLL error (like the NLL migrate mode was used to transition away from AST borrowck)

The “shiny future” we are working towards

Stable support for the polonius alpha analysis, before gradually improving expressiveness, by capitalizing on the insights gathered during the previous goal periods.

Design axioms

The older datalog implementation can accept more exotic borrowing patterns, as it (slowly) elaborates all the data needed to handle full flow-sensitivity, but it also doesn’t scale, has no path to stabilization and suffers from other shortcomings. In order to not let “perfect be the enemy of good”, we’ve chosen to reduce the scope to a manageable subset that we can ship sooner rather than later.

NLL problem case 3, and the like, are a common issue encountered by users, and we believe handling these kinds of patterns is worthwhile, without needing to wait for a solution to handle even more cases. Especially as we think these cases are encountered more rarely than the new cases we’ll accept.

Ownership and team asks

Owner: lqd

Other support provided by Amanda Stjerna as part of her PhD.

TaskOwner(s) or team(s)Notes
Design reviewNiko Matsakis
ImplementationRémy Rakic, Amanda Stjerna
Standard reviewsTeam typesJack Huey, Matthew Jasper

Support needed from the project

We expect most support to be needed from the types team, for design, reviews, interactions with the trait solver, and so on. We expect Niko Matsakis, leading the polonius working group and design, to provide guidance and design time, and Jack Huey and Matthew Jasper to help with reviews.

Outputs and milestones

Outputs

Nightly implementation of polonius that passes NLL problem case #3 and accepts lending iterators (#92985).

This implementation should be good enough to be stabilizable, both in features and performance, should pass the full test suite, do crater runs, and test it on CI.

As our model is a superset of NLLs, we expect little to no diagnostics regressions, but improvements would probably still be needed for the new errors.

Milestones

Note: some of these are currently being worked on and close to being done, and could be completed before the 2025h2 period.

MilestoneOwnerNotes
Factoring out higher-ranked concerns from the main pathAmanda Stjerna
↳ [x] rewrite invalid universe constraints with outlives 'static constraints
↳ [ ] completely remove placeholdersin progress, PR #130227(https://github.com/rust-lang/rust/pull/130227)
Location-sensitive prototype on nightlyRémy Rakic
↳ [x] create structures for location-dependent outlives constraints
↳ [x] build new constraint graph from typeck constraints and liveness constraints
↳ [x] update NLLs for required changes to local & region liveness, loan liveness & loan scopes, (possibly unreachable) kills, bidirectional traversal & active loans
↳ [x] limit regressions about diagnostics when using the new constraints on diagnostics tailored to the old constraints
↳ [x] land on nightly
[x] Debugging / dump tool for analysis of location-sensitive analysisRémy Rakic
Expand prototype into alpha versionRémy Rakic
↳ [ ] Handle member constraints, and SCCs
↳ [ ] Reduce overhead of the analysis
↳ [ ] Make the analysis incremental and/or lazy
Tests and validationRémy Rakicin progress
↳ [ ] make the full test suite passin progress, PR #143093
↳ [x] do a crater run for assertions and backwards-compatibility
↳ [ ] expand test suite with tests about the new capabilitiesin progress, PR #143093(https://github.com/rust-lang/rust/pull/143093)
[ ] Alpha version on nightly, tested on CIRémy Rakic

Production-ready cranelift backend

Metadata
Point of contactFolkert de Vries
StatusProposed
FlagshipFlexible, fast(er) compilation
Tracking issuerust-lang/rust-project-goals#397
Zulip channel
compiler championbjorn3
Teamscompiler, wg-compiler-performance
Task ownersbjorn3, Folkert de Vries, Trifecta Tech Foundation

Summary

This project aims to get the rust cranelift codegen backend to a production-ready state. Specifically, with this work completed, we’d be confident to recommend it as the default for local development, e.g. with cargo test or cargo run.

Motivation

Compile-time performance consistently comes up as a limiting factor in the use and enjoyment of rust. Through extensive tracking and the hard work of T-perf and others, performance has gradually improved over the years. However, in practical terms, a 1% improvement here and there is not sufficient to truly improve users’ workflows.

The cranelift codegen backend (rustc_codegen_cranelift) is one of the most concrete ways we have to deliver a serious improvement to compile times in the typical development cycle. In our measurements on larger projects (e.g. Zed, Tauri, hickory-dns), we currently see roughly a 20% reduction of code generation time, translating to around 5% speedup of total compilation time for clean builds.

Currently, this backend still has some serious limitations that real-world code bases run into. This project goal aims to get the rustc_codegen_cranelift to a state where we can confidently recommend it for local development.

Status quo

The cranelift backend is already very capable, and well-integrated into the rust project. It is able to re-use a lot of infrastructure and code, for instance via rustc_codegen_ssa. It can be enabled on a per-project basis in the Cargo.toml:

# This line needs to come before anything else in Cargo.toml
cargo-features = ["codegen-backend"]

[profile.dev]
codegen-backend = "cranelift"

It is however not quite stable and reliable enough for real use. Most large projects run into one or two missing features, meaning that rustc_codegen_cranelift cannot be used. Furthermore, small changes in the project and/or its dependencies could run into limitations of rustc_codegen_cranelift, so while experimentation with the backend is highly encouraged, we cannot currently recommend it for serious local development.

The next 6 months

We plan to work on fixing the following cranelift limitations:

  • supporting unwinding (at least on Linux and macOS)
  • fixing remaining ABI issues
  • a better approach for supporting (SIMD) intrinsics

As a side-effect we will also look at improving code sharing with rustc, for instance by moving more logic into rustc_codegen_ssa. These changes reduce the maintenance burden of the other backends (cranelift, but also rustc_codegen_gcc), and generally improves the code which is still quite over-fit to LLVM

With these items completed, we believe that we can confidently recommend the use of the cranelift backend for local development and CI builds on linux and macOS.

The “shiny future” we are working towards

We believe we can get to a production-ready rustc_codegen_cranelift implementation for Linux and macOS, on x86_64 and aarch64, within the context of this project goal. The problems and solutions are mapped out, and there are many similarities between these targets.

Ultimately, we’d like to provide the same level of quality for Windows, but this is much more challenging. Progress on this front is highly dependent on additional funding, and will take considerably more time.

While this project aims to deliver a production-ready backend, it is by no means feature-complete at that point. One major missing feature is debug info (i.e. debugger support).

More long-term we see the cranelift backend as an extremely promising approach for decreasing compile times, and substantially improving developer experience. However, significant technical work remains to be done to achieve that goal. We believe that the best next step towards this goal is to first get cranelift ready for widespread use, and then collectively work on further improving performance.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Acquire fundingTrifecta Tech FoundationWe will only be able to work on this project if it is funded
Standard reviewsTeam compilerCasual improvements to rustc_codegen_ssa and other parts of the backend
Dedicated reviewerTeam compilerLarger changes to rustc_codegen_ssa. While not strictly required, we think having a dedicated reviewer will speed up our progress.
Deploy to productionTeam wg-compiler-performanceIf possible, track and show rustc_codegen_cranelift performance. See note below for more details.
Do the workbjorn3, Folkert de Vries

Note: the wg-compiler-performance ask is a nice to have, and it is clear to both the goal owners and the working group that:

  • it depends on another goal for the technical ability to exist in the first place, with its own requirements and timeline
  • and when it’s possible to handle rustc_codegen_cranelift in rustc-perf, deployment and availability could also have practical requirements like funding
  • and that wg-compiler-performance can accept the ask conditionally on the above external requirements it doesn’t control

Frequently asked questions

Stabilize public/private dependencies

Metadata
Point of contactEd Page
StatusProposed
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#272
cargo championEd Page
Teamscargo, compiler
Task ownersHelp wanted, Ed Page

Summary

Find a MVP for stabilization and move it forward.

Motivation

This will allow users to tell Rustc and Cargo what dependencies are private

  • Help users catch ways they unexpectedly expose their implementation details
  • Help tooling better identify what all constitutes an API

The status quo

RFC #1977(https://github.com/rust-lang/rfcs/pull/1977) has been superseded by RFC #3516(https://github.com/rust-lang/rfcs/pull/3516) to reduce complexity on the Cargo side to help get this over the line. However, there is still a lot of complexity on the compiler side to get this right ( rust#3516, rust#119428, ), keeping this feature in limbo

The next 6 months

Work with compiler to identify a minimal subset of functionality for what the lint can do and close out the remaining stabilization tasks.

The “shiny future” we are working towards

Design axioms

  • False negatives are likely better than false positives

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler
Work through #3516, #119428Help wanted
Finish any remaining tasksHelp wanted
MentoringEd Page
Stabilization reportHelp wanted

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Expand the Rust Reference to specify more aspects of the Rust language

Summary

The Rust Reference (https://doc.rust-lang.org/nightly/reference/) describes and documents the Rust language. The Reference has coverage of many areas of Rust already, and it has been integrated into language evolution processes, so that new changes to the language get corresponding updates to the Reference. However, there are some remaining gaps in the Reference’s existing coverage of Rust.

This project goal proposes to write new chapters for the Reference to fill these gaps, making its coverage of Rust more comprehensive. This project goal also proposes to provide additional review bandwidth for other changes, to ensure that the new material does not overwhelm existing review capacity.

Motivation

The Rust Reference is one of the core pieces of documentation for Rust. It serves as documentation for users and implementers alike. The Reference should, ideally, describe all aspects of the Rust language comprehensively. It is easier to contribute changes to existing material than large swaths of new material; the latter is a larger commitment. Thus, this project goal will coordinate the efforts of several prospective contributors (who have already been identified and lined up) to write, contribute, and merge new material for the Reference.

Writing new material for the Reference does not suffice to get it merged, however. Each change to the Reference requires review and approval, which sometimes requires calling in additional expertise, and can require more and scarcer resources. This project goal serves to request such review resources, and additionally to coordinate contribution of additional review resources in other areas to share the overall review load, in an effort to alleviate this and not put as much additional load on existing contributors.

The status quo

We consulted multiple experts on the Rust Reference, and based on that and on analysis of the current Rust Reference, some of the key areas of Rust that the Reference doesn’t fully specify (and in some cases no documentation fully specifies) are:

  • The behavior of type inference, including both when the language can infer types and the boundaries and limitations of when it cannot.
  • The trait solver (up to date with the new solver work by lcnr).
  • More details on macros and expansion, in general. Macros-by-example (declarative macro_rules! macros) are mostly covered, but not things like the exact behavior of proc macros and the general process such as cfg pruning.
  • Name resolution: the process by which the Rust compiler resolves a name used in Rust code, including methods of traits, and items imported from various modules in various crates. Name resolution includes various extensions and special cases that have been added over the years, and the reference should document those and their behavior.
  • Completing documentation of const eval.

Out of scope

Other items, which are out of the scope of this project goal:

  • The behavior of the borrow checker. This is extensive work that has been the subject of PhD theses. There have been multiple attempts to document and bound the behavior of the borrow checker, the latest of which is Tree Borrows ( https://www.ralfj.de/blog/2023/06/02/tree-borrows.html ) by Ralf Jung, a successor to the previous Stacked Borrows model. Specifying this will also carefully distinguish between description of the current behavior and bounds on future behavior, as the borrow checker likely will improve further in the future.
  • The operational semantics of the Rust language, which includes the work formerly described as “unsafe code guidelines”. This has been the focus of the opsem team (https://github.com/rust-lang/opsem-team).

Both of these have substantial efforts already working on them. In some cases, this work is as much about determining and negotiating the correct semantics as documenting them. These two areas have been the work of years and are unlikely to get completed or substantively accelerated in the goal period.

The next 6 months

We propose to have a team of established Rust developers working on different new chapters of the Reference, writing and contributing material for those chapters. Along the way, we expect to make various other contributions based on what turns up during the project period while re-reviewing existing material. We hope to substantially close the gap between the Reference and the Rust language.

The developers working on this project goal have expert-level knowledge of multiple areas of Rust, and in several cases, directly worked on the portions of Rust that need documenting.

Josh Triplett and Jack Huey will coordinate these contributions.

We’re expecting to coordinate contributions of new reference material from lcnr, Jack Huey, Amanieu d’Antras, Guillaume Gomez, Jane Lusby, and Ed Page.

Additional people, who may provide review, mentoring, support, and drafting, include Josh Triplett, lcnr, Jack Huey, Amanieu d’Antras, Guillaume Gomez, Mara Bos, Vadim Petrochenkov, Jane Lusby, Luca Carlig, Midia Reshadi, Vitali Borsak, Sparrow Li, and Ed Page.

The “shiny future” we are working towards

We hope to continue providing ongoing support for reference updates in our areas of expertise, as well as making it easier for others to make ongoing contributions by providing a starting point. While we don’t expect the Reference to ever be “done” (much as the Rust language will not be), we hope to substantially close the gap between the Reference and the language.

In the future, we hope that the reference will include full and complete documentation for all parts of the Rust language, including the borrow checker and the operational semantics.

Design axioms

The following design axioms apply:

  • Some documentation may be better suited for the rustc-dev-guide rather than the Rust Reference. If we find ourselves with material better suited for the rustc-dev-guide, we can submit it there, and submit appropriate user-focused subsets of it to the Rust Reference.
  • Large changes all at once can be harder to review. When possible, we should endeavor to share outlines of new material in advance, and make sure we’re broadly aligned, before writing and submitting full prose. And when feasible and appropriate, we should break up changes into easier-to-review chunks (e.g. individual commits).
  • When writing down descriptions of Rust based on the observed current behavior of rustc, we sometimes encounter areas where we’re not entirely sure whether we want to guarantee the observed behavior as the behavior of Rust. There are two cases:
    1. We’re unhappy with the current behavior of some edge cases. Here, we will prefer to document the current user-visible behavior while leaving an appropriate disclaimer in the Reference (following conventions of the Reference) that there are open questions about whether we may wish to change this behavior.
    2. We’re uncertain about whether the behavior represents a stable guarantee or simply a description of one of many behaviors that Rust could validly exhibit. Here, we will describe the current behavior in an explicitly non-normative fashion (following conventions of the Reference), noting specifically that this does not represent a Rust language guarantee and that other behaviors are possible.
  • Sometimes, writing things down may uncover behaviors that are clearly bugs in rustc (e.g., because those behaviors would be unsound, would contradict other settled language in the Reference, or are otherwise just obviously wrong) and where the correct behavior is obvious (e.g. because it’s implied by other text in the Reference, by existing lang RFCs, due to being the only choice, etc.). In these cases, we’ll prefer to normatively document the correct behavior, to file the relevant bug report in rust-lang/rust, and if appropriate (e.g. because we expect the bug to be longstanding) to add a disclaimer in the Reference (in the standard format) describing the incorrect behavior and citing the bug report.
  • Other times, we’ll uncover behaviors where either 1) it’s unclear whether or not the behavior represents a bug in rustc or 2) it probably does represent a bug in rustc but it’s unclear what the correct behavior is. In these cases, we’ll prefer to non-normatively document the current behavior (in the standard way for the Reference), to file an issue in rust-lang/rust asking the lang team (potentially along with one of its subteams, as appropriate) to make a decision about what the correct behavior is, and to cite that issue in the Reference.
  • Tests demonstrating the behavior being documented, whether as rust-lang/rust tests or as tested reference examples, can provide value in making a change easier to review and validate.
  • We should be explicit about any material that is primarily descriptive rather than normative.
  • We should keep an eye out for potential process improvements that may make it easier to maintain the Reference in the future.
    • Jack Huey (Jack Huey) will work with T-types and T-compiler on potential process improvements to loop in the Reference when making relevant changes as part of those teams.

Ownership and team asks

Owner: Josh Triplett, in his capacity as t-lang and t-spec team member, will lead this project goal. Jack Huey will co-lead this goal.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam spec
New reference chapterslcnr, Jack Huey, Amanieu d’Antras, Guillaume Gomez, Jane Lusby
Standard reviewsJosh Triplett, lcnr, Jack Huey, Amanieu d’Antras, Guillaume Gomez, Mara Bos, Vadim Petrochenkov, Jane Lusby
Standard reviewsTeam spec lang-docs

Frequently asked questions

reflection and comptime

Metadata
Point of contactOliver Scherer
StatusProposed
Other Tracking issuerust-lang/rust#142577
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
compiler championOliver Scherer
lang championScott McMurray
libs championJosh Triplett
Tracking issuerust-lang/rust-project-goals#406
Teamscompiler, lang, libs
Task ownersoli-obk

Summary

Design, implement and experimentally land a reflection scheme based on const fn that can only be called at compile time. This proposal is solely for producing const eval values, not for putting types back into the type system. That will be a follow-up once this proposal has a merged MVP.

Motivation & status quo

Creating new general purpose crates (like serialization crates, log/tracing crates, game engine state inspection crates) that should work with almost all other data structures is nontrivial today. You either need to locally implement your new traits for other (common) crates, or the other crates need to depend on you and implement your traits. This often hinders rollout and will never reach every crate. Most crate maintainers do not want to depend on 2+ serialization crates, and 3+ logging crates, so they will instead pick one, causing everyone to either pick the large popular crates or be limited in what they can serializer/log. This is a hindrance to innovation and will (imo) long term cause the ecosystem to stop evolving even when an objectively better solution to a problem is found.

Reflection offers a way out of this dilemma, as you can write your logic for all types. You would be processing the type information at runtime (or even preprocess it at compile-time, e.g. in const blocks) without requiring trait bounds on your functions or trait impls anywhere. This means no one but consumers of your serialization/logging/game-engine will need to know about your crate, and you do not need the entire crates.io ecosystem to add derives for your traits. Your consumers immediately are able to interoperate with tuples of any size, arbitrary structs and enums from arbitrary crates that neither depend on yours nor you on theirs.

If this experiment is successful, crates like bevy will be able to “just work” with arbitrary types instead of requiring authors to #[derive(Component)], #[derive(Bundle)], or #[derive(Resource)] their types just to get the bevy_reflect information built at compile-time. Crates like bevy_reflect and facet will still exist, but only as different libraries with different goals and methods for exposing reflection information.

Furthermore it opens up new possibilities of reflection-like behaviour by

  • specializing serialization on specific formats (e.g. serde won’t support changing serialization depending on the serializer https://github.com/serde-rs/serde/issues/2877),
  • specializing trait impl method bodies to have more performant code paths for specific types, groups of types or shapes (e.g. based on the layout) of types.

I consider reflection orthogonal to derives as they solve similar problems from different directions. Reflection lets you write the logic that processes your types in a way very similar to dynamic languages, by inspecting values’ types during the execution of the reflection code, while derives generate the code that processes types ahead of time. Proc macros derives have historically been shown to be fairly hard to debug and bootstrap from scratch (we should totally also improve proc macro workflows). While reflection can get similarly complex fast, it allows for a more dynamic approach where you can easily debug the state your are in, as you do not have to pair the derive logic with the consumer logic (e.g. a serializer) and are instead directly writing just the consumer logic.

Reflection often is not as efficient as derives, as the derives can generate the ideal code ahead of time, but once a fully functioning reflection system has been written for a use case, and performance becomes a problem, it should be significantly easier to now write a derive for the performance critical cases than to have started doing so from the start.

The next 6 months

  • add an attribute for const fn that prevents them from being called from runtime code or const fn without the attribute
    • See the FAQ for why we need #[rustc_comptime] const fn() {} declarations
  • add basic datastructures to libcore that represent common information about types and the APIs to obtain that information

The “shiny future” we are working towards

Create basic building blocks that allow facet, bevy-reflect and reflect to process types without requiring derives or trait bounds.

Design axioms

  • Prefer procedural const-eval code over associated const based designs (see also “why not uwuflection” in the FAQ).
    • We picked const fn in general evaluation over associated const based designs that are equally expressive but are essentially a DSL
  • Ensure privacy is upheld, modulo things like size_of exposing whether new private fields have been added
    • This is important to ensure that we cannot break abstractions. We will experiment with allowing const items in the same module to access private fields even if the access is in a comptime fn defined in another crate. Or with a comptime fn defined in the same module of a private field accessing that private field even if called in a const item outside of it.
  • Avoid new semver hazards and document any if unavoidable.
    • e.g. do not expose private fields, methods, or types

This section is optional, but including design axioms can help you signal how you intend to balance constraints and tradeoffs (e.g., “prefer ease of use over performance” or vice versa). Teams should review the axioms and make sure they agree. Read more about design axioms.

Ownership and team asks

This section lists out the work to be done and the asks from Rust teams. Every row in the table should either correspond to something done by a contributor or something asked of a team.

For most goals, a single table will suffice, but you can also add subsections with ###. We give several example subsections below that also demonstrate the most common kinds of goals. Remember that the items in the table only corresponds to what you plan to do over the next 6 months.

For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. The owner is ideally identified as a github username like @ghost.

For items asked of teams, list Team and the name of the team, e.g. ![Team][] [compiler] or ![Team][] [compiler], [lang] (note the trailing [] in ![Team][], that is needed for markdown to parse correctly). For team asks, the “task” must be one of the tasks defined in rust-project-goals.toml or cargo rpg check will error.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Do the workoli-obk

Design language feature to solve problem

Some goals propose to design a feature to solve a problem. Typically the outcome from this goal is an draft or accepted RFC. If you would like to work on an experimental implementation in-tree before an RFC is accepted, you can create a lang team experiment, but note that a trusted contributor is required.

TaskOwner(s) or team(s)Notes
Lang-team experimentTeam lang, libsNeeds libstd data structures (lang items) to make the specialization data available

Implement language feature

If there is an accepted RFC, or you are doing a lang-team experiment, you commonly need someone to write the code, support from the compiler to review your PRs, and possibly lang-team design meetings to review interesting design questions. Once implementation completes we recommend a call for testing blog post.

TaskOwner(s) or team(s)Notes
Implementationoli-obk
Standard reviewsTeam compiler
Design meetingTeam lang
Author call for testing blog postLikely will just experiment with bevy or facet, no general call for testing

Frequently asked questions

Why do you need comptime in addition to reflection?

If we had a bevy_reflect::Type type in libcore and a

#![allow(unused)]
fn main() {
const fn type_of(id: TypeId) -> &'static Type;
}

function, that has the special requirement of, unlike every other const fn, not being callable at runtime, then we could work with type descriptions from normal procedural rust code.

So for this experimental impl we would do

#![allow(unused)]
fn main() {
#[compile_time_only]
const fn type_of(id: TypeId) -> &'static Type;
}

These functions can’t be run at runtime, because that would require there to be some global table somewhere that maps all TypeIds to their repr. This is an obvious no-go in my book.

an demonstration impl (absolutely not salvageable for anything that could be landed!) can be found here

Why not continue where uwuflection left off?

See https://soasis.org/posts/a-mirror-for-rust-a-plan-for-generic-compile-time-introspection-in-rust/ for details on what uwuflection is

Structural processing

it makes procedural processing of type information very hard. E.g. to get the 3rd element of a tuple you need to

#![allow(unused)]
fn main() {
<introwospect_type::<YourType> as FieldDescriptor<3>>
}

so to compute that index you need a constant. you can’t just use a for loop to iterate over the indices.

we chose const fn over associated consts and generics which could compute the same thing as the const fn, just more expensively and mostly purely functional. so going to assoc consts again seems like it goes against that

This can somewhat be resolved by adding a compile-time for loop feature to the language, that will just expand the body N times in a macro/loop-unrolling kind of way.

generic const exprs

in order to use uwuflection in types in generic code you need to either write infallible code with min const generics or you need to add uwuflection bounds (Lots, think typenum) , which defeats the purpose.

Why not go full zig-style comptime?

zig’s approach to comptime from a very high level is effectively

  • generate AST for all source files
  • pick the main function and start compiling it and looking for what it needs to be compiled
  • if a comptime function call is found, look only for what code that needs to compile, compile it and produce the resulting code of the comptime function
  • continue the main compilation, which may now invoke the generated code and start compiling that

we do not experiment with this approach at this time, because the compiler is not set up in a way to permit proc macros from accessing type information from the current crate. While there are ongoing refactorings that go into the direction of potentially allowing more of that in the future, that future seems to be more than 5 years away at my best guess.

  • the compiler is not set up to add AST nodes while type information is already available. It possibly never will, and it would be an immense amount of work to get there. I’m doing lots of refactorings that would need to be done for sth like that anyway, even if the goal is just better incremental and general compilar architecture.
  • there are too many open language questions about it that we haven’t even started to discuss
  • a hacky comptime reflection prototype that works for just tuples and that works with regular const eval exists right now, so pursueing the definitely possible implementation will pay off in a shorter term.

Relink don’t Rebuild

Metadata
Point of contactJane Lusby
StatusProposed
Tracking issuerust-lang/rust-project-goals#400
Zulip channel
FlagshipFlexible, fast(er) compilation
cargo championWeihang Lo
compiler championOliver Scherer
Teamscargo, compiler
Task owners@dropbear32, @osiewicz

Summary

Work towards avoiding rebuilds of a crate’s dependents for changes that don’t affect the crate’s public interface.

Motivation

Changing a comment, reordering use statements, adding a dbg! statement to a non-inlinable function, formatting code, or moving item definitions from one impl block to another identical one all cause rebuilds of reverse dependencies of that crate.

This clashes with users’ intuition for what needs to be rebuilt when certain changes are made and makes iterating more painful.

As a point of reference, in C and C++ – where there is a strict separation between interface and implementation in the form of header files – equivalent changes would only cause a rebuild of the translation unit whose source has been modified. For other units, existing compiler outputs would be reused (and re-linked into the final binary).

Our goal is to work towards making cargo and rustc smarter about when they do or don’t need to rebuild dependent crates (reverse dependencies).

The status quo

As an example, consider the rg binary in the ripgrep package.

Its crate dependency graph (narrowed to only include dependents of globset, a particular crate in ripgrep’s Cargo workspace) looks like this:

❯ cargo tree --invert globset
globset v0.4.16
├── grep-cli v0.1.11
│   └── grep v0.3.2
│       └── ripgrep v14.1.1
└── ignore v0.4.23
    └── ripgrep v14.1.1
flowchart TB
  globset
  grep-cli
  grep
  ignore
  ripgrep

  globset --> ignore --> ripgrep

  globset --> grep-cli --> grep --> ripgrep

Consider a change that does not alter the interface of the globset crate (for example, modifying a private item or changing a comment within globset’s source code).

Here is the output of cargo build --timings for an incremental build of ripgrep where only such a change was made to globset:

In the above we see `globset` and all transitive "upstream" dependent crates (up to `ripgrep`) being rebuilt.

Ideally, in this scenario, the transitive dependents of globset (that only depend on globset’s “interface”) would not need to be rebuilt. This would allow us to skip the grep-cli, ignore, grep, and ripgrep re-compiles and only redo linking of the final binary (“relink, don’t rebuild”)1.

For smaller/shallow dep graphs (like the above) the extra rebuilds are tolerable, but for deeper graphs, these rebuilds significantly impact edit-debug cycle times.


Transitive Deps and the Build System View

Ideally the crate-level dependency graph above would (morally) correspond to a build graph like this2:

flowchart TB
  subgraph globset[globset compile]
    globset.rmeta:::rmeta
    globset.rlib:::rlib
  end
  subgraph grep-cli[grep-cli compile]
    grep-cli.rmeta:::rmeta
    grep-cli.rlib:::rlib
  end
  subgraph grep[grep compile]
    grep.rmeta:::rmeta
    grep.rlib:::rlib
  end
  subgraph ignore[ignore compile]
    ignore.rmeta:::rmeta
    ignore.rlib:::rlib
  end
  subgraph ripgrep[ripgrep compile]
    %% ripgrep.rmeta:::rmeta
    ripgrep.rlib:::rlib
  end

  ripgrep_bin["`rg (bin)`"]

  classDef rmeta fill:#ea76cb
  classDef rlib fill:#2e96f5

  %% linker inputs (`rlib`s):
  globset.rlib & grep-cli.rlib & grep.rlib & ignore.rlib & ripgrep.rlib -.-> ripgrep_bin

  %% direct deps (`rmeta`s):
  globset.rmeta --> ignore
  ignore.rmeta --> ripgrep

  globset.rmeta --> grep-cli
  grep-cli.rmeta --> grep
  grep.rmeta --> ripgrep

In particular, note that crate compiles use the rmetas of their direct dependencies.

However, in reality crate compiles need access to all transitive rmetas:

flowchart TB
  subgraph globset[globset compile]
    globset.rmeta:::rmeta
    globset.rlib:::rlib
  end
  subgraph grep-cli[grep-cli compile]
    grep-cli.rmeta:::rmeta
    grep-cli.rlib:::rlib
  end
  subgraph grep[grep compile]
    grep.rmeta:::rmeta
    grep.rlib:::rlib
  end
  subgraph ignore[ignore compile]
    ignore.rmeta:::rmeta
    ignore.rlib:::rlib
  end
  subgraph ripgrep[ripgrep compile]
    %% ripgrep.rmeta:::rmeta
    ripgrep.rlib:::rlib
  end

  ripgrep_bin["`rg (bin)`"]

  classDef rmeta fill:#ea76cb
  classDef rlib fill:#2e96f5

  %% linker inputs (`rlib`s):
  globset.rlib & grep-cli.rlib & grep.rlib & ignore.rlib & ripgrep.rlib -.-> ripgrep_bin

  %% direct deps (`rmeta`s):
  globset.rmeta --> ignore
  ignore.rmeta --> ripgrep

  globset.rmeta --> grep-cli
  grep-cli.rmeta --> grep
  grep.rmeta --> ripgrep

  %% transitive deps (`rmeta`s):
  globset.rmeta ==> ripgrep & grep
  grep-cli.rmeta ==> ripgrep

This means that when a crate’s rmeta changes, the rustc invocations corresponding to all transitive dependents of that crate are rerun (even if intermediate rmetas are the same).

More concretely: when globset.rmeta changes, grep is rebuilt – even if grep-cli.rmeta (after grep-cli is re-compiled) hasn’t changed.

The fact that crate compiles depend on the rmetas for all transitive dependencies is significant because it inhibits our ability to get “early cutoff” (ECO). In reality, crates compiles are only actually sensitive to the subset of their transitive deps exposed via their direct deps but under this view (file-level, in the eyes of the build system) crates are sensitive to transitive dependencies in their entirety.

More concretely: the grep crate is only sensitive to the parts of globset accessible via grep_cli – if a change is made to globset that doesn’t affect this subset, we’d expect to see grep_cli being rebuilt but the existing grep outputs being reused (no grep rebuild).

“Early cutoff” (ECO) refers to a build system optimization where we are able to detect that a freshly-built artifact is identical to a prior one and to then reuse existing artifacts of dependent crates from then on (instead of continuing to rebuild them).

The next 6 months

  • Identify and remove “oversensitivity” in .rmeta
    • i.e. changes to spans, comments, etc. will not affect the .rmeta
    • coupled with cargo’s unstable checksum-freshness feature, this would avoid triggering rebuilds for dependent crates
  • Make DefIds more stable when items are added or reordered
    • today this is a major source of differences in compiler output
    • there are other things like SymbolIndexes which we may also want to stabilize
  • Work on designs for enabling “transitive” ECO
    • i.e. the decision to rebuild should factor in what parts of a transitive crate dep are accessible via direct deps

The “shiny future” we are working towards

Only changes to a crate that affect the public interface of the crate should cause downstream crates to rebuild.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Design meetingTeam compiler
Discussion and moral supportTeam compiler Team cargo
Nightly experiment for RDR
↳ Author MCP@osiewiczalready accepted
↳ Rustc ImplementationWIP
↳ Cargo ImplementationWIP
Improve DefId stability@dropbear32
Standard reviewsTeam compiler cargo

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Other kinds of decisions:

Frequently asked questions

Isn’t rustc incremental enough?

Theoretically, yes: under a system like rust-analyzer where there isn’t chunking of work along crate/file/process invocation boundaries, incremental compilation would obviate this effort.

However under rustc’s current architecture (1 process invocation per crate, new process invocation for each compile rather than a daemon): RDR (i.e. being able to skip rustc invocations) still matters.

Right now even when 100% of a compile’s incremental queries hit the cache (such as when you touch a source file; i.e. incr-unchanged) it still takes non-negligible amounts of time to replay those queries and re-emit compiler outputs (see zulip thread).


  1. cargo --timings output does not currently differentiate between time spent compiling (i.e. producing the rlib for) and linking the final binary (rg); the rg bar covers time spent for both

  2. We have taken some liberties in the above graph w.r.t. pipelining.

    Today, cargo preforms a single rustc invocation to produce the rlib and rmeta for each crate – rmeta is modeled as an “early out”.

    Additionally, producing ripgrep.rlib and linking (the rg (bin) node) happens as part of a single rustc invocation.

Rust Vision Document

Metadata
Point of contactNiko Matsakis
StatusProposed
Zulip channel[#vision-doc-2025][channel]
Tracking issuerust-lang/rust-project-goals#269
Teamsleadership-council
Task ownersvision team

Summary

Conduct sufficient interviews to gather adequate data from a representative sample of Rust users across demographic categories and target domains for the Rust Vision Doc. The Vision Doc aims to answer key research questions about Rust’s role in the technology landscape, what brings people to Rust, how Rust can succeed in various domains, and how we can improve the global experience of using and contributing to Rust. Our focus for 2025h2 is ensuring we have comprehensive, representative data before proceeding to synthesize findings and finalize the document. See our detailed research questions and interview guidelines for more information.

Motivation

The goal is to gather adequate data from a representative sample of Rust users and stakeholders to inform a longer-term “vision doc” that identifies key opportunities for Rust over the next 3-5 years.

The status quo

In 2025H1, we formed a vision team and began systematic data gathering for the Rust Vision Doc. We started with a comprehensive survey to get the “lay of the land” across different user segments, domains, and backgrounds. This survey helped us identify initial focus areas and connect with potential interview candidates.

Following the survey, we conducted a number of in-depth interviews with Rust users, maintainers, and community members. We presented a first draft of our findings at the Rust All Hands in May 2025 and collected initial feedback.

However, we have not gathered enough data yet to proceed with finalizing the Vision Doc. While we have good insights from current Rust users and some community segments, we need more comprehensive coverage across key areas, particularly non-Rust users (those considering Rust or who have decided against it). We also need more data across different demographic categories, geographic regions, and target domains to ensure the Vision Doc truly represents the broader landscape of potential Rust adoption and use.

The next 6 months

Our primary goal for 2025H2 is to conduct sufficient interviews to gather adequate data for the Rust Vision Doc. We will:

  1. Identify gaps in our current data coverage across different Rust use cases and user segments
  2. Develop a targeted interview strategy to fill these gaps
  3. Conduct interviews with users from underrepresented domains and use cases
  4. Document and synthesize the findings from these interviews
  5. Assess whether we have sufficient data to proceed with finalizing the Vision Doc

The “shiny future” we are working towards

The Rust Vision Doc will tell us about where we are and serve as a foundation for future planning, helping us identify the gaps that need to be closed. While Project Goals describe the next few steps, the Vision Doc will provide the broader context of Rust users’ needs and opportunities for improvement.

However, before we can create this foundational document, we need to ensure it’s based on comprehensive and representative data. The work in 2025H2 focuses on gathering adequate data through targeted interviews. Once we have sufficient data coverage, we can proceed to finalize the Vision Doc, likely in a future goal period.

If successful, we expect the Vision Doc will need to be periodically refreshed to help ensure we have a coherent view of Rust users’ needs as the ecosystem evolves. The completed Vision Doc will help teams prioritize their work and provide context for future Project Goals, serving as a communication tool for the broader Rust community about where Rust is headed and why certain priorities have been chosen.

Design axioms

  • Descriptive. We are capturing things as they are, documenting the current state of Rust adoption and user experiences.
  • Representative. We are cutting across various parts of Rust - different user segments, domains, geographic regions, and experience levels.
  • Qualitative. Interviews are good at identifying the range of Rust experiences, but we are not yet assessing which needs are the most common. That can be done as needed through a later phase of data collection.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Assess data gaps from 2025H1 workvision team
Develop targeted interview strategyvision team
Conduct targeted interviewsvision team
Document and synthesize interview findingsvision team
Assess data adequacy and plan next stepsvision team
Discussion and moral supportTeam leadership-council

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

How does this relate to the 2025H1 Rust Vision Doc goal?

The 2025H1 goal focused on forming a team, gathering initial status quo stories, and presenting a first draft at the Rust All Hands. This 2025H2 goal builds on that work by focusing specifically on ensuring we have adequate data coverage through targeted interviews before proceeding to finalize the document.

Why focus on data gathering rather than finalizing the document?

The feedback from the Rust All Hands and our own assessment revealed that while we have good insights from some areas, there are significant gaps in our understanding of how Rust is being used across different domains. Rather than rushing to publish an incomplete Vision Doc, we’re prioritizing comprehensive data gathering to ensure the final document is truly representative.

What happens after we have adequate data?

Once we’ve conducted sufficient interviews and assessed that we have adequate data coverage, we’ll plan the next steps for finalizing the Vision Doc. This may involve a future project goal focused on synthesis, RFC authoring, and publication.

Should we rename the “Vision Doc”?

Maybe! The better name might be “State of the Rust Union” or something like that. The current name “Vision Doc” suggests we’re primarily focused on future direction, but our actual goal is to understand where we are now and use that as a foundation for future planning. A name like “State of the Rust Union” might better capture that we’re assessing the current state of Rust adoption, usage, and community needs across different domains and user segments.

rustc-perf improvements

Metadata
Point of contactJames
StatusProposed
Zulip channel#project-goals/2025h1/rustc-perf-improvements
Tracking issuerust-lang/rust-project-goals#275
compiler championDavid Wood
infra championJakub Beránek
Teamscompiler, infra
Task ownersJames, Jakub Beránek, David Wood

This goal will be primarily worked on by James, but David Wood or Jakub Beránek can always be contacted for updates.

Summary

Continue our efforts from 2025H1 to add support to rustc-perf for distributed benchmarking across multiple platforms and configuration.

Motivation

Improving the performance of the Rust compiler is a long-standing objective of the Rust project and compiler team, which has led to the development of the project’s performance tracking infrastructure. While the performance tracking infrastructure has seen many improvements in recent years, it cannot scale to support multiple benchmarking machines simultaneously.

There are increasingly demands on the performance infrastructure which require a more scalable benchmarking infrastructure - benchmarking the parallel compiler with different thread counts, different codegen backends, or different architectures.

The status quo

rustc-perf does not yet support scheduling or accepting benchmarks from multiple machines.

To ensure ongoing changes don’t break existing functionality, tests have been added to guard the current system. Notable progress includes the introduction of database tests and incremental improvements to error handling in the new system.

A new system architecture has been outlined in this design document of which progress has commenced in implementing it. The new system will operate in parallel with the existing one until we are confident it can fully replace it. rustc-perf does not currently support scheduling and accepting benchmarks from multiple machines, requiring a non-trivial rearchitecting to do so. None of our policies around performance triage and handling regressions currently consider what to do in case of conflicting benchmarking results.

The next 6 months

This period is a continuation of the previous six months, during which meaningful progress was made in beginning the implementation of a new system for rustc-perf.

  • Switch the default collector to the new AX-42, initially running on the legacy non-parallel system.
  • Enable benchmarking to run in parallel across multiple collectors.
  • Continue expanding test coverage for the new distributed rustc-perf infrastructure to reduce the risk of future regressions.
  • Build a status page to display the health of each collector.
  • Add support for benchmarking on AArch64 as a separate architecture.
  • Enhance perf.rust-lang.org to display performance data from multiple collectors, with the ability to compare results within a given configuration (not across different configurations).

The “shiny future” we are working towards

Following the completion of this goal, it is anticipated that new platforms and configurations will be added to rustc-perf, but this is unlikely to warrant further goals.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam infra
Improve rustc-perf implementation workJames, Jakub Beránek
Standard reviewsTeam infra
Deploy to productionTeam infrarustc-perf improvements, testing infrastructure
Draft performance regression policyDavid Wood
Policy decisionTeam compilerUpdate performance regression policy
Inside Rust blog post announcing improvementsJakub Beránek, David Wood

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Stabilize rustdoc doc_cfg feature

Metadata
Point of contactGuillaume Gomez
StatusProposed
Other tracking issuesrust-lang/rust#43781
Zulip channel#t-rustdoc
rustdoc championGuillaume Gomez
Tracking issuerust-lang/rust-project-goals#404
Teamsrustdoc
Task ownersGuillaume Gomez

Summary

Over the next six months, we will do the following:

  • Finish the review and implementation of the feature.
  • Get users feedback.
  • Stabilize the feature.

Motivation

This goal represents the final step for the stabilization of a long awaited, allowing to greatly improve documentation quality by providing information about under which conditions an item is available.

The status quo

This has been one of the most asked rustdoc features recently. An RFC was written and merged. We’re now reaching the final steps before making this feature stable.

Without this feature, it’s not possible to know when an item is available, you need to go read the source code to find out if there are cfg attributes or not. It will improve the situation for both doc readers and doc writers:

  1. For readers, they won’t need to read source code anymore to find out when an item is available.
  2. For doc writers, they won’t need to write down explicitly when an item is available or rely on nightly features.

The next 6 months

Sketch out the specific things you are trying to achieve in this goal period. This should be short and high-level – we don’t want to see the design!

Finish implementation

A pull request is open, maybe a few more review rounds are required but it should be close to maturity.

Getting feedback

The next step will be to gather feedback, and in particular ensure that there is no bug. Here are the steps:

  1. Communication about the feature.
  2. Enable it by default on docs.rs

Stabilization

If no bug is reported for enough time, the last step will be to stabilize the feature.

Ownership and team asks

This section lists out the work to be done and the asks from Rust teams. Every row in the table should either correspond to something done by a contributor or something asked of a team.

For most goals, a single table will suffice, but you can also add subsections with ###. We give several example subsections below that also demonstrate the most common kinds of goals. Remember that the items in the table only corresponds to what you plan to do over the next 6 months.

For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. The owner is ideally identified as a github username like @ghost.

For items asked of teams, list Team and the name of the team, e.g. ![Team][] [compiler] or ![Team][] [compiler], [lang] (note the trailing [] in ![Team][], that is needed for markdown to parse correctly). For team asks, the “task” must be one of the tasks defined in rust-project-goals.toml or cargo rpg check will error.

TaskOwner(s) or team(s)Notes
Standard reviewsTeam rustdocMerge #138907
Communicate about the featureGuillaume Gomez
Enable it by default on docs.rsGuillaume Gomez
Send pull request to stabilize the featureGuillaume Gomez

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Add a team charter for rustdoc team

Metadata
Point of contactGuillaume Gomez
StatusProposed
Zulip channel#t-rustdoc
rustdoc championGuillaume Gomez
Tracking issuerust-lang/rust-project-goals#387
Teamsrustdoc
Task owners(none)

Summary

Over the next six months, we will do the following:

  • Write the team charter in the rust-forge

Motivation

Having a team charter will allow both rustdoc team members and non-members to have a document of reference when they want to know how to do something. It would also allow the rustdoc team to have well defined rules about what is expected of its members. And for non-members, it gives them indication on what’s expected to be able to join the team.

The status quo

Not having well defined written expectations leaves a grey area for everyone: non-members don’t know what are the processes and members could potentially all have different ways to handle similar situations.

The next 6 months

Writing the team charter.

Ownership and team asks

This section lists out the work to be done and the asks from Rust teams. Every row in the table should either correspond to something done by a contributor or something asked of a team.

For most goals, a single table will suffice, but you can also add subsections with ###. We give several example subsections below that also demonstrate the most common kinds of goals. Remember that the items in the table only corresponds to what you plan to do over the next 6 months.

For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. The owner is ideally identified as a github username like @ghost.

For items asked of teams, list Team and the name of the team, e.g. ![Team][] [compiler] or ![Team][] [compiler], [lang] (note the trailing [] in ![Team][], that is needed for markdown to parse correctly). For team asks, the “task” must be one of the tasks defined in rust-project-goals.toml or cargo rpg check will error.

TaskOwner(s) or team(s)Notes
Org decisionTeam rustdocWrite team charter

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

SVE and SME on AArch64

Metadata
Point of contactDavid Wood
StatusProposed
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#270
compiler championDavid Wood
lang championNiko Matsakis
libs championAmanieu d’Antras
Teamscompiler, lang, libs, types
Task ownersDavid Wood

Summary

Over the next six months, we will continue our efforts from the 2025H1 goal to merge nightly support for SVE and establish a path towards stabilisation:

  • propose language changes which will enable scalable vector types to be represented in Rust’s type system
  • land an experimental nightly implementation of SVE
  • identify remaining blockers for SVE stabilisation and plan their resolution
  • gain a better understanding of SME’s implications for Rust and identify first steps towards design and implementation

Motivation

AArch64 is an important architecture for Rust, with two tier 1 targets and over thirty targets in lower tiers. It is widely used by some of Rust’s largest stakeholders and as a systems language, it is important that Rust is able to leverage all of the hardware capabilities provided by the architecture, including new SIMD extensions: SVE and SME.

SIMD types and instructions are a crucial element of high-performance Rust applications and allow for operating on multiple values in a single instruction. Many processors have SIMD registers of a known fixed length and provide intrinsics which operate on these registers. Arm’s Neon extension is well-supported by Rust and provides 128-bit registers and a wide range of intrinsics.

Instead of releasing more extensions with ever increasing register bit widths, recent versions of AArch64 have a Scalable Vector Extension (SVE), with vector registers whose width depends on the CPU implementation and bit-width-agnostic intrinsics for operating on these registers. By using SVE, code won’t need to be re-written using new architecture extensions with larger registers, new types and intrinsics, but instead will work on newer processors with different vector register lengths and performance characteristics.

SVE has interesting and challenging implications for Rust, introducing value types with sizes that can only be known at runtime, requiring significant work on the language and compiler. Arm has since introduced Scalable Matrix Extensions (SME), building on SVE to add new capabilities to efficiently process matrices, with even more interesting implications for Rust.

Hardware is generally available with SVE, and key Rust stakeholders want to be able to use these architecture features from Rust. In a recent discussion on SVE, Amanieu, co-lead of the library team, said:

I’ve talked with several people in Google, Huawei and Microsoft, all of whom have expressed a rather urgent desire for the ability to use SVE intrinsics in Rust code, especially now that SVE hardware is generally available.

While SVE is specifically an AArch64 extension, the infrastructure for scalable vectors in Rust should also enable Rust to support for RISC-V’s “V” Vector Extension, and this goal will endeavour to extend Rust in an architecture-agnostic way. SVE is supported in C through Arm’s C Language Extensions (ACLE) but requires a change to the C standard (documented in pages 122-126 of the 2024Q3 ACLE), so Rust has an opportunity to be the first systems programming language with native support for these hardware capabilities.

The status quo

SVE is currently entirely unsupported by Rust, but progress is being made - see the tracking issues for the Sized Hierarchy prerequisite (rust#144404) and for Scalable Vectors themselves (rust#145052).

The next 6 months

The primary objective of this initial goal is to land a nightly experiment with SVE, have both RFCs accepted and establish a path towards stabilisation:

  1. Resolve any and all follow-ups to rust#137944 now that it has been merged
  2. Merge a pull request with Part II of [rust#3729]’s implementation
  3. Rewrite rfcs#3838 in light of rfcs#3729 to defer to rfcs#3729’s solutions for how scalable vectors will fit in the Rust type system
  4. Rebase rust#143924 on top of Part II of the Sized Hierarchy work, enabling it to be merged experimentally
  5. Merge stdarch#1509 adding SVE types and intrinsics
  6. Identify and start addressing remaining stabilisation blockers

The “shiny future” we are working towards

Adding support for Scalable Matrix Extensions in Rust is the next logical step following SVE support. There are still many unknowns regarding what this will involve and part of this goal or the next goal will be understanding these unknowns better.

Design axioms

  • Avoid overfitting. It’s important that whatever extensions to Rust’s type system are proposed are not narrowly tailored to support for SVE/SME, can be used to support similar extensions from other architectures, and unblocks or enables other desired Rust features wherever possible and practical.
  • Low-level control. Rust should be able to leverage the full capabilities and performance of the underlying hardware features and should strive to avoid inherent limitations in its support.
  • Rusty-ness. Extensions to Rust to support these hardware capabilities should align with Rust’s design axioms and feel like natural extensions of the type system.

Ownership and team asks

Here is a detailed list of the work to be done and who is expected to do it. This table includes the work to be done by owners and the work to be done by Rust teams (subject to approval by the team in an RFC/FCP).

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang, types, compiler, libs
ImplementationDavid WoodPart II of Sized Hierarchy implementation
Dedicated reviewerTeam typesReview Part II of Sized Hierarchy implementation
Author RFCDavid WoodWrite rfcs#3838 in light of rfcs#3729
Lang-team experimentTeam libs, compilerApprove experiment of rfcs#3838
ImplementationDavid WoodUpdate rust#143924 after Part II
Standard reviewsTeam compilerReview and approve rust#143924
ImplementationDavid WoodUpdate stdarch#1509 with SVE types/intrinsics
Standard reviewsTeam libsReview and approve stdarch#1509
RFC decisionTeam langLanguage team decide whether to accept rfcs#3729
RFC decisionTeam langCompiler/Library team decide whether to accept rfcs#3838

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Rust Stabilization of MemorySanitizer and ThreadSanitizer Support

Metadata
Point of contactJakob Koschel
StatusProposed
flagshipFlexible, fast(er) builds
Tracking issuerust-lang/rust-project-goals#403
Zulip channelN/A
Teamsbootstrap, compiler, infra, project-exploit-mitigations
Task owners[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

Summary

Stabilize the MemorySanitizer and ThreadSanitizer support. This includes fixing open bugs for the sanitizers to open a path for stabilization and the necessary infrastructure changes to provide precompiled and instrumented standard libraries for the sanitizers.

Motivation

Sanitizers help with increasing the robustness and security of software and have been increasingly adopted as part of the software development life cycle. Even though the Rust programming language provides memory and thread safety guarantees, use of Unsafe Rust and foreign code in mixed-language binaries do not provide the same memory and thread safety guarantees. Thus, support for sanitizers must be added to the Rust compiler for secure Rust adoption ([source](https://hackmd.io/Ramon de C Valle/S1Ou9K6H6#Organize-and-stabilize-support-for-sanitizers)).

In order for them to be properly usable, the sanitizer support should be stabilized so it is no longer required to use a nightly toolchain and build your own standard libraries.

The status quo

Currently, there is unstable support for several sanitizers (address, hwaddress, memtag, memory, thread, leak, cfi, kcfi, safestack, shadow-call-stack). The AddressSanitizer and LeakSanitizer (that do not require rebuilding an instrumented standard library) are close to being stabilized (https://github.com/rust-lang/rust/pull/123617). The others require more work in order to become stabilized.

The next 6 months

The goal is to stabilize MemorySanitizer and ThreadSanitizer for Tier 1 targets and provide a way to use them without rebuilding the standard library (which currently is also behind an unstable flag). This requires a way to ship sanitizer instrumented standard libraries (for Memory- and ThreadSanitizer) through rustup.

The “shiny future” we are working towards

All sanitizers (including memtag, cfi, kcfi, safestack, shadow-call-stack) are fully stabilized and supported on all targets supported by the Rust compiler. In the meantime we work towards at least supporting Tier 1 targets for all of them.

Ownership and team asks

Owner: [Jakob Koschel](https://github.com/jakos-sec), [Bastian Kersting](https://github.com/1c3t3a)

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler, infra
Implementation[Jakob Koschel](https://github.com/jakos-sec), [Bastian Kersting](https://github.com/1c3t3a)
Stabilization decisionTeam compiler
Standard reviewsTeam compiler
Dedicated reviewerTeam bootstrap, project-exploit-mitigations

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Type System Documentation

Metadata
Point of contactBoxy
StatusProposed
Tracking issuerust-lang/rust-project-goals#405
Zulip channelN/A
types championBoxy
Teamstypes
Task ownersBoxy, lcnr

Summary

Improve documentation of type system components to aide in types team onboarding and communication about changes to the type system .

Motivation & Status Quo

The type system is a very complex and critical component of the compiler. It is currently lacking in documentation, and the documentation that does exist is often inadequate for gaining a thorough understanding of a given part of the type system (or simply outdated as it was written many years ago).

The lack of documentation makes onboarding difficult for new contributors and require a lot of energy from experienced contributors who are now responsible for explaining everything from scratch themselves. A similar problem also occurs when reviewing changes to the type system, as there is no documentation it can be difficult to bring everything back into cache and be confident that the subtleties of the area being changed have all been taken into account.

The next 6 months

  • Compile and publish a list of type system concepts then compare that against the in-compiler documentation and the rustc-dev-guide’s type system chapter to find weak points in our documentation.
  • Document existing known weak points:
    • How const generic arguments are type checked
    • The design of the new solver and how/why it differs from the old solver

The “shiny future” we are working towards

All type system components should be thoroughly documented. Contributors should not find themselves in a position where knowledge of the type system is only attainable by speaking with types team members instead of having readily available documentation to read.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam types
Triage Analysis ChapterBoxy
Const Generics DocumentationBoxy
New Solver DocumentationBoxy, lcnr

Unsafe Fields

Metadata
Point of contactJack Wrenn
StatusProposed
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#273
compiler championJack Wrenn
lang championScott McMurray
Teamscompiler, lang
Task ownersJacob Pratt, Jack Wrenn, Luca Versari

Summary

Design and implement a mechanism for denoting when fields carry library safety invariants.

Motivation

The absence of a mechanism for denoting the presence of library safety invariants increases both the risk of working with unsafe code and the difficulty of evaluating its soundness.

The status quo

Presently, Rust lacks mechanisms for denoting when fields carry library safety invariants, and for enforcing extra care around their use. Consequently, to evaluate the soundness of unsafe code (i.e., code which relies on safety invariants being upheld), it is not enough to check the contents of unsafe blocks — one must check all places (including safe contexts) in which safety invariants might be violated. (See The Scope of Unsafe)

For example, consider this idealized Vec:

#![allow(unused)]
fn main() {
pub struct Vec<T> {
    data: Box<[MaybeUninit<T>]>,
    len: usize,
}
}

Although len is bound by a safety invariant, it is trivial to violate its invariant in entirely safe code:

#![allow(unused)]
fn main() {
impl Vec<T> {
    pub fn evil(&mut self) {
        self.len += 2;
    }
}
}

Rust cannot enforce that modifications of len require unsafe, because the language does not provide the programmer a way of communicating to the compiler that len carries safety invariants.

The “shiny future” we are working towards

Rust programmers will use the unsafe keyword to denote fields that carry library safety invariants; e.g.:

#![allow(unused)]
fn main() {
struct Vec<T> {
    // SAFETY: The elements `data[i]` for
    // `i < len` are in a valid state.
    unsafe data: Box<[MaybeUninit<T>]>,
    unsafe len: usize,
}
}

Rust will require that usages of unsafe fields which could violate their safety invariants must only occur within unsafe contexts.

The next 6 months

In the next six months, we will iterate on the design and implementation of unsafe fields. An RFC for unsafe fields will be accepted, and a candidate implementation will — at the very least — be ready to enter the stabilization process.

Design axioms

The design of unsafe fields is guided by three axioms:

  1. Unsafe Fields Denote Safety Invariants A field should be marked unsafe if it carries arbitrary library safety invariants with respect to its enclosing type.
  2. Unsafe Usage is Always Unsafe Uses of unsafe fields which could violate their invariants must occur in the scope of an unsafe block.
  3. Safe Usage is Usually Safe Uses of unsafe fields which cannot violate their invariants should not require an unsafe block.

Ownership and team asks

Owner: Jack Wrenn

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Author RFCJacob Pratt, Jack WrennRFC3458, Living Design Doc
ImplementationLuca Versari, Jack Wrenn
Standard reviewsTeam compiler
Design meetingTeam lang
RFC decisionTeam lang

Ongoing discussion on Zulip.

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

TBD

Not accepted

This section contains goals that were proposed but ultimately not accepted, either for want of resources or consensus. In many cases, narrower versions of these goals were proposed instead.

GoalPoint of contactTask Owners and Champions
DelegationVadim Petrochenkov@bryanskiy, Vadim Petrochenkov (compiler)

Reports

This section contains automatically generated reports based on the comments left in the goal tracking issues.

These reports were last generated at 2026-02-16 10:21:15 UTC.

February Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

No detailed updates available.
Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

No detailed updates available.
Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

No detailed updates available.
C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

No detailed updates available.
Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

1 detailed update available.

Comment by [Niko Matsakis][] posted on 2026-02-13:

Latest updates:

Boxy and I have met (and continue to meet) and work on modeling const generics in a-mir-formality. We're still working on laying the groundwork.

There is a proposed project goal for next year: https://rust-lang.github.io/rust-project-goals/2026/const-generics.html

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

No detailed updates available.
Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

No detailed updates available.
Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

No detailed updates available.
Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

No detailed updates available.
Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

No detailed updates available.
Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

No detailed updates available.
Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

No detailed updates available.
Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

No detailed updates available.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

No detailed updates available.
Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

No detailed updates available.
Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

No detailed updates available.
Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

No detailed updates available.
In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

No detailed updates available.
MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

No detailed updates available.
Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

No detailed updates available.
Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

No detailed updates available.
Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

No detailed updates available.
Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

No detailed updates available.
reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

1 detailed update available.

Comment by [Oliver Scherer][] posted on 2026-02-09:
  • @BD103 added slices, arrays and raw pointer support
    • https://github.com/rust-lang/rust/pull/151019
    • https://github.com/rust-lang/rust/pull/151031
    • https://github.com/rust-lang/rust/pull/151118
    • https://github.com/rust-lang/rust/pull/151119
  • Asuna added all of our primitives
    • https://github.com/rust-lang/rust/pull/151123
  • Jamie Hill-Daniel gave us references
    • https://github.com/rust-lang/rust/pull/151222
  • @izagawd made it possible to extract some info from dyn Trait
    • https://github.com/rust-lang/rust/pull/151239

There is ongoing work for Adts and function pointers, both of which will land as MVPs and will need some work to make them respect semver or generally become useful in practice

Removing the 'static bound from try_as_dyn turned out to have many warts, so I'm limiting it to a much smaller subset and will have borrowck emit the 'static requirement if the other rules do not apply (instead of having an unconditional 'static requirement)

Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

No detailed updates available.
Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

No detailed updates available.
Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

No detailed updates available.
Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

1 detailed update available.

Comment by [Jakob Koschel][] posted on 2026-02-16:

Both the MCP and the PR for the AddressSanitizer target have been merged (https://github.com/rust-lang/compiler-team/issues/951, https://github.com/rust-lang/rust/pull/149644). Next up I should prepare the MCP for the Memory- and ThreadSanitizer targets, hopefully sending out soon.

Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

No detailed updates available.
rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

No detailed updates available.
Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

No detailed updates available.
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2026-02-13:

Key developments

  • FCP has ended on frontmatter support, just awaiting merge (https://github.com/rust-lang/rust/pull/148051)
  • Cargo script has entered FCP (https://github.com/rust-lang/cargo/pull/16569)

Blockers

  • Potential issues around edition, see https://github.com/rust-lang/rust/issues/152254
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

No detailed updates available.
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

No detailed updates available.
Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

No detailed updates available.
Progress
Point of contact

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

January Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

No detailed updates available.
Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

No detailed updates available.
Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

1 detailed update available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rfcs#3873 has been merged and an FCP has been started on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 - those both have some feedback for me to respond to that I'll get to as soon as I can

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

2 detailed updates available.

Comment by [Joel Marcey][] posted on 2026-01-20:

The Rust Foundation is opening up a short-term, approximately 3-month, contracting role to assist in our Rust/C++ Interop initiative. The primary work and deliverables for the role will be to make substantial progress on the Problem Space Mapping Rust Project Goal by collecting discrete problem statements and offering up recommendations on the work that should follow based upon the problems that you found.



If you are interested in how programming languages interoperate, are curious in understanding the problems therein, and are have a passion to think about how those problems may be resolved for the betterment of interop, then this work may be for you.

An ideal candidate will have experience with Rust programming. Having experience in C++ is strongly preferred as well. If you have direct experience with actual engineering that required interoperating between Rust and C++ codebases, that's even better.



If you are interested, please email me (email address found in my GitHub profile) or contact me directly on Zulip by Tuesday, January 27 and we can take it from there to see if there may be a potential fit for further discussion.

Thank you.

Comment by [Joel Marcey][] posted on 2026-01-31:

The effort to fill the contracting role to support this project goal is in the process winding down. The interview and discussion process is nearly complete. We expect to make a final decision for the role in early February.

Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

2 detailed updates available.

Comment by [Niko Matsakis][] posted on 2026-01-27:

Boxy and I have established a regular time to check-in on formalizing this within a-mir-formality. Today we mostly worked on the "model" of const values, starting with this

#![allow(unused)]
fn main() {
#[term]
pub enum ConstData {
    // Sort of equivalent to `ValTreeKind::Branch`
    #[cast]
    RigidValue(RigidConstData),

    // Sort of equivalent to `ValTreeKind::Leaf`
    #[cast]
    Scalar(ScalarValue),

    #[variable(ParameterKind::Const)]
    Variable(Variable),
}



#[term]
pub enum ScalarValue {
    #[grammar(u8($v0))]
    U8(u8),
    #[grammar(u16($v0))]
    U16(u16),
    #[grammar(u32($v0))]
    U32(u32),
    #[grammar(u64($v0))]
    U64(u64),
    #[grammar(i8($v0))]
    I8(i8),
    #[grammar(i16($v0))]
    I16(i16),
    #[grammar(i32($v0))]
    I32(i32),
    #[grammar(i64($v0))]
    I64(i64),
    #[grammar($v0)]
    Bool(bool),
    #[grammar(usize($v0))]
    Usize(usize),
    #[grammar(isize($v0))]
    Isize(isize),
}


#[term($name $<parameters> { $,values })]
pub struct RigidConstData {
    pub name: RigidName,
    pub parameters: Parameters,
    pub values: Vec<Const>,
}
}

i.e., a const value can be a scalar value (as today) or a struct literal like Foo { ... } (which would also cover tuples and things). We got the various tests passing. Huzzah!

Comment by [Boxy][] posted on 2026-01-30:

In addition to what niko posted previously there's been a lot of other stuff happening. A lot of people have opened PRs to improve mGCA this month: León Orell Valerian Liehr Noah Lev @enthropy7 Kivooeo @mu001999 @Human9000-bit Redddy @Keith-Cancel @AprilNEA

A rough list of things that have been improved for mGCA:

  • Lots of new expressions now supported by mGCA: const constructors, tuple constructor calls, array expressions, tuple expression, literals
  • associated_const_equality has been merged into min_generic_const_args. the former was effectively dependent on the latter already so this just makes it nicer to use the former :)
  • traits can now be dyn compatible if all associated constants are type consts and are specified in the trait object (e.g. dyn Trait<ASSOC = 10>)
  • type consts are enforced to be non-generic
  • a bunch of ICEs have been fixed
  • camelid has been working on "non-min" version of mGCA which will allow arbitrary expressions to be used in the type system (a blog post with more detail will be published once this actually lands)

In non-mGCA updates, as niko says, we've been meeting regularly to make progress on modelling const generics in a-mir-formality. I've also been spending time thinking about the interactions between adt_const_params and ADTs with privacy/safety invariants and I think I know how to structure the RFC in this area so can make progress on that again

There's some more detail about the various bits of work people have done and who did what here: #project-const-generics > perfectly adequately sized wins @ 💬

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

No detailed updates available.
Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

1 detailed update available.

Comment by [Predrag Gruevski][] posted on 2026-01-17:

I posted a "year in review" for cargo-semver-checks here: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/

It has a section on how I think we should move forward in 2026 and beyond: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/#the-path-forward-for-2026-and-beyond

Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

TL;DR.

1 detailed update available.

Comment by [Benno Lossin][] posted on 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.

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

No detailed updates available.
Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

1 detailed update available.

Comment by [Ian McCormack][] posted on 2026-01-09:

Here's our January status update!

  • Yesterday, we posted an MCP for our retag intrinsics. While that's in progress, we'll start adapting our current prototype to remove our dependence on MIR-level retags. Once that's finished, we'll be ready to submit a PR.

  • We published our first monthly blog post about BorrowSanitizer.

  • Our overall goal for 2026 is to transition from a research prototype to a functional tool. Three key features have yet to be implemented: garbage collection, error reporting, and support for atomic memory accesses. Once these are complete, we'll be able to start testing real-world libraries and auditing our results against Miri.

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

No detailed updates available.
Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

No detailed updates available.
Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

No detailed updates available.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

1 detailed update available.

Comment by [Manuel Drehwald][] posted on 2026-01-16:

Key developments:

std::autodiff is moving closer to nightly, and std::offload is gaining various performance, feature, and hardware support improvements.

autodiff

Jakub Beránek, @sgasho, and I continued working on enabling autodiff in nightly. We have a PR up that builds autodiff in CI, and verified that the artifacts can be installed and work on Linux. For apple however, we noticed that any autodiff usage hangs. After some investigation, it turns out that we ended up embedding two LLVM copies, one in rustc, and one in Enzyme. It should be comparably easy to get rid of the second one. Once we verified that this fixes the build, we'll merge the PR to enable autodiff on both targets in nightly.

offload

A lot of interesting updates on the performance, feature, and hardware support side.

  1. Marcelo Domínguez, @kevinsala, @jdoerfert, and I started implementing the first benchmarks, since that's generally the best way to find missing features or performance issues. We were positively surprised by how good the out-of-the-box performance was. We will implement a few more benchmarks and post the results once we have verified them. We also implemented multiple PRs which implement bugfixes, cleanups, and needed features like support for scalars. We also started working on LLVM optimizations which make sure that we can achieve even better performance.

  2. I noticed that our offload intrinsic allowed running Rust code on the GPU, but it wasn't of much help when calling gpu vendor libraries like cuBLAS. In https://github.com/rust-lang/rust/pull/150683 I implemented a new helper intrinsic which allows calling those functions conveniently, without having to manually move data to or from the device. It will benefit from the same LLVM optimizations as our full offload intrinsic. It also a bit simpler to set up on the compiler and linker side, so it already works with std and mangled kernel names, something that we still have to improve for our main offload intrinsic.

  3. A lot of work happened on the LLVM offload side for SPIRV and Intel GPU support. At the moment, our Rust frontend is tested on NVIDIA and AMD server and consumer GPUs, as well as AMD HPC and Lapotop APUs. Karol Zwolak reached out since he wants to help with with also running Rust on Intel GPUs. Offload relies on LLVM which started gaining Intel support, so hopefully we won't need much work beyond a new intel-gpu target and a new stdarch module. There is also work on a new spirv target for rustc, which we could also support if it goes through LLVM. Due to some open questions around typed pointers it does not seem clear yet whether it will, so we will have to wait.

  4. Nikita started working on updating our submodule to LLVM 22. This hopefully does not only brings some compile and runtime performance improvements, but also greatly simplifies how we can build and use offload. Once it landed I'll refactor our bootstraping logic, and as part of that start building offload in CI.

Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

1 detailed update available.

Comment by [Tomas Sedovic][] posted on 2026-01-16:

Update from the 2026-01-14 meeting:

#![register_tool] rust#66079

Tyler Mandry proposed FCP of the RFC#3808 and nominated it for a Lang discussion.

-Zdebuginfo-compression rust#120953

Wesley Wiser proposed stabilization: rust#150625.

Josh Triplett suggested trying to bring zlib-rs in the kernel as a case study.

-Zdirect-access-external-data rust#127488

rust#150494 was merged two days ago, what reminds is updating the documentation and stabilizing the feature.

There's an ongoing discussion about the feature on the Rust Zulip as well.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

1 detailed update available.

Comment by [Tomas Sedovic][] posted on 2026-01-19:

Update from the 2026-01-14 meeting.

Deref / Receiver

Ding's arbitrary_self_types: Split the Autoderef chain rust#146095 is waiting on reviews. It updates the method resolution to essentially: deref_chain(T).flat_map(|U| receiver_chain(U)).

The perf run was a wash and a carter has completed yesterday. Analysis pending.

RFC #3851: Supertrait Auto-impl

Ding has submitted a Rust Project goal for Supertrait Auto Impl.

Arbitrary Self Types rust#44874

We've discovered the #[feature(arbitrary_self_types_pointer)] feature gate. As the Lang consensus is to not support the Receiver trait on raw pointer types we're probably going to remove it (but this needs further discussion). This was a remnant from the original proposal, but the Lang has changed direction since.

derive(CoercePointee) rust#123430

Ding is working on a fix to prevent accidental specialization of the trait implementation. rust#149968 is adding an interim fix.

Alice opened a Reference PR for rust#136776. There are questions around the behaviour of the as cast vs. coercions.

Pass pointers to const in assembly rfc#3848

Gary opened implementation for the RFC: rust#138618.

In-place initialization goal#395

Ding is writing a post to describe all the open proposals including Alice's new one that she brouhght up during the LPC 2025. He'll merge it in: https://rust-lang.github.io/beyond-refs.

Field Projections goal#390

Benno updated the Field Representing Types PR to the latest design. This makes the PR much simpler.

Tyler opened a wiki to keep all the proposals, resources in one place: https://rust-lang.github.io/beyond-refs.

Macros, attributes, derives, etc.

Josh brought up his work on adding more capable declarative macros for writing attributes and derives. He's asked the Rust for Linux team for what they need to stop using proc macros.

Miguel noted they've just added dependency on syn, but they would like to remove it some day if their could.

Benno provided a few cases of large macros that he thought were unlikely to be replacable by declarative-style ones. Josh suggested there may be a way and suggested an asynchronous discussion.

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

No detailed updates available.
In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

1 detailed update available.

Comment by [Alice Ryhl][] posted on 2026-01-31:

A proposal to continue this goal in the next goal period was merged: https://github.com/rust-lang/rust-project-goals/pull/477

MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

No detailed updates available.
Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

1 detailed update available.

Comment by [lcnr][] posted on 2026-01-19:

There hasn't been too much progress over the last few weeks and I've been mostly taking a Christmas break. Nicholas Nethercote has been looking into the performance of the new trait solver, cleaning up canonicalization and slightly improving its performance: https://github.com/rust-lang/rust/pull/150748 https://github.com/rust-lang/rust/pull/150859.

Shoyu Vanilla looked into https://github.com/rust-lang/trait-system-refactor-initiative/issues/251 and uncovered the underlying bug there. While this issue also affects the old solver and the proper fix for it requires where-bounds on binders, we can work around this bug in the trait solver for now and intend to do so.

We've started another crater run with all our recent changes and adwin has started to triage it, uncovering one new issue up until now. Intend to continue going through that over the next few weeks.

There's also a lot in-progress work going on. I am collaborating with Niko Matsakis to specify and later RFC the cycle semantics of Rust. León Orell Valerian Liehr is working on a replacement for the rustdoc's auto trait impl synthesis: https://github.com/rust-lang/rust/pull/149019. @tiff is working on a fix a MIR borrowck unsoundness: https://github.com/rust-lang/trait-system-refactor-initiative/issues/159. Shoyu Vanilla and I are improving the way we propagate inference constraints from the expected return type to function arguments, fixing https://github.com/rust-lang/trait-system-refactor-initiative/issues/259.

Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

No detailed updates available.
Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

1 detailed update available.

Comment by [Weihang Lo][] posted on 2026-01-08:

Project Goal Update

The prototype of this project goal is basically complete.

Current state

This project goal introduces build analysis support in Cargo, with the aim of making build behavior understandable across multiple invocations, not just a single run.

At a high level, the prototype:

  • Records build metadata over time, including:
    • rebuild reasons
    • timing information
    • relevant invocation context
  • Stores this data locally in a structured log format suitable for later analysis
  • Exposes the data via unstable cargo report subcommands, such as:
    • cargo report sessions - list session IDs
    • cargo report timings - HTML timing report
    • cargo report rebuilds - Why things rebuilt

See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-analysis for a more thorough usage documentation


Path towards stabilization

Before this feature can be stabilized, the following unresolved questions must be answered.

They might not block stabilization, but need to be evaluated if it is fine to leave for future.

cargo report commands

This is a stabilization blocker.

  • [ ] Currently all three report commands (sessions, rebuilds, timings) implicitly inspect global log files when if not in a workspace.
    • Should this be explicit with a flag?
    • Should this be an error if not in a workspace?
  • [ ] Bikeshed on command names
    • Currently we have all nouns
      • For sessions
        • runs simple but ambiguous
        • Just log like git log
        • history user-friendly (docker history, shell history, though not alike)
      • For timings:
        • Not controversial, as we have --timings flag already
      • For rebuilds:
        • rebuild-reasons more explicit
    • Or move to action-oriented verbs:
    • cargo report list-sessions
    • cargo report analyze-timings (bazel analyze-profile https://bazel.build/docs/user-manual#analyze-profile)
    • cargo report explain-rebuilds
    • Or question-oriented verbs:
    • cargo report what-ran more general https://buck2.build/docs/developers/what-ran/
    • cargo report why-rebuilt/why-reran

cargo report sessions

  • Currently it prints a human-readable output without a format for programmable use cases.
    • Should we provide a programmable output (for example behind --message-format=json)?

cargo report rebuilds

  • Extend the report from fingerprint to new hash (-Cmetadata/-Cextra-filename)
    • We currently can't distinguish whether a fresh build is a real new build or just rustflags changed
    • https://github.com/rust-lang/cargo/pull/16456#discussion_r2662364819
  • Make each rebuilt reason more actionable and friendly for end-users.
  • Should we log the fingerprint values being compared, or just the diff result?
  • #t-cargo > logging unit fingerprint @ 💬

Log message schema

This is a stabilization blocker.

Log infrastructure

These are mostly future possibilities, not a stabilization blocker, as it is highly possible to do incremental improvements.

See also https://github.com/rust-lang/cargo/issues/16471#issuecomment-3724915770

Nested Cargo calls

See https://github.com/rust-lang/cargo/issues/16477.

Basically, we need to have a way to associate log files of nested Cargo calls. That helps other tools as well as cargo fix itself.

This is a stabilization blocker.

How contributors can help

Future contributors can help by:

A series of follow-up tasks has been cut to track remaining work:

  • https://github.com/rust-lang/cargo/issues/16470
  • https://github.com/rust-lang/cargo/issues/16471
  • https://github.com/rust-lang/cargo/issues/16472
  • https://github.com/rust-lang/cargo/issues/16473
  • https://github.com/rust-lang/cargo/issues/16474
  • https://github.com/rust-lang/cargo/issues/16475
  • https://github.com/rust-lang/cargo/issues/16477
  • https://github.com/rust-lang/cargo/issues/16488
Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

No detailed updates available.
reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

1 detailed update available.

Comment by [Oliver Scherer][] posted on 2026-01-14:
  • https://github.com/rust-lang/rust/pull/146923 has landed, and we even got the first contribs adding array support to reflection.
    • there are lots more types and type information that we could support, and it's rather easy to add more. Happy to review any work here.
  • https://github.com/rust-lang/rust/pull/150033 has landed, and I'm working on removing the 'static requirement in https://github.com/rust-lang/rust/pull/150161
Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

No detailed updates available.
Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

1 detailed update available.

Comment by [Ross Sullivan][] posted on 2026-01-15:

Status update January 15, 2026

Fine grain locking for build-dir was merged in https://github.com/rust-lang/cargo/pull/16155 and now available on nightly via -Zfine-grain-locking unstable flag. 🎉

There are some known issues we'd like to address before doing a formal call for testing. Notably, improving blocking messages, fixing potential thread starvation in Cargo's job queue when locks block, and investigate increasing rlimits to reduce risk of hitting max file descriptors for large projects.

I am hopeful that these issues will be resolved over the coming month and we can do a call for testing to start gathering feedback from the community on whether the new locking strategy improves workflows.

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

No detailed updates available.
Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

1 detailed update available.

Comment by [Jakob Koschel][] posted on 2026-01-14:

The MCP (https://github.com/rust-lang/compiler-team/issues/951) has been seconded and is still waiting 3 days to be approved. Once that is done, we can proceed with merging the Tier 2 target.

Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

No detailed updates available.
rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

No detailed updates available.
Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

1 detailed update available.

Comment by [Rémy Rakic][] posted on 2026-01-30:

This month's update:

  • tiif is making progress on https://github.com/rust-lang/trait-system-refactor-initiative/issues/159
  • 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.
  • https://github.com/rust-lang/rust/pull/149639 has now landed, and https://github.com/rust-lang/rust/pull/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 🤞
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2026-01-14:

Key developments

  • #146377 has been decided and merged

Blockers

  • T-lang discussing CR / text direction feedback: https://github.com/rust-lang/rust/pull/148051#issuecomment-3638326490
  • T-rustdoc deciding on and implementing how they want frontmatter handled in doctests
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

No detailed updates available.
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

1 detailed update available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rust#143924 has been merged, enabling scalable vector types to be defined on nightly, and I'm working on a patch to introduce unstable intrinsics/scalable vector types to std::arch

Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

1 detailed update available.

Comment by [Boxy][] posted on 2026-01-30:

Nothing this month, been busy with other stuff :)

Progress
Point of contact

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

December Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

No detailed updates available.
Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

4 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-12-03:

PR https://github.com/rust-lang/a-mir-formality/pull/206 contains a "first draft" for the NLL rules. It checks for loan violations (e.g., mutating borrowed data) as well as some notion of outlives requirements. It does not check for move errors and there aren't a lot of tests yet.

Comment by [Niko Matsakis][] posted on 2025-12-03:

The PR also includes two big improvements to the a-mir-formality framework:

  • support for (for_all) rules that can handle "iteration"
  • tracking proof trees, making it much easier to tell why something is accepted that should not be
Comment by [Niko Matsakis][] posted on 2025-12-10:

Update: opened https://github.com/rust-lang/a-mir-formality/pull/207 which contains support for &mut, wrote some new tests (including one FIXME), and added a test for NLL Problem Case #3 (which behaved as expected).

One interesting thing (cc Ralf Jung) is that we have diverged from MiniRust in a few minor ways:

  • We do not support embedding value expressions in place expressions.
  • Where MiniRust has a AddrOf operator that uses the PtrType to decide what kind of operation it is, we have added a Ref MIR operation. This is in part because we need information that is not present in MiniRust, specifically a lifetime.
  • We have also opted to extend goto with the ability to take multiple successors, so that goto b1, b2 can be seen as "goto either b1 or b2 non-deterministically" (the actual opsem would probably be to always go to b1, making this a way to add "fake edges", but the analysis should not assume that).
Comment by [Niko Matsakis][] posted on 2025-12-17:

Update: opened https://github.com/rust-lang/a-mir-formality/pull/210 with today's work. We are discussing how to move the checker to support polonius-alpha. To that end, we introduced feature gates (so that a-mir-formality can model nightly features) and did some refactoring of the type checker aiming at allowing outlives to become flow-sensitive.

Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

1 detailed update available.

Comment by [David Wood][] posted on 2025-12-15:

rust-lang/rfcs#3873 is waiting on one checkbox before entering the final comment period. We had our sync meeting on the 11th and decided that we would enter FCP on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 after rust-lang/rfcs#3873 is accepted. We've responded to almost all of the feedback on the next two RFCs and expect the FCP to act as a forcing-function so that the relevant teams take a look, they can always register concerns if there are things we need to address, and if we need to make any major changes then we'll restart the FCP.

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

No detailed updates available.
Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

3 detailed updates available.

Comment by [Boxy][] posted on 2025-12-30:

Since the last update both of my PRs I mentioned have landed, allowing for constructing ADTs in const arguments while making use of generic parameters. This makes MGCA effectively a "full" prototype where it can now fully demonstrate the core concept of the feature. There's still a lot of work left to do but now we're at the point of finishing out the feature :)

Once again huge thanks to camelid for sticking with me throughout this. Also thanks to errs, oli and lcnr for reviewing some of the work and chatting with me about possible impl decisions.

Some examples of what is possible with MGCA as of the end of this goal cycle:

#![allow(unused)]
#![feature(const_default, const_trait_impl, min_generic_const_args)]

fn main() {
trait Trait {
    #[type_const]
    const ASSOC: usize;
}

fn mk_array<T: const Default + Trait>() -> [T; T::ASSOC] {
    [const { T::default() }; _]
}
}
#![allow(unused)]
#![feature(adt_const_params, min_generic_const_args)]

fn main() {
fn foo<const N: Option<u32>>() {}

trait Trait {
    #[type_const]
    const ASSOC: usize;
}

fn bar<T: Trait, const N: u32>() {
    // the initializer of `_0` is a `N` which is a legal const argument
    // so this is ok.
    foo::<{ Some::<u32> { 0: N } }>();

    // this is allowed as mgca supports uses of assoc consts in the
    // type system. ie `<T as Trait>::ASSOC` is a legal const argument
    foo::<{ Some::<u32> { 0: <T as Trait>::ASSOC } }>();

    // this on the other hand is not allowed as `N + 1` is not a legal
    // const argument
    foo::<{ Some::<u32> { 0: N + 1 } }>(); // ERROR
}
}

As for adt_const_params we now have a zulip stream specifically for discussion of the upcoming RFC and the drafting of the RFC: #project-const-generics/adt_const_params-rfc. I've gotten part of the way through actually writing the RFC itself though it's gone slower than I had originally hoped as I've also been spending more time thinking through the implications of allowing private data in const generics.

I've debugged the remaining two ICEs making adt_const_params not fully ready for stabilization and written some brief instructions on how to resolve them. One ICE has been incidentally fixed (though more masked) by some work that Kivooeo has been doing on MGCA. The other has been picked up by someone I'm not sure the github handle of so that will also be getting fixed soon.

Comment by [Boxy][] posted on 2025-12-30:

Ah I forgot to mention, even though MGCA has a tonne of work left to do I expect it should be somewhat approachable for people to help out with. So if people are interested in getting involved now is a good time :)

Comment by [Boxy][] posted on 2025-12-30:

Ah another thing I forgot to mention. David Wood spent some time looking into the name mangling scheme for adt_const_params stuff to make sure it would be fine to stabilize and it seems it is so that's another step closer to adt_const_params being stabilizable

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

1 detailed update available.

Comment by [Frank King][] posted on 2025-12-18:
Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

No detailed updates available.
Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

5 detailed updates available.

Comment by [Benno Lossin][] posted on 2025-12-07:

Since we have chosen virtual places as the new approach, we reviewed what open questions are most pressing for the design. Our discussion resulted in the following five questions:

  1. Should we have 1-level projections xor multi-level projections?
  2. What is the semantic meaning of the borrow checker rules (BorrowKind)?
  3. How should we add "canonical projections" for types such that we have nice and short syntax (like x~y or x.@y)?
  4. What to do about non-indirected containers (Cell, MaybeUninit, Mutex, etc)?
  5. How does one inspect/query Projection types?

We will focus on these questions in December as well as implementing FRTs.

Comment by [Benno Lossin][] posted on 2025-12-12:

Canonical Projections

We have discussed canonical projections and come up with the following solution:

#![allow(unused)]
fn main() {
pub trait CanonicalReborrow: HasPlace {
    type Output<'a, P: Projection<Source = Self::Target>>: HasPlace<Target = P::Target>
    where
        Self: PlaceBorrow<'a, P, Self::Output<'a, P>>;
}
}

Implementing this trait permits using the syntax @$place_expr where the place's origin is of the type Self (for example @x.y where x: Self and y is an identifier or tuple index, or @x.y.z etc). It is desugared to be:

#![allow(unused)]
fn main() {
@<<Self as CanonicalReborrow>::Output<'_, projection_from_place_expr!($place_expr)>> $place_expr
}

(The names of the trait, associated type and syntax are not final, better suggestions welcome.)

Reasoning

  • We need the Output associated type to support the @x.y syntax for Arc and ArcRef.
  • We put the FRT and lifetime parameter on Output in order to force implementers to always provide a canonical reborrow, so if @x.a works, then @x.b also works (when b also is a field of the struct contained by x).
    • This (sadly or luckily) also has the effect that making @x.a and @x.b return different wrapper types is more difficult to implement and requires a fair bit of trait dancing. We should think about discouraging this in the documentation.
Comment by [Benno Lossin][] posted on 2025-12-16:

Non-Indirected Containers

Types like MaybeUninit<T>, Cell<T>, ManuallyDrop<T>, RefCell<T> etc. currently do not fit into our virtual places model, since they don't have an indirection. They contain the place directly inline (and some are even repr(transparent)). For this reason, we currently don't have projections available for &mut MaybeUninit<T>.

Enter our new trait PlaceWrapper which these types implement in order to make projections available for them. We call these types place wrappers. Here is the definition of the trait:

#![allow(unused)]
fn main() {
pub unsafe trait PlaceWrapper<P: Projection<Source = Self::Target>>: HasPlace {
    type WrappedProjection: Projection<Source = Self>;

    fn wrap_projection(p: P) -> Self::WrappedProjection;
}
}

This trait should only be implemented when Self doesn't contain the place as an indirection (so for example Box must not implement the trait). When this trait is implemented, then Self has "virtual fields" available (actually all kinds of place projections). The name of these virtual fields/projections is the same as the ones of the contained place. But their output type is controlled by this trait.

As an example, here is the implementation for MaybeUninit:

#![allow(unused)]
fn main() {
impl<T, P: Projection<Source = T>> PlaceWrapper<P> for MaybeUninit<T> {
    type WrappedProjection = TransparentProjection<P, MaybeUninit<T>, MaybeUninit<P::Target>>;

    fn wrap_projection(p: P) -> Self::WrappedProjection {
        TransparentProjection(p, PhantomData, PhantomData)
    }
}
}

Where TransparentProjection will be available in the standard library defined as:

#![allow(unused)]
fn main() {
pub struct TransparentProjection<P, Src, Tgt>(P, PhantomData<Src>, PhantomData<Tgt>);

impl<P: Projection, Src, Tgt> Projection for TransparentProjection<P, Src, Tgt> {
    type Source = Src;
    type Target = Tgt;

    fn offset(&self) -> usize {
        self.0.offset()
    }
}
}

When there is ambiguity, because the wrapper and the wrapped types both have the same field, the wrapper's field takes precedence (this is the same as it currently works for Deref). It is still possible to refer to the wrapped field by first dereferencing the container, so x.field refers to the wrapper's field and (*x).field refers to the field of the wrapped type.

Comment by [Benno Lossin][] posted on 2025-12-20:

Field-by-Field Projections vs One-Shot Projections

We have used several different names for these two ways of implementing projections. The first is also called 1-level projections and the second multi-level projections.

The field-by-field approach uses field representing types (FRTs), which represent a single field of a struct with no indirection. When writing something like @x.y.z, we perform the place operation twice, first using the FRT field_of!(X, y) and then again with field_of!(T, z) where T is the resulting type of the first projection.

The second approach called one-shot projections instead extends FRTs with projections, these are compositions of FRTs, can be empty and dynamic. Using these we desugar @x.y.z to a single place operation.

Field-by-field projections have the advantage that they simplify the implementation for users of the feature, the compiler implementation and the mental model that people will have to keep in mind when interacting with field projections. However, they also have pretty big downsides, which either are fundamental to their design or would require significant complification of the feature:

  • They have less expressiveness than one-shot projections. For example, when moving out a subsubfield of x: &own Struct by doing let a = @x.field.a, we have to move out field, which prevents us from later writing let b = @x.field.b. One-shot projections allow us to track individual subsubfields with the borrow checker.
  • Field-by-field projections also make it difficult to define type-changing projections in an inference friendly way. Projecting through multiple fields could result in several changes of types in between, so we would have to require only canonical projections in certain places. However, this requires certain intermediate types for which defining their safety invariants is very complex.

We additionally note that the single function call desugaring is also a simplification that also lends itself much better when explaining what the @ syntax does.

All of this points in the direction of proceeding with one-shot projections and we will most likely do that. However, we must note that the field-by-field approach might yield easier trait definitions that make implementing the various place operations more manageable. There are several open issues on how to design the field-by-field API in the place variation (the previous proposal did have this mapped out clearly, but it does not translate very well to places), which would require significant effort to solve. So at this point we cannot really give a fair comparison. Our initial scouting of the solutions revealed that they all have some sort of limitation (as we explained above for intermediate projection types for example), which make field-by-field projections less desirable. So for the moment, we are set on one-shot projections, but when the time comes to write the RFC we need to revisit the idea of field-by-field projections.

Comment by [Benno Lossin][] posted on 2025-12-25:

Wiki Project

We started a wiki project at https://rust-lang.github.io/beyond-refs to map out the solution space. We intend to grow it into the single source of truth for the current state of the field projection proposal as well as unfinished and obsolete ideas and connections between them. Additionally, we will aim to add the same kind of information for the in-place initialization effort, since it has overlap with field projections and, more importantly, has a similarly large solution space.

In the beginning you might find many stub pages in the wiki, which we will work on making more complete. We will also mark pages that contain old or abandoned ideas as such as well as mark the current proposal.

This issue will continue to receive regular detailed updates, which are designed for those keeping reasonably up-to-date with the feature. For anyone out of the loop, the wiki project will be a much better place when it contains more content.

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

1 detailed update available.

Comment by [Pete LeVasseur][] posted on 2025-12-16:

Meeting notes here: FLS team meeting 2025-12-12

Key developments: We're close to completing the FLS release for 1.91.0, 1.91.1. We've started to operate as a team, merging a PR with the changelog entries, then opening up issues for each change required: ✅ #624(https://github.com/rust-lang/fls/issues/624), ✅ #625(https://github.com/rust-lang/fls/issues/625), ✅ #626(https://github.com/rust-lang/fls/issues/626), ⚠️ #623(https://github.com/rust-lang/fls/issues/623). #623(https://github.com/rust-lang/fls/issues/623) is still pending, as it requires a bit of alignment with the Reference on definitions and creation of a new example. Blockers: None currently Help wanted: We'd love more folks from the safety-critical community to contribute to picking up issues or opening an issue if you notice something is missing.

Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

1 detailed update available.

Comment by [Ian McCormack][] posted on 2025-12-16:

Here's our December status update!

  • We have revised our prototype of the pre-RFC based on Ralf Jung's feedback. Now, instead of having two different retag functions for operands and places, we emit a single __rust_retag intrinsic in every situation. We also track interior mutability precisely. At this point, the implementation is mostly stable and seems to be ready for an MCP.

  • There's been some discussion here and in the pre-RFC about whether or not Rust will still have explicit MIR retag statements. We plan on revising our implementation so that we no longer rely on MIR retags to determine where to insert our lower-level retag calls. This should be a relatively straightforward change to the current prototype. If anything, it should make these changes easier to merge upstream, since they will no longer affect Miri.

  • BorrowSanitizer continues to gain new features, and we've started testing it on our first real crate (lru) (which has uncovered a few new bugs in our implementation). The two core Tree Borrows features that we have left to support are error reporting and garbage collection. Once these are finished, we will be able to expand our testing to more real-world libraries and confirm that we are passing each of Miri's test cases (and likely find more bugs lurking in our implementation). Our instrumentation pass ignores global and thread-local state for now, and it does not support atomic memory accesses outside of atomic load and store instructions. These operations should be relatively straightforward to add once we've finished higher-priority items.

  • Performance is slow. We do not know exactly how slow yet, since we've been focusing on feature support over benchmarking and optimization. This is at least partially due to the lack of garbage collection, based on what we're seeing from profiling. We will have a better sense of what our performance is like once we can compare against Miri on more real-world test cases.

As for what's next, we plan on posting an MCP soon, now that it's clear that we will be able to do without MIR retags. You can expect a more detailed status update on BorrowSanitizer by the end of January. This will discuss our implementation and plans for 2026. We will post that here and on our project website.

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

1 detailed update available.

Comment by [Taylor Cramer][] posted on 2025-12-17:

Current status:

  • The RFC for auto impl supertraits has been updated to address SemVer compatibility issues.
  • There is a parsing PR kicking off an experimental implementation. The tracking issue for this experimental implementation is here.
Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

1 detailed update available.

Comment by [Josh Triplett][] posted on 2025-12-17:

In addition to further ongoing work on reference material (some of which is on track to be merged), we've had some extensive discussions about reference processes, maintenance, and stability markers. Niko Matsakis is putting together a summary and proposal for next steps.

Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

No detailed updates available.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

2 detailed updates available.

Comment by [Manuel Drehwald][] posted on 2025-12-02:

It's only been two weeks, but we got a good number of updates, so I already wanted to share them.

autodiff

  1. On the autodiff side, we landed the support for rlib and better docs. This means that our autodiff frontend is "almost" complete, since there are almost no cases left where you can't apply autodiff. There are a few features like custom-derivatives or support for dyn arguments that I'd like to add, but they are currently waiting for better docs on the Enzyme side. There is also a long-term goal off replacing the fat-lto requirement with the less invasive embed-bc requirement, but this proved to be tricky in the past and only affects compile times.
  2. @sgasho picked up my old PR to dlopen enzyme, and found the culprit of it failing after my last rebase. A proper fix might take a bit longer, but it might be worth waiting for. As a reminder, using dlopen in the future allows us to ship autodiff on nightly without increasing the size of rustc and therefore without making our infra team sad.

All in all, we have landed most of the hard work here, so that's a very comfortable position to be in before enabling it on nightly.

offload

  1. We have landed the intrinsic implementation of Marcelo Domínguez, so now you can offload functions with almost arbitrary arguments. In my first prototype, I had limited it to pointers to 256 f64 values. The updated usage example continues to live here in our docs. As you can see, we still require #[cfg(target_os=X)] annotations. Under the hood, the LLVM-IR which we generate is also still a bit convoluted. In his next PRs, he'll clean up the generated IR, and introduce an offload macro that users shall call instead of the internal offload intrinsic.
  2. I spend more time on enabling offload in our CI, to enable std::offload in nightly. After multiple iterations and support from LLVM offload devs, we found a cmake config that does not run into bugs, should not increase Rust CI time too much, and works with both in-tree llvm/clang builds, as well as external clang's (the current case in our Rust CI).
  3. I spend more time on simplifying the usage instructions in the dev guide. We started with two cargo calls, one rustc call, two clang calls, and two clang-helper binary calls. I was able to remove the rustc and one of the clang-offload-packager calls, by directly calling the underlying LLVM APIs. I also have an unmerged PR which removes the two clang calls. Once I cleaned it up and landed it, we would be down to only two cargo calls and one binary call to clang-linker-wrapper. Once I automated this last wrapper (and enabled offload in CI), nightly users should be able to experiment with std::offload.
Comment by [Manuel Drehwald][] posted on 2025-12-26:

Time for the next round of updates. Again, most of the updates were on the GPU side, but with some notable autodiff improvements too.

autodiff:

  1. @sgasho finished his work on using dlopen to load enzyme and the pr landed. This allowed Jakub Beránek and me to start working on distributing Enzyme via a standalone component.

  2. As a first step, I added a nicer error if we fail to find or dlopen our Enzyme backend. I also removed most of our autodiff fallbacks, we now unconditionally enable our macro frontend on nightly: https://github.com/rust-lang/rust/pull/150133 You may notice that cargo expand now works on autodiff code. This also allowed the first bug reports about ICE (internal compiler error) in our macro parser logic.

  3. Kobzol opened a PR to build Enzyme in CI. In theory, I should have been able to download that artifact, put it into my sysroot, and use the latest nightly to automatically load it. If that had worked, we could have just merged his PR, and everyone could have started using AD on nightly. Of course, things are never that easy. Even though both Enzyme, LLVM, and rustc were built in CI, the LLVM version shipped along with rustc does not seem compatible with the LLVM version Enzyme was built against. We assume some slight cmake mismatch during our CI builds, which we will have to debug.

offload:

  1. On the gpu side, Marcelo Domínguez finished his cleanup PR, and along the way also fixed using multiple kernels within a single codebase. When developing the offload MVP I had taken a lot of inspiration from the LLVM-IR generated by clang - and it looks like I had gotten one of the (way too many) LLVM attributes wrong. That caused some metadata to be fused when multiple kernels are present, confusing our offload backend. We started to find more bugs when working on benchmarks, more about the fixes for those in the next update.

  2. I finished cleaning up my offload build PR, and Oliver Scherer reviewed and approved it. Once the dev-guide gets synced, you should see much simpler usage instructions. Now it's just up to me to automate the last part, then you can compile offload code purely with cargo or rustc. I also improved how we build offload, which allows us to build it both in CI and locally. CI had some very specific requirements to not increase build times, since our x86-64-dist runner is already quite slow.

  3. Our first benchmarks directly linked against NVIDIA and AMD intrinsics on llvm-ir level. However, we already had an nvptx Rust module for a while, and since recently also an amdgpu module which nicely wraps those intrinsics. I just synced the stdarch repository into rustc a few minutes ago, so from now on, we can replace both with the corresponding Rust functions. In the near future we should get a higher level GPU module, which abstracts away naming differences between vendors.

  4. Most of my past rustc contributions were related to LLVM projects or plugins (Offload and Enzyme), and I increasingly encountered myself asking other people for updates or backports of our LLVM submodule, since upstream LLVM has fixes which were not yet merged into our LLVM submodule. Our llvm working group is quite small and I didn't want to burden them too much with my requests, so I recently asked them to join it, which also got approved. In the future I intend to help a little with the maintenance here.

Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

1 detailed update available.

Comment by [Tomas Sedovic][] posted on 2025-12-05:

Update from the 2025-12-03 meeting:

-Zharden-sls

Wesley reviewed it again, provided a qualification, more changes requested.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

2 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2025-12-05:

Update from the 2025-12-03 meeting.

Deref / Receiver

Ding keeps working on the Reference draft. The idea is still not well-proliferated and people are not convinced this is a good way to go. We hope the method-probing section in Reference PR could clear thins up.

We're keeping the supertrait auto-impl experiment as an alternative.

RFC #3851: Supertrait Auto-impl

Ding addressed Predrag's requests on SemVer compatibility. He's also opened an implementation PR: https://github.com/rust-lang/rust/pull/149335. Here's the tracking issue: https://github.com/rust-lang/rust/issues/149556.

derive(CoercePointee)

Ding opened a PR to require additional checks for DispatchFromDyn: https://github.com/rust-lang/rust/pull/149068

In-place initialization

Ding will prepare material for a discussion at the LPC (Linux Plumbers Conference). We're looking to hear feedback on the end-user syntax for it.

The feature is going quite large, Ding will check with Tyler on the whether this might need a series of RFCs.

The various proposals on the table continue being discussed and there are signs (albeit slow) of convergence. The placing function and guaranteed return ones are superseded by outpointer. The more ergonomic ideas can be built on top. The guaranteed value placement one would be valuable in the compiler regardless and we're waiting for Olivier to refine it.

The feeling is that we've now clarified the constraints that the proposals must operate under.

Field projections

Nadri's Custom places proposal is looking good at least for the user-facing bits, but the whole thing is growing into a large undertaking. Benno's been focused on academic work that's getting wrapped up soon. The two will sync afterwards.

Comment by [Tomas Sedovic][] posted on 2025-12-18:

Quick bit of great news: Rust in the Linux kernel is no longer treated as an experiment, it's here to stay 🎉

https://lwn.net/SubscriberLink/1050174/63aa7da43214c3ce/

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

3 detailed updates available.

Comment by @sladyn98 posted on 2025-12-03:

Ed Page hey i would like to contribute to this I reached out on zulip. Bumping up the post in case it might have gone under the radar

CC Niko Matsakis

Comment by [Ed Page][] posted on 2025-12-03:

The work is more on the compiler side atm, so Eric Holk and b-naber could speak more to where they could use help.

Comment by [Eric Holk][] posted on 2025-12-06:

Hi @sladyn98 - feel free to ping me on Zulip about this.

In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

No detailed updates available.
MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

1 detailed update available.

Comment by [Amanieu d'Antras][] posted on 2025-12-17:

The RFC draft was reviewed in detail and Ralf Jung pointed out that the proposed semantics introduce issues because they rely on "no-behavior" (NB) with regards to choosing an address for a local. This can lead to surprising "time-traveling" behavior where the set of possible addresses that a local may have (and whether 2 locals can have the same address) depends on information from the future. For example:

#![allow(unused)]
fn main() {
// This program has DB
let x = String::new();
let xaddr = &raw const x;
let y = x; // Move out of x and de-initialize it.
let yaddr = &raw const y;
x = String::new(); // assuming this does not change the address of x
// x and y are both live here. Therefore, they can't have the same address.
assume(xaddr != yaddr);
drop(x);
drop(y);
}
#![allow(unused)]
fn main() {
// This program has UB
let x = String::new();
let xaddr = &raw const x;
let y = x; // Move out of x and de-initialize it.
let yaddr = &raw const y;
// So far, there has been no constraint that would force the addresses to be different.
// Therefore we can demonically choose them to be the same. Therefore, this is UB.
assume(xaddr != yaddr);
// If the addresses are the same, this next line triggers NB. But actually this next
// line is unreachable in that case because we already got UB above...
x = String::new();
// x and y are both live here.
drop(x);
drop(y);
}

With that said, there is still a possibility of achieving the optimization, but the scope will need to be scaled down a bit. Specifically, we would need to:

  • no longer perform a "partial free"/"partial allocation" when initializing or moving out of a single field of a struct. The lifetime of a local starts when any part of it is initialized and ends when it is fully moved out.
  • allow a local's address to change when it is re-initialized after having been fully moved out, which eliminates the need for NB.

This reduces the optimization opportunities since we can't merge arbitrary sub-field moves, but it still allows for eliminating moves when constructing a struct from multiple values.

The next step is for me to rework the RFC draft to reflect this.

Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

1 detailed update available.

Comment by [lcnr][] posted on 2025-12-15:

We've continued to fix a bunch of smaller issues over the last month. Tim (Theemathas Chirananthavat) helped uncover a new potential issue due to non-fatal overflow which we'll have to consider before stabilizing the new solver: https://github.com/rust-lang/trait-system-refactor-initiative/issues/258.

I fixed two issues myself in https://github.com/rust-lang/rust/pull/148823 and https://github.com/rust-lang/rust/pull/148865.

tiif with help by Boxy fixed query cycles when evaluating constants in where-clauses: https://github.com/rust-lang/rust/pull/148698.

adwin fixed a subtle issues involving coroutine witnesses in https://github.com/rust-lang/rust/pull/149167 after having diagnosed the underlying issue there last month. They've also fixed a smaller diagnostics issue in https://github.com/rust-lang/rust/pull/149299. Finally, they've also fixed an edge case of impl well-formedness checking in https://github.com/rust-lang/rust/pull/149345.

Shoyu Vanilla fixed a broken interaction of aliases and fudging in https://github.com/rust-lang/rust/pull/149320. Looking into fudging and HIR typeck Expectation handling also uncovered a bunch of broken edge-cases and I've openedhttps://github.com/rust-lang/rust/issues/149379 to track these separately.

I have recently spent some time thinking about the remaining necessary work and posted a write-up on my personal blog: https://lcnr.de/blog/2025/12/01/next-solver-update.html. I am currently trying to get a clearer perspective on our cycle handling while slowly working towards an RFC for the changes there. This is challenging as we don't have a good theoretical foundation here yet.

Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

1 detailed update available.

Comment by [Folkert de Vries][] posted on 2025-12-01:

We did not receive the funding we needed to work on this goal, so no progress has been made.

Overall I think the improvements we felt comfortable promising are on the low side. Overall the amount of time spent in codegen for realistic changes to real code bases was smaller than expected, meaning that the improvements that cranelift can deliver for the end-user experience are smaller.

We still believe larger gains can be made with more effort, but did not feel confident in promising hard numbers.

So for now, let's close this.

Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

2 detailed updates available.

Comment by [Weihang Lo][] posted on 2025-12-13:

Key developments: HTML replay logic has merge. Once it gets into nightly cargo report timings can open the timing report you have previously logged.

  • https://github.com/rust-lang/cargo/pull/16377
  • https://github.com/rust-lang/cargo/pull/16378
  • https://github.com/rust-lang/cargo/pull/16382

Blockers: No, except my own availability

Help wanted: Same as https://github.com/rust-lang/rust-project-goals/issues/398#issuecomment-3571897575

Comment by [Weihang Lo][] posted on 2025-12-26:

Key developments:

Headline: You should always enable build analysis locally, if you are using nightly and want the timing info data always available.

[unstable]
build-analysis = true

[build.analysis]
enabled = true
  • More log events are emitted: https://github.com/rust-lang/cargo/pull/16390
    • dependency resolution time
    • unit-graph construction
    • unit-registration (which contain unit metadata)
  • Timing replay from cargo report timings now has almost the same feature parity as cargo build --timings, except CPU usage: https://github.com/rust-lang/cargo/pull/16414
  • Rename rebuild event to unit-fingerprint, and is emitted also for fresh unit: https://github.com/rust-lang/cargo/pull/16408.
  • Proposed a new cargo report sessions command so that people can retrieve previous sessions IDs not use the latest one: https://github.com/rust-lang/cargo/pull/16428
  • Proposed to remove --timings=json which timing info in log files should be a great replacement: https://github.com/rust-lang/cargo/pull/16420
  • Documenting efforts for having man pages for nested commands `cargo report : https://github.com/rust-lang/cargo/pull/16430 and https://github.com/rust-lang/cargo/pull/16432

Besides implementations, we also discussed about:

  • The interaction of --message-format and structured logging system, as well as log event schemas and formats: https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/build.20analysis.20log.20format/with/558294271
  • A better name for RunId. We may lean towards SessionId which is a common name for logging/tracing ecosystem.
  • Nested Cargo calls to have a sticky session ID. At least a way to show they were invoked from the same top-level Cargo call.

Blockers: No, except my own availability

Help wanted: Same as https://github.com/rust-lang/rust-project-goals/issues/398#issuecomment-3571897575

Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

1 detailed update available.

Comment by [Aapo Alasuutari][] posted on 2025-12-17:

Purpose

A refresher on what we want to achieve here: the most basic form of reborrowing we want to enable is this:

#![allow(unused)]
fn main() {
// Note: not Clone or Copy
#[derive(Reborrow)]
struct MyMutMarker<'a>(...);

// ...

let marker: MyMarkerMut = MyMutMarker::new();
some_call(marker);
some_call(marker);
}

ie. make it possible for an owned value to be passed into a call twice and have Rust inject a reborrow at each call site to produce a new bitwise copy of the original value for the passing purposes, and mark the original value as disabled for reads and writes for the duration of the borrow.

A notable complication appears with implementing such reborrowing in userland using explicit cals when dealing with returned values:

#![allow(unused)]
fn main() {
return some_call(marker.reborrow());
}

If the borrowed lifetime escapes through the return value, then this will not compile as the borrowed lifetime is based on a value local to this function. Alongside convenience, this is the major reason for the Reborrow traits work.

CoerceShared is a secondary trait that enables equivalent reborrowing that only disables the original value for writes, ie. matching the &mut T to &T coercion.

Update

We have the Reborrow trait working, albeit currently with a bug in which the marker must be bound as let mut. We are working towards a working CoerceShared trait in the following form:

#![allow(unused)]
fn main() {
trait CoerceShared<Target: Copy> {}
}

Originally the trait had a type Target ADT but this turned out to be unnecessary, as there is no reason to particularly disallow multiple coercion targets. The original reason for using an ADT to disallow multiple coercion targets was based on the trait also having an unsafe method, at which point unscrupulous users could use the trait as a generic coercion trait. Because the trait method was found to be unnecessary, the fear is also unnecessary.

This means that the trait has better chances of working with multiple coercing lifetimes (think a collection of &muts all coercing to &s, or only some of them). However, we are currently avoiding any support of multiple lifetimes as we want to avoid dealing with rmeta before we have the basic functionality working.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

1 detailed update available.

Comment by [Oliver Scherer][] posted on 2025-12-15:

Updates

  • https://github.com/rust-lang/rust/pull/148820 adds a way to mark functions and intrinsics as only callable during CTFE
  • https://github.com/rust-lang/rust/pull/144363 has been unblocked and just needs some minor cosmetic work

Blockers

  • https://github.com/rust-lang/rust/pull/146923 (reflection MVP) has not been reviewed yet
Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

No detailed updates available.
Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

1 detailed update available.

Comment by [Ross Sullivan][] posted on 2025-12-23:

Status update December 23, 2025

The majority of December was spent iterating on https://github.com/rust-lang/cargo/pull/16155 . As mentioned in the previous update, the original locking design was not correct and we have been working through other solutions.

As locking is tricky to get right and there are many scenarios Cargo needs to support, we are trying to descope the initial implementation to an MVP, even if that means we lose some of the concurrency. Once we have an MVP on nightly, we can start gathering feedback on the scenarios that need improvement and iterate.

I'm hopeful that we get an unstable -Zfine-grain-locking on nightly in January for folks to try out in their workflows.


Also we are considering adding an opt-in for the new build-dir layout using an env var (CARGO_BUILD_DIR_LAYOUT_V2=true) to allow tool authors to begin migrating to the new layout. https://github.com/rust-lang/cargo/pull/16336

Before stabilizing this, we are doing crater run to test the impact of the changes and proactively reaching out to projects to minimize breakage as much as possible. https://github.com/rust-lang/rust/pull/149852

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

No detailed updates available.
Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

1 detailed update available.

Comment by [Jakob Koschel][] posted on 2025-12-15:

Based on the gathered feedback I opened a new MCP for the proposed new Tier 2 targets with sanitizers enabled. (https://github.com/rust-lang/compiler-team/issues/951)

Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

No detailed updates available.
rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

1 detailed update available.

Comment by [Jakub Beránek][] posted on 2025-12-15:

We have enabled the second x64 machine, so we now have benchmarks running in parallel 🎉 There are some smaller things to improve, but next year we can move onto running benchmarks on Arm collectors.

Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

2 detailed updates available.

Comment by [Rémy Rakic][] posted on 2025-12-30:

This month's key developments were:

  • borrowck support in a-mir-formality has been progressing steadily — it has its own dedicated updates in https://github.com/rust-lang/rust-project-goals/issues/122 for more details
  • we were also able to find a suitable project for the master's student project on a-mir-formality (and they accepted and should start around February) and which will help expand our testing coverage for the polonius alpha as well.
  • tiif has kept making progress on fixing opaque type soundness issue https://github.com/rust-lang/trait-system-refactor-initiative/issues/159. It is the one remaining blocker for passing all tests. By itself it will not immediately fix the two remaining (soundness) issues with opaque type region liveness, but we'll able to use the same supporting code to ensure the regions are indeed live where they need to be.
  • I quickly cleaned up some inefficiencies in constraint conversion, it hasn't landed yet but it maybe won't need to because of the next item
  • but most of the time this month was spent on this final item: we have the first interesting results from the rewriting effort. After a handful of wrong starts, I have a branch almost ready to switch the constraint graph to be lazy and computed during traversal. It removes the need to index the numerous list of constraints, or to convert liveness data to a different shape. It thus greatly reduces the current alpha overhead (some rare cases look faster than NLLs but I don't yet know why, maybe due to being able to better use the sparseness, low connectivity of the constraint graph, and a small number of loans). The overhead wasn't entirely removed of course: the worst offending benchmark has a +5% wall-time regression, but icounts are worse looking (+13%). This was also only benchmarking the algorithm itself, without the improvements to the rest of borrowck mentioned in previous updates. I should be able to open a PR in the next couple days, once I figure out how to best convert the polonius mermaid graph dump to the new lazy localized constraint generation.
  • and finally, happy holidays everyone!
Comment by [Rémy Rakic][] posted on 2025-12-31:
  • I should be able to open a PR in the next couple days

done in https://github.com/rust-lang/rust/pull/150551

Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-12-15:

Key developments

  • A fence length limit was added in response to T-lang feedback (https://github.com/rust-lang/rust/pull/149358)
  • Whether to disallow or lint for CR inside of a frontmatter is under discussion (https://github.com/rust-lang/rust/pull/149823)

Blockers

  • https://github.com/rust-lang/rust/pull/146377
  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-12-17:

Opened stabilization PR but we have blockers I didn't hear of, so stabilization will be postponed until then.

SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

3 detailed updates available.

Comment by [David Wood][] posted on 2025-12-15:

I haven't made any progress on Deref::Target yet, but I have been focusing on landing rust-lang/rust#143924 which has went through two rounds of review and will hopefully be approved soon.

Comment by [Niko Matsakis][] posted on 2025-12-18:

Update: David and I chatted on Zulip. Key points:

David has made "progress on the non-Sized Hierarchy part of the goal, the infrastructure for defining scalable vector types has been merged (with them being Sized in the interim) and that'll make it easier to iterate on those and find issues that need solving".

On the Sized hierarchy part of the goal, no progress. We discussed options for migrating. There seem to be three big options:

(A) The conservative-but-obvious route where the T: Derefin the old edition is expanded to T: Deref<Target: SizeOfVal> (but in the new edition it means T: Deref<Target: Pointee>, i.e., no additional bounds). The main downside is that new Edition code using T: Deref can't call old Edition code using T: Deref as the old edition code has stronger bounds. Therefore new edition code must either use stronger bounds than it needs or wait until that old edition code has been updated.

(B) You do something smart with Edition.Old code where you figure out if the bound can be loose or strict by bottom-up computation. So T: Deref in the old could mean either T: Deref<Target: Pointee> or T: Deref<Target: SizeOfVal>, depending on what the function actually does.

(C) You make Edition.Old code always mean T: Deref<Target: Pointee> and you still allow calls to size_of_val but have them cause post-monomorphization errors if used inappropriately. In Edition.New you use stricter checking.

Options (B) and (C) have the downside that changes to the function body (adding a call to size_of_val, specifically) in the old edition can stop callers from compiling. In the case of Option (B), that breakage is at type-check time, because it can change the where-clauses. In Option (C), the breakage is post-monomorphization.

Option (A) has the disadvantage that it takes longer for the new bounds to roll out.

Given this, (A) seems the preferred path. We discussed options for how to encourage that roll-out. We discussed the idea of a lint that would warn Edition.Old code that its bounds are stronger than needed and suggest rewriting to T: Deref<Target: Pointee> to explicitly disable the stronger Edition.Old default. This lint could be implemented in one of two ways

  • at type-check time, by tracking what parts of the environment are used by the trait solver. This may be feasible in the new trait solver, someone from @rust-lang/types would have to say.
  • at post-mono time, by tracking which functions actually call size_of_val and propagating that information back to callers. You could then compare against the generic bounds declared on the caller.

The former is more useful (knowing what parts of the environment are necessary could be useful for more things, e.g., better caching); the latter may be easier or more precise.

Comment by [Niko Matsakis][] posted on 2025-12-19:

Update to the previous post.

Tyler Mandry pointed me at this thread, where lcnr posted this nice blog post that he wrote detailing more about (C).

Key insights:

  • Because the use of size_of_val would still cause post-mono errors when invoked on types that are not SizeOfVal, you know that adding SizeOfVal into the function's where-clause bounds is not a breaking change, even though adding a where clause is a breaking change more generally.
  • But, to David Wood's point, it does mean that there is a change to Rust's semver rules: adding size_of_val would become a breaking change, where it is not today.

This may well be the best option though, particularly as it allows us to make changes to the defaults across-the-board. A change to Rust's semver rules is not a breaking change in the usual sense. It is a notable shift.

Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

1 detailed update available.

Comment by [Boxy][] posted on 2025-12-30:

This month I've written some documentation for how Const Generics is implemented in the compiler. This mostly covers the implementation of the stable functionality as the unstable features are quite in flux right now. These docs can be found here: https://rustc-dev-guide.rust-lang.org/const-generics.html

Progress
Point of contact

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

November Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-11-21:

Done in https://github.com/rust-lang/rust-forge/pull/852.

Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

3 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-11-05:

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.

Comment by [Niko Matsakis][] posted on 2025-11-12:

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.

Comment by [Niko Matsakis][] posted on 2025-11-19:

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

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

1 detailed update available.

Comment by [David Wood][] posted on 2025-11-22:

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.

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

1 detailed update available.

Comment by [Jon Bauman][] posted on 2025-11-26:

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.

Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

2 detailed updates available.

Comment by [Boxy][] posted on 2025-11-05:

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.

Comment by [Boxy][] posted on 2025-11-29:

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.

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

1 detailed update available.

Comment by [Frank King][] posted on 2025-11-21:

Status update:

Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

2 detailed updates available.

Comment by [Predrag Gruevski][] posted on 2025-11-02:

Status update as of November 1

Key developments:

  • Draft PR for exposing implied bounds in rustdoc JSON: https://github.com/rust-lang/rust/pull/148379
  • A concrete plan for how that new info turns into dozens of new lints covering many kinds of bounds

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.

Comment by [Predrag Gruevski][] posted on 2025-11-23:

Google Summer of Code 2025 is complete + finally some movement on cross-crate linting! 🚀

Key developments

  • Two students had a successful conclusion of Google Summer of Code working on cargo-semver-checksfind more details here!
  • rustdoc JSON now includes rlib information, following the design for cross-crate rustdoc JSON info created at RustWeek 2025: https://github.com/rust-lang/rust/pull/149043
  • A cargo issue was discovered that prevents this rlib info from being used; it's currently being triaged: https://github.com/rust-lang/cargo/issues/16291
  • Once that's resolved, we'll have enough here for a basic prototype. Getting features right in dependencies will likely require more work due to having many more cargo-related edge cases.
Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

TL;DR.
  • 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.

Comment by [Benno Lossin][] posted on 2025-11-01:

Moving Projections and &own

Moving 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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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:

  1. Add a ProjectMoveBack trait that declares an operation which accepts a value that is moved back into the projected one, or
  2. Add &own references.

Until now, we have explored the second option, because there are lot's of other applications for &own.

&own References

A 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.

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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 pinning

To 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:

#![allow(unused)]
fn main() {
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:

  • we can't have &'static own T pointing to non-static values (for example coming from a Box::leak_owned function).
  • field projections complicate things: if we project to a field, then we could possibly forget one field, but drop another
    • solution: just store drop flags not only for the whole struct, but also all transitive fields that implement Drop
  • there is different behavior between &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));
}
DerefMove

The 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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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:

#![allow(unused)]
fn main() {
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.

Comment by [Benno Lossin][] posted on 2025-11-02:

Having a single Project trait

The 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:

#![allow(unused)]
fn main() {
#[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 extendible (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).

Comment by [Benno Lossin][] posted on 2025-11-06:

A new Perspective: Projections via Places

[@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:

  • instead of the 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.
  • we can allow custom smart pointer reborrowing possibly using the syntax @MySmartPtr <place-expr>
  • we need multi-projections to allow simultaneous existence of &mut x.field.a and &mut x.field.b

We still have many things to flesh out in this proposal (some of these pointed out by [@Nadrieril][]):

  • how do FRTs still fit into the equation? And what are the types implementing the Projection trait?
  • What do we do about non-indirected place containers like MaybeUninit<T>, UnsafeCell<T> and ManuallyDrop<T>?
  • does BorrowKind work as a model for the borrow checker?
  • how do we make match ergonomics work nicely?
  • how do we get around the orphan rule limitations?
  • several smaller issues/questions...

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!

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

2 detailed updates available.

Comment by [Pete LeVasseur][] posted on 2025-11-05:

Meeting minutes from meeting held on 2025-10-31 (thank you to Tomas Sedovic 🥰)

Top-level:

  • Keep high quality bar, merge small, well-vetted changes when possible
  • Need concentrated effort to get the 1.90 FLS updates merged
  • Once 1.90 merged, we attempt first go as a team at 1.91

Discussion:

  • Suggest that everyone read the Glossary as a starting point
  • How to best triage / handle incoming issues?
Comment by [Pete LeVasseur][] posted on 2025-11-21:

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.

Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

1 detailed update available.

Comment by [Ian McCormack][] posted on 2025-11-11:

We've posted a pre-RFC for feedback, and we'll continue updating and expanding the draft here. This reflects most of the current state of the implementation, aside from tracking interior mutability precisely, which is still TBD but is described in the RFC.

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

2 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-11-05:

Three new blog posts:

The most important conclusions from those posts are

  • Explicit capture clauses would be useful, I proposed one specific syntax but bikeshedding will be required. To be "ergonomic" we need the ability to refer to full places, e.g., move(cx.foo.clone()) || use(cx.foo).
  • We should consider 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".
  • We should look for solutions that apply well to clone and alias so that higher-level Rust gets the ergonomic benefits even when cloning "heavier-weight" types to which Alias does not apply.
Comment by [Niko Matsakis][] posted on 2025-11-12:

New blog post:

  • https://smallcultfollowing.com/babysteps/blog/2025/11/10/just-call-clone/

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.

Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

No detailed updates available.
Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

1 detailed update available.

Comment by [Josh Triplett][] posted on 2025-11-12:

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").

Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-11-21:

Key developments:

  • libtest2:
    • #[test] macro added
    • Support for should_panic
    • Support for ignore
    • Support for custom error types
    • compile-fail tests for macros

Blockers

  • None

Help wanted:

Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

1 detailed update available.

Comment by [Manuel Drehwald][] posted on 2025-11-19:

Automatic Differentiation

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.

  1. As part of my cleanup I went through old issues, and realized we now partly support rlib's! That's a huge improvement, because it means you can use autodiff not only in your 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.
  2. I started documentation improvements in https://github.com/rust-lang/rust/pull/149082 and https://github.com/rust-lang/rust/pull/148201, which should be visible on the website from tomorrow onwards. They are likely still not perfect, so please keep opening issues if you have questions.
  3. We now provide a helpful error message if a user forgets enabling lto=fat: https://github.com/rust-lang/rust/pull/148855
  4. After two months of work, @sgasho managed to add Rust CI to enzyme! Unfortunately, Enzyme devs broke and disabled it directly, so we'll need to talk about maintaining it as part of shipping Enzyme in nightly.

I have the following elements on my TODO list as part shipping AD on nightly

  1. Re-enable macOS build (probably easy)
  2. Talk with Enzyme Devs about maintenance
  3. Merge rlib support (under review)
  4. upstream ADbenchmarks from r-l/enzyme to r-l/r as codegen tests (easy)
  5. Write a block post/article for https://blog.rust-lang.org/inside-rust/

GPU offload

  1. The llvm dev talk about GPU programming went great, I got to talk to a lot of other developers in the area of llvm offload. I hope to use some of the gained knowledge soon. Concrete steps planned are the integration of libc-gpu for IO from kernels, as well as moving over my code from the OpenMP API to the slightly lower level liboffload API.
  2. We confirmed that our gpu offload prototype works on more hardware. By now we have the latest AMD APU generation covered, as well as an MI 250X and an RTX 4050. My own Laptop with a slightly older AMD Ryzen 7 PRO 7840U unfortunately turned out to be not supported by AMD drivers.
  3. The offload intrinsic PR by Marcelo Domínguez is now marked as ready, and I left my second round of review. Hopefully, we can land it soon!
  4. I spend some time trying to build and potentially ship the needed offload changes in nightly, unfortunately I still fail to build it in CI: https://github.com/rust-lang/rust/pull/148671.

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.

Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

2 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2025-11-19:

Update from the 2025-11-05 meeting.

-Zharden-sls / rust#136597

Wesley Wiser left a comment on the PR, Andr

-Zno-jump-tables / rust#145974

Merged, expected to ship in Rust 1.93. The Linux kernel added support for the new name for the option (-Cjump-tables=n).

Comment by [Tomas Sedovic][] posted on 2025-11-28:

Update form the 2025-11-19 meeting:

-Zharden-sls / rust#136597

Andrew addressed the comment and rebased the PR. It's waiting for a review again.

#![register_tool] / rust#66079

Tyler 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.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

2 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2025-11-19:

Update from the 2025-11-05 meeting.

Deref/Receiver

Ding 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.

Arbitrary Self Types and derive(CoercePointee) / tracking issue #44874

theemathas 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 .

RFC #3851: Supertrait Auto-impl

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

Field projections

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).

Inlining C code into Rust code

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.

Comment by [Tomas Sedovic][] posted on 2025-11-28:

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#112504

This 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.

Fix for imports_granularity is not respected for #[cfg]'d items / rustfmt#6666

Ding opened a PR to fix this: https://github.com/rust-lang/rustfmt/issues/6666

rustfmt trailing comma hack

Ding and Manish were talking about writing up a proper fix for the vertical layout that's currently being solved by the , //, hack

TypeId layout

This 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 / Receiver

Following TC's recommendation, Ding is drafting the Reference PR.

Arbitrary Self Types and 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

RFC #3848: Pass pointers to const in assembly

Merged!

In-place initialization

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.

Alice has been nominated and accepted as language-advisor. Fantastic news and congratulations!

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

No detailed updates available.
In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

1 detailed update available.

Comment by [Alice Ryhl][] posted on 2025-11-14:

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

MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

1 detailed update available.

Comment by [Amanieu d'Antras][] posted on 2025-11-15:

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.

Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

1 detailed update available.

Comment by [lcnr][] posted on 2025-11-13:

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 adwin for implementing these. adwin 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.

Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

No detailed updates available.
Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

2 detailed updates available.

Comment by [Weihang Lo][] posted on 2025-11-04:

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:

  • https://github.com/rust-lang/cargo/pull/16150
  • https://github.com/rust-lang/cargo/pull/16179

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.

Comment by [Weihang Lo][] posted on 2025-11-24:

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.

  • https://github.com/rust-lang/cargo/pull/16203
  • https://github.com/rust-lang/cargo/pull/16282

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

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

1 detailed update available.

Comment by [Aapo Alasuutari][] posted on 2025-11-11:

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.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

1 detailed update available.

Comment by [Niko Matsakis][] posted on 2025-11-12:

Another related PR:

https://github.com/rust-lang/rust/pull/148820

Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

1 detailed update available.

Comment by [Jane Lusby][] posted on 2025-11-21:

linking this here so people know why there hasn't been any progress on this project goal.

#t-compiler > 2025H2 Goal Review @ 💬

Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

1 detailed update available.

Comment by [Ross Sullivan][] posted on 2025-11-21:

Status update November 21, 2025

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.

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-11-19:

This project goal has been completed. I updated the first issue to reflect it. Closing the issue then.

Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

1 detailed update available.

Comment by [Jakob Koschel][] posted on 2025-11-21:

We've had a bunch of discussions and I opened a MCP (link, zulip).

I think the final sentiment was creating new targets for the few sanitizers and platforms that are critical. I'm in the process of prototyping something to get new feedback on it.

Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

1 detailed update available.

Comment by [Niko Matsakis][] posted on 2025-11-05:

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:

  • What you know (e.g., experience in other languages, how much experience with Rust)
  • What you are trying to do (e.g., application area)
  • Where you are trying to do it (e.g., country)

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).

rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

1 detailed update available.

Comment by [Jakub Beránek][] posted on 2025-11-19:

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.

Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

1 detailed update available.

Comment by [Rémy Rakic][] posted on 2025-11-25:

Key developments:

  • I prototyped building blocks to fix the liveness soundness issue, but this was deemed too brittle.
  • so we prepared a meeting for the types team to discuss the problem, and possible solutions.
  • it turns out the issue is related to another soundness issue for opaque types in the new trait solver, https://github.com/rust-lang/trait-system-refactor-initiative/issues/159, and that tiif is already working on. The same solution is needed for both issues: with the full implied bounds available for opaque types in liveness, we'll able to require all the regions outliving the opaque lower bound to be live, while ignoring the unrelated regions (that the hidden type cannot use anyway). There will be no relevant dead region through which loans flow, and code relying on unused lifetimes being dead (like a lot of ed2024 code with the default capture changes) will still compile
  • we prepared another types-team meeting to discuss polonius in general, and the alpha algorithm in particular, to share knowledge among the team. This will also be helpful to then on apply member constraints in a location-sensitive manner, since right now they're applied at the SCC level and we need to make sure these constraints with the choice regions are present in the localized subset graph.
  • niko and tiif have made a lot of progress on adding support for borrow checking in a-mir-formality, so I've also joined these meetings, since we'll also want to model the alpha.
  • I've looked into Prusti's Place Capability Graphs, and plan to see how to integrate the alpha there, and if possible with the fuzzing capabilities mentioned in the paper, with the usual goal to expand testing as we've mentioned many times
  • we also had some discussion for a possible masters' student project, and thought about different practical and theoretical topics
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-11-21:

Key developments

  • rust-lang/rust#148051

Blockers:

  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

No detailed updates available.
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

2 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-11-05:

Notes from our meeting today:

Syntax proposal: only keyword

We 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:

#![allow(unused)]
fn main() {
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:

  • A ^SizeOfVal sigil was appealing due to the semver analogy but rejected on the basis of it being cryptic and hard to google.
  • The idea of applying the keyword to the type parameter 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.

Transitioning target

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.

Supertrait bounds

We explored the implications of weakening supertrait bounds a bit, looking at this example

#![allow(unused)]
fn main() {
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.

Comment by [David Wood][] posted on 2025-11-22:

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.

Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

2 detailed updates available.

Comment by [Boxy][] posted on 2025-11-05:

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):

  • opaque types
    • non defining vs defining uses
    • member constraints (borrowck overlap)
    • checking item bounds
    • high level normalization/opaque type storage approach (new solver)
    • normalization incompleteness
    • method/function incompleteness
    • how does use<...> work
    • 'erased regions causes problems with outlives item bounds in liveness
    • consistency across defining scopes
    • RPITIT inference? does this have special stuff
    • capturing of bound vars in opaques under binders, Fn bounds are somewhat special in relation to this
    • opaques inheriting late bound function parameters
  • non opaque type, impl Trait
    • RPITIT in traits desugaring
    • impl Trait in bindings
    • APIT desugaring impl details
  • const generics
    • anonymous constants
    • ConstArgHasType
    • TSVs vs RVs and generally upstream doc from lang meeting to dev guide
    • deterministic CTFE requirement
  • HIR typeck
    • expectations (and how used incorrectly :3)
    • method lookup + assorted code cleanups
    • coercions
    • auto-deref/reborrows (in coercions/method selection)
    • closure signature inference
    • fudge_inference_if_ok :>
    • diverging block handling :3
    • fallback :3
  • MIR borrowck
    • MIR typeck
      • why do we want two typecks
      • region dependent goals in new solver (interaction with lack-of region uniquification)
    • overlaps with opaque types
    • compute region graph
    • closure requirements
    • borrowck proper
  • compare predicate entailment :>
    • param env jank
    • implied bounds handling
  • trait objects: recent FCPs :3
    • dyn compatibility soundness interactions (see coerce pointee/arbitrary self types stuff)
    • dyn compatibility for impl reasons (monomorphization)
    • projection bounds handling
    • args not required for wf
  • ty::Infer in ty overview
  • generalization
  • coroutines
    • deferred coroutine obligations
    • witness types?
    • why -Zhigher-ranked-assumptions exists
  • binders and universes existsA forallB A == B
    • build more of an intuition than current docs :thinking_face:
  • talk about hr implied bounds there/be more explicit/clear in https://rustc-dev-guide.rust-lang.org/traits/implied-bounds.html?highlight=implied#proving-implicit-implied-bounds
  • incompleteness
    • what is it
    • what kinds are OK (not entirely sure yet. small explanation and add a note)
  • trait solving
    • cycles
    • general overview of how trait solving works as a concept (probably with example and handwritten proof trees)
      • important: first go "prove stuff by recursively proving nested requirements", then later introduce candidates
      • clauses/predicates
    • running pending goals in a loop
    • what kinds of incompleteness (overlap with opaques)
    • builtin impls and how to add them
  • hir to ty lowering :>
    • itemctxt vs fnctxt behaviours
    • normalization in lowering
    • lowering should be lossy
    • idempotency(?)
    • cycles from param env construction
    • const generics jank about Self and no generic parameters allowed
  • well formedness checking + wf disambiguation page
  • normalization & aliases
    • be more clear about normalizing ambig aliases to infer vars :thinking_face:
    • normalize when equating infer vars with aliases (overlap with generalization?)
    • item bounds checking
    • interactions with implied bounds (overlap with implied bounds and hir ty lowering)
  • variance

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

Comment by [Boxy][] posted on 2025-11-29:

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

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

October Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

No detailed updates available.
Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

No detailed updates available.
Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

1 detailed update available.

Comment by [David Wood][] posted on 2025-10-31:

We've now opened our first batch of RFCs: rust-lang/rfcs#3873, rust-lang/rfcs#3874 and rust-lang/rfcs#3875

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

No detailed updates available.
Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

1 detailed update available.

Comment by [Niko Matsakis][] posted on 2025-10-22:

We had a design meeting on 2025-09-10, minutes available here, aiming at these questions:

There are a few concrete things I would like to get out of this meeting, listed sequentially in order of most to least important:

  1. Would you be comfortable stabilizing the initial ADTs-only extensions?
    • This would be properly RFC'd before stabilization, this ask is just a "vibe check".
  2. Are you interested in seeing Per-Value Rejection for enums with undesirable variants?
  3. How do you feel about the idea of Lossy Conversion as an approach in general, what about specifically for the References and Raw Pointers extensions?
  4. How do you feel about the idea of dropping the One Equality ideal in general, what about specifically for -0.0 vs +0.0, what about specifically for NaN values?

The vibe checks on the first one were as follows:

Vibe check

The main ask:

Would you be comfortable stabilizing the initial ADTs-only extensions?

(plus the other ones)

nikomatsakis

I am +1 on working incrementally and focusing first on ADTs. I am supportive of stabilization overall but I don't feel like we've "nailed" the way to talk or think about these things. So I guess my "vibe" is +1 but if this doc were turned into an RFC kind of "as is" I would probably wind up -1 on the RFC, I think more work is needed (in some sense, the question is, "what is the name of the opt-in trait and why is it named that"). This space is complex and I think we have to do better at helping people understand the fine-grained distinctions between runtime values, const-eval values, and type-safe values.

Niko: if we add some sort of derive of a trait name, how much value are we getting from the derive, what should the trait be named?

tmandry

I think we'll learn the most by stabilizing ADTs in a forward compatible way (including an opt-in) now. So +1 from me on the proposed design.

It's worth noting that this is a feature that interacts with many other features, and we will be considering extensions to the MVP for the foreseeable future. To some extent the lang team has committed to this already but we should know what we're signing ourselves up for.

scottmcm

scottmcm: concern over the private fields restriction (see question below), but otherwise for the top ask, yes happy to just do "simple" types (no floats, no cells, no references, etc).

TC

As Niko said, +1 on working incrementally, and I too am supportive overall.

As a vibe, per-value rejection seems fairly OK to me in that we decided to do value-based reasoning for other const checks. It occurs to me there's some parallel with that.

https://github.com/rust-lang/rust/pull/119044

As for the opt-in on types, I see the logic. I do have reservations about adding too many opt-ins to the language, and so I'm curious about whether this can be safely removed.

Regarding floats, I see the question on these as related to our decision about how to handle padding in structs. If it makes sense to normalize or otherwise treat -0.0 and +0.0 as the same, then it'd also make sense in my view to normalize or otherwise treat two structs with the same values but different padding (or where only one has initialized padding) as the same.

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

1 detailed update available.

Comment by [Frank King][] posted on 2025-10-22:

Status update:

Regarding the TODO list in the next 6 months, here is the current status:

Introduce &pin mut|const place borrowing syntax

  • [x] parsing: #135731(https://github.com/rust-lang/rust/pull/135731), merged.
  • [ ] lowering and borrowck: not started yet.

I've got some primitive ideas about borrowck, and I probably need to confirm with someone who is familiar with MIR/borrowck before starting to implement.

A pinned borrow consists two MIR statements:

  1. a borrow statement that creates the mutable reference,
  2. and an adt aggregate statement that put the mutable reference into the Pin struct.

I may have to add a new borrow kind so that pinned borrows can be recognized. Then traverse the dataflow graph to make sure that pinned places cannot been moved.

Pattern matching of &pin mut|const T types

In the past few months, I have struggled with the !Unpin stuffs (the original design sketch Alternative A), trying implementing it, refactoring, discussing on zulips, and was constantly confused; luckily, we have finally reached a new agreement of the Alternative B version.

  • [ ] #139751(https://github.com/rust-lang/rust/pull/139751) under review (reimplemented regarding Alternative B).

Support drop(&pin mut self) for structually pinned types

  • [ ] adding a new Drop::pin_drop(&pin mut self) method: draft PR #144537(https://github.com/rust-lang/rust/pull/144537)

Supporting both Drop::drop(&mut self) and Drop::drop(&pin mut self) seems to introduce method-overloading to Rust, which I think might need some more general ways to handle (maybe by a rustc attribute?). So instead, I'd like to implemenent this via a new method Drop::pin_drop(&pin mut self) first.

Introduce &pin pat pattern syntax

Not started yet (I'd prefer doing that when pattern matching of &pin mut|const T types is ready).

Support &pin mut|const T -> &|&mut T coercion (requires T: Unpin of &pin mut T -> &mut T)

Not started yet. (It's quite independent, probably someone else can help with it)

Support auto borrowing of &pin mut|const place in method calls with &pin mut|const self receivers

Seems to be handled by Autoreborrow traits?

Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

No detailed updates available.
Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

TL;DR.

There have been lots of internal developments since the last update:

Next Steps:

  • we're still planning to merge https://github.com/rust-lang/rust/pull/146307, after I have updated it with the new FRT logic and it has been reviewed
  • once that PR lands, I plan to update the library experiment to use the experimental FRTs
  • then the testing using that library can begin in the Linux kernel and other projects (this is where anyone interested in trying field projections can help out!)

4 detailed updates available.

Comment by [Benno Lossin][] posted on 2025-10-23:

Decomposing Projections

A chained projection operation should naturally decompose, so foo.@bar.@baz should be the same as writing (foo.@bar).@baz. Until now, the different parenthesizing would have allowed different outcomes. This behavior is confusing and also makes many implementation details more complicated than they need to be.

Field Representing Types

Since projections now decompose, we have no need from a design perspective for multi-level FRTs. So field_of!(Foo, bar.baz) is no longer required to work. Thus we have decided to restrict FRTs to only a single field and get rid of the path. This simplifies the implementation in the compiler and also avoids certain difficult questions such as the locality of FRTs (if we had a path, we would have to walk the path and it is local, if all structs included in the path are local). Now with only a single field, the FRT is local if the struct is.

We also discovered that it is a good idea to make FRTs inhabited (they still are ZSTs), since then it allows the following pattern to work:

#![allow(unused)]
fn main() {
fn project_free_standing<F: Field>(_: Field, r: &F::Base) -> &F::Type { ... }

// can now call the function without turbofish:
let my_field = project_free_standing(field_of!(MyStruct, my_field), &my_struct);
}

FRTs via const Generics

We also spent some time thinking about const generics and FRTs on zulip:

In short, this won't be happening any time soon. However, it could be a future implementation of the field_of! macro depending on how reflection through const generics evolves (but also only in the far-ish future).

Comment by [Benno Lossin][] posted on 2025-10-23:

Single Project Operator & Trait via Exclusive Decay

It would be great if we only had to add a single operator and trait and could obtain the same features as we have with two. The current reason for having two operators is to allow both shared and exclusive projections. If we could have another operation that decays an exclusive reference (or custom, exclusive smart-pointer type) into a shared reference (or the custom, shared version of the smart pointer). This decay operation would need borrow checker support in order to have simultaneous projections of one field exclusively and another field shared (and possibly multiple times).

This goes into a similar direction as the reborrowing project goal https://github.com/rust-lang/rust-project-goals/issues/399, however, it needs extra borrow checker support.

#![allow(unused)]
fn main() {
fn add(x: cell::RefMut<'_, i32>, step: i32) {
    *x = *x + step;
}

struct Point {
    x: i32,
    y: i32,
}

fn example(p: cell::RefMut<'_, Point>) {
    let y: cell::Ref<'_, i32> = coerce_shared!(p.@y);
    let y2 = coerce_shared!(p.@y); // can project twice if both are coerced
    add(p.@x, *y);
    add(p.@x, *y2);
    assert_eq!(*y, *y2); // can still use them afterwards
}
}

Problems:

  • explicit syntax is annoying for these "coercions", but
  • we cannot make this implicit:
    • if this were an implicit operation, only the borrow checker would know when one had to coerce,
    • this operation is allowed to change the type,
    • this results in borrow check backfeeding into typecheck, which is not possible or at least extremely difficult

Syntax

Not much movement here, it depends on the question discussed in the previous section, since if we only have one operator, we could choose .@, -> or ~; if we have to have two, then we need additional syntax to differentiate them.

Comment by [Benno Lossin][] posted on 2025-10-23:

Simplifying the Project trait

There have been some developments in pin ergonomics https://github.com/rust-lang/rust/issues/130494: "alternative B" is now the main approach which means that Pin<&mut T> has linear projections, which means that it doesn't change its output type depending on the concrete field (really depending on the field, not only its type). So it falls into the general projection pattern Pin<&mut Struct> -> Pin<&mut Field> which means that Pin doesn't need any where clauses when implementing Project.

Additionally we have found out that RCU also doesn't need where clauses, as we can also make its projections linear by introducing a MutexRef<'_, T> smart pointer that always allows projections and only has special behavior for T = Rcu<U>. Discussed on zulip after this message.

For this reason we can get rid of the generic argument to Project and mandate that all types that support projections support them for all fields. So the new Project trait looks like this:

#![allow(unused)]
fn main() {
// still need a common super trait for `Project` & `ProjectMut`
pub trait Projectable {
    type Target: ?Sized;
}

pub unsafe trait Project: Projectable {
    type Output<F: Field<Base = Self::Target>>;

    unsafe fn project<F: Field<Base = Self::Target>>(
        this: *const Self,
    ) -> Self::Output<F>;
}
}

Are FRTs even necessary?

With this change we can also think about getting rid of FRTs entirely. For example we could have the following Project trait:

#![allow(unused)]
fn main() {
pub unsafe trait Project: Projectable {
    type Output<F>;

    unsafe fn project<const OFFSET: usize, F>(
        this: *const Self,
    ) -> Self::Output<F>;
}
}

There are other applications for FRTs that are very useful for Rust-for-Linux. For example, storing field information for intrusive data structures directly in that structure as a generic.

More concretely, in the kernel there are workqueues that allow you to run code in parallel to the currently running thread. In order to insert an item into a workqueue, an intrusive linked list is used. However, we need to be able to insert the same item into multiple lists. This is done by storing multiple instances of the Work struct. Its definition is:

#![allow(unused)]
fn main() {
pub struct Work<T, const ID: u64> { ... }
}

Where the ID generic must be unique inside of the struct.

#![allow(unused)]
fn main() {
struct MyDriver {
    data: Arc<MyData>,
    main_work: Work<Self, 0>,
    aux_work: Work<Self, 1>,
    // more fields ...
}

// Then you call a macro to implement the unsafe `HasWork` trait safely.
// It asserts that there is a field of type `Work<MyDriver, 0>` at the given field
// (and also exposes its offset).
impl_has_work!(impl HasWork<MyDriver, 0> for MyDriver { self.main_work });
impl_has_work!(impl HasWork<MyDriver, 1> for MyDriver { self.aux_work });

// Then you implement `WorkItem` twice:

impl WorkItem<0> for MyDriver {
    type Pointer = Arc<Self>;
    
    fn run(this: Self::Pointer) {
        println!("doing the main work here");
    }
}

impl WorkItem<1> for MyDriver {
    type Pointer = Arc<Self>;
    
    fn run(this: Self::Pointer) {
        println!("doing the aux work here");
    }
}

// And finally you can call `enqueue` on a `Queue`:

let my_driver = Arc::new(MyDriver::new());
let queue: &'static Queue = kernel::workqueue::system_highpri();
queue.enqueue::<_, 0>(my_driver.clone()).expect("my_driver is not yet enqueued for id 0");

// there are different queues
let queue = kernel::workqueue::system_long();
queue.enqueue::<_, 1>(my_driver.clone()).expect("my_driver is not yet enqueued for id 1");

// cannot insert multiple times:
assert!(queue.enqueue::<_, 1>(my_driver.clone()).is_err());
}

FRTs could be used instead of this id, making the definition be Work<F: Field> (also merging the T parameter).

#![allow(unused)]
fn main() {
struct MyDriver {
    data: Arc<MyData>,
    main_work: Work<field_of!(Self, main_work)>,
    aux_work: Work<field_of!(Self, aux_work)>,
    // more fields ...
}

impl WorkItem<field_of!(MyDriver, main_work)> for MyDriver {
    type Pointer = Arc<Self>;
    
    fn run(this: Self::Pointer) {
        println!("doing the main work here");
    }
}

impl WorkItem<field_of!(MyDriver, aux_work)> for MyDriver {
    type Pointer = Arc<Self>;
    
    fn run(this: Self::Pointer) {
        println!("doing the aux work here");
    }
}

let my_driver = Arc::new(MyDriver::new());
let queue: &'static Queue = kernel::workqueue::system_highpri();
queue
    .enqueue(my_driver.clone(), field_of!(MyDriver, main_work))
    //                          ^ using Gary's idea to avoid turbofish
    .expect("my_driver is not yet enqueued for main_work");

let queue = kernel::workqueue::system_long();
queue
    .enqueue(my_driver.clone(), field_of!(MyDriver, aux_work))
    .expect("my_driver is not yet enqueued for aux_work");

assert!(queue.enqueue(my_driver.clone(), field_of!(MyDriver, aux_work)).is_err());
}

This makes it overall a lot more readable (by providing sensible names instead of magic numbers), and maintainable (we can add a new variant without worrying about which IDs are unused). It also avoids the unsafe HasWork trait and the need to write the impl_has_work! macro for each Work field.

I still think that having FRTs is going to be the right call for field projections as well, so I'm going to keep their experiment going. However, we should fully explore their necessity and rationale for a future RFC.

Comment by [Benno Lossin][] posted on 2025-10-23:

Making Project::project safe

In the current proposal the Project::project function is unsafe, because it takes a raw pointer as an argument. This is pretty unusual for an operator trait (it would be the first). Tyler Mandry thought about a way of making it safe by introducing "partial struct types". This new type is spelled Struct.F where F is an FRT of that struct. It's like Struct, but with the restriction that only the field represented by F can be accessed. So for example &Struct.F would point to Struct, but only allow one to read that single field. This way we could design the Project trait in a safe manner:

#![allow(unused)]
fn main() {
// governs conversion of `Self` to `Narrowed<F>` & replaces Projectable
pub unsafe trait NarrowPointee {
    type Target;

    type Narrowed<F: Field<Base = Self::Target>>;
}

pub trait Project: NarrowPointee {
    type Output<F: Field<Base = Self::Type>>;

    fn project(narrowed: Self::Narrowed<F>) -> Self::Output<F>;
}
}

The NarrowPointee trait allows a type to declare that it supports conversions of its Target type to Target.F. For example, we would implement it for RefMut like this:

#![allow(unused)]
fn main() {
unsafe impl<'a, T> NarrowPointee for RefMut<'a, T> {
    type Target = T;
    type Narrowed<F: Field<Base = T>> = RefMut<'a, T.F>;
}
}

Then we can make the narrowing a builtin operation in the compiler that gets prepended on the actual coercion operation.

However, this "partial struct type" has a fatal flaw that Oliver Scherer found (edit by oli: it was actually boxy who found it): it conflicts with mem::swap, if Struct.F has the same layout as Struct, then writing to such a variable will overwrite all bytes, thus also overwriting field that aren't F. Even if we make an exception for these types and moves/copies, this wouldn't work, as a user today can rely on the fact that they write size_of::<T>() bytes to a *mut T and thus have a valid value of that type at that location. Tyler Mandry suggested we make it !Sized and even !MetaSized to prevent overwriting values of that type (maybe the Overwrite trait could come in handy here as well). But this might make "partial struct types" too weak to be truly useful. Additionally this poses many more questions that we haven't yet tackled.

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

2 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-10-22:

After much discussion, we have decided to charter this team as a t-spec subteam. Pete LeVasseur and I are working to make that happen now.

Comment by [Niko Matsakis][] posted on 2025-10-22:

PR with charters:

https://github.com/rust-lang/team/pull/2028

Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

1 detailed update available.

Comment by [Ian McCormack][] posted on 2025-10-25:

Here's our first status update!

  • We've been experimenting with a few different ways of emitting retags in codegen, as well as a few different forms that retags should take at this level. We think we've settled on a set of changes that's worth sending out to the community for feedback, likely as a pre-RFC. You can expect more engagement from us on this level in the next couple of weeks.

  • We've used these changes to create an initial working prototype for BorrowSanitizer that supports finding Tree Borrows violations in tiny, single-threaded Rust programs. We're working on getting Miri's test suite ported over to confirm that everything is working correctly and that we've quashed any false positives or false negatives.

  • This coming Monday, I'll be presenting on BorrowSanitizer and this project goal at the Workshop on Supporting Memory Safety in LLVM. Please reach out if you're attending and would like to chat more in person!

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

3 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-10-07:

I posted this blog post that proposes that we ought to name the trait Handle and define it as a trait where clone produces an "entangled" value -- i.e., a second handle to the same underlying value.

Before that, there's been a LOT of conversation that hasn't made its way onto this tracking issue. Trying to fix that! Here is a brief summary, in any case:

RFC #3680: https://github.com/rust-lang/rfcs/pull/3680

Comment by [Niko Matsakis][] posted on 2025-10-09:

I wrote up a brief summary of my current thoughts on Zulip; I plan to move this content into a series of blog posts, but I figured it was worth laying it out here too for those watching this space:

09:11 (1) I don't think clones/handles are categorically different when it comes to how much you want to see them made explicit; some applications want them both to be explicit, some want them automatic, some will want a mix -- and possibly other kinds of categorizations.

09:11 (2) But I do think that if you are making everything explicit, it's useful to see the difference between a general purpose clone and a handle.

09:12 (3) I also think there are many classes of software where there is value in having everything explicit -- and that those classes are often the ones most in Rust's "sweet spot". So we should make sure that it's possible to have everything be explicit ergonomically.

09:12 (4) This does not imply that we can't make automatic clones/handles possible too -- it is just that we should treat both use cases (explicit and automatic) as first-class in importance.

09:13 (5) Right now I'm focused on the explicit case. I think this is what the use-use-everywhere was about, though I prefer a different proposal now -- basically just making handle and clone methods understood and specially handled by the compiler for optimization and desugaring purposes. There are pros and cons to that, obviously, and that's what I plan to write-up in more detail.

09:14 (6) On a related note, I think we also need explicit closure captures, which is a whole interesting design space. I don't personally find it "sufficient" for the "fully explicit" case but I could understand why others might think it is, and it's probably a good step to take.

09:15 (7) I go back and forth on profiles -- basically a fancy name for lint-groups based on application domain -- and whether I think we should go that direction, but I think that if we were going to go automatic, that's the way I would do it: i.e., the compiler will automatically insert calls to clone and handle, but it will lint when it does so; the lint can by deny-by-default at first but applications could opt into allow for either or both.

I previously wanted allow-by-default but I've decided this is a silly hill to die on, and it's probably better to move in smaller increments.

Comment by [Niko Matsakis][] posted on 2025-10-22:

Update:

There has been more discussion about the Handle trait on Zulip and elsewhere. Some of the notable comments:

  • Downsides of the current name: it's a noun, which doesn't follow Rust naming convention, and the verb handle is very generic and could mean many things.
  • Alternative names proposed: Entangle/entangle or entangled, Share/share, Alias/alias, or Retain/retain. if we want to seriously hardcore on the science names -- Mitose/mitose or Fission/fission.
  • There has been some criticism pointing out that focusing on handles means that other types which might be "cheaply cloneable" don't qualify.

For now I will go on using the term Handle, but I agree with the critique that it should be a verb, and currently prefer Alias/alias as an alternative.


I'm continuing to work my way through the backlog of blog posts about the conversations from Rustconf. The purposes of these blog posts is not just to socialize the ideas more broadly but also to help myself think through them. Here is the latest post:

https://smallcultfollowing.com/babysteps/blog/2025/10/13/ergonomic-explicit-handles/

The point of this post is to argue that, whatever else we do, Rust should have a way to create handles/clones (and closures that work with them) which is at once explicit and ergonomic.

To give a preview of my current thinking, I am working now on the next post which will discuss how we should add an explicit capture clause syntax. This is somewhat orthogonal but not really, in that an explicit syntax would make closures that clone more ergonomic (but only mildly). I don't have a proposal I fully like for this syntax though and there are a lot of interesting questions to work out. As a strawperson, though, you might imagine [this older proposal I wrote up](https://hackmd.io/Niko Matsakis/SyI0eMFXO?type=view), which would mean something like this:

#![allow(unused)]
fn main() {
let actor1 = async move(reply_tx.handle()) {
    reply_tx.send(...);
};
let actor2 = async move(reply_tx.handle()) {
    reply_tx.send(...);
};
}

This is an improvement on

#![allow(unused)]
fn main() {
let actor1 = {
    let reply_tx = reply_tx.handle();
    async move(reply_tx.handle()) {
        reply_tx.send(...);
    }
};
}

but only mildly.

The next post I intend to write would be a variant on "use, use everywhere" that recommends method call syntax and permitting the compiler to elide handle/clone calls, so that the example becomes

#![allow(unused)]
fn main() {
let actor1 = async move {
    reply_tx.handle().send(...);
    //       -------- due to optimizations, this would capture the handle creation to happen only when future is *created*
};
}

This would mean that cloning of strings and things might benefit from the same behavior:

#![allow(unused)]
fn main() {
let actor1 = async move {
    reply_tx.handle().send(some_id.clone());
    //                     -------- the `some_id.clone()` would occur at future creation time
};
}

The rationable that got me here is (a) minimizing perceived complexity and focusing on muscle memory (just add .clone() or .handle() to fix use-after-move errors, no matter when/where they occur). The cost of course is that (a) Handle/Clone become very special; and (b) it blurs the lines on when code execution occurs. Despite the .handle() occurring inside the future (resp. closure) body, it actually executes when the future (resp. closure) is created in this case (in other cases, such as a closure that implements Fn or FnMut and hence executes more than once, it might occur during each execution as well).

Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

No detailed updates available.
Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

1 detailed update available.

Comment by [Josh Triplett][] posted on 2025-10-22:

The work on this goal has led to many ongoing discussions on the current status of the Reference. Those discussions are still in progress.

Meanwhile, many people working on this goal have successfully written outlines or draft chapters, at various stages of completeness. There's a broken-out status report at https://github.com/rust-lang/project-goal-reference-expansion/issues/11 .

Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

No detailed updates available.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

1 detailed update available.

Comment by [Manuel Drehwald][] posted on 2025-10-22:

A longer update of the changes over the fall. We had two gsoc contributors and a lot of smaller improvements for std::autodiff. The first two improvements were already mentioned as draft PRs in the previous update, but got merged since. I also upstreamed more std::offload changes.

  1. Marcelo Domínguez refactored the autodiff frontend to be a proper rustc intrinsic, rather than just hackend into the frontend like I first implemented it. This already solved multiple open issues, reduced the code size, and made it generally easier to maintain going forward.
  2. Karan Janthe upstreamed a first implementation of "TypeTrees", which lowers rust type and layout information to Enzyme, our autodiff backend. This makes it more likely that you won't see compilation failures with the error message "Can not deduce type of ". We might refine in the future what information exactly we lower.
  3. Karan Janthe made sure that std::autodiff has support for f16 and and f128 types.
  4. One more of my offload PRs landed. I also figured out why the LLVM-IR generated by the std::offload code needed some manual adjustments in the past. We were inconsistent when communicating with LLVM's offload module, about whether we'd want a magic, extra, dyn_ptr argument, that enables kernels to use some extra features. We don't use these features yet, but for consistency we now always generate and expect the extra pointer. The bugfix is currently under review, once it lands upstream, rustc is able to run code on GPUs (still with a little help of clang).
  5. Marcelo Domínguez refactored my offload frontend, again introducing a proper rustc intrinsic. That code will still need to go through review, but once it lands it will get us a lot closer to a usable frontend. He also started to generate type information for our offload backend to know how many bytes to copy to and from the devices. This is a very simplified version of our autodiff typetrees.
  6. At RustChinaConf, I was lucky to run into the wild linker author David Lattimore, which helped me to create a draft PR that can dlopen Enzyme at runtime. This means we could ship it via rustup for people interested in std::autodiff, and don't have to link it in at build time, which would increase binary size even for those users that are not interested in it. There are some open issues, so please reach out if you have time to get the PR ready!
  7. @sgasho spend a lot of time trying to get Rust into the Enzyme CI. Unfortunately that is a tricky process due to Enzyme's CI requirements, so it's not merged yet.
  8. I tried to simplify building std::autodiff by marking it as compatible with download-llvm-ci. Building LLVM from source was previously the by far slowest part of building rustc with autodiff, so this has a large potential. Unfortunately the CI experiments revealed some issues around this setting. We think we know why Enzyme's Cmake causes issues here and are working on a fix to make it more reliable.
  9. @osamakader and bjorn3 looked into automatically enabling fat-lto when autodiff is enabled. In the past, forgetting to enable fat-lto resulted in incorrect (zero) derivatives. The first approach unfortunately wasn't able to cover all cases, so we need to see whether we can handle it nicely. If that turns out to be too complicated, we will revert it and instead "just" provide a nice error message, rather than returning incorrect derivatives.

All-in-all I spend a lot more time on infra (dlopen, cmake, download-llvm-ci, ...) then I'd like, but on the happy side there are only so many features left that I want to support here so there is an end in sight. I am also about to give a tech-talk at the upcoming LLVM dev meeting about safe GPU programming in Rust.

Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

3 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2025-10-09:

I've updated the top-level description to show everything we're tracking here (please let me know if anything's missing or incorrect!).

Comment by [Tomas Sedovic][] posted on 2025-10-10:
  • [merged] Sanitizers target modificators / https://github.com/rust-lang/rust/pull/138736
  • [merged] Add assembly test for -Zreg-struct-return option / https://github.com/rust-lang/rust/pull/145382
  • [merged] CI: rfl: move job forward to Linux v6.17-rc5 to remove temporary commits / https://github.com/rust-lang/rust/pull/146368
  • -Zharden-sls / https://github.com/rust-lang/rust/pull/136597
    • Waiting on review
  • #![register_tool] / https://github.com/rust-lang/rust/issues/66079
    • Waiting on https://github.com/rust-lang/rfcs/pull/3808
  • -Zno-jump-tables / https://github.com/rust-lang/rust/pull/145974
    • Active FCP, waiting on 2 check boxes
Comment by [Tomas Sedovic][] posted on 2025-10-24:

-Cunsigned-char

We've discussed adding an option analogous to -funsigned-char in GCC and Clang, that would allow you to set whether std::ffi::c_char is represented by i8 or u8. Right now, this is platform-specific and should map onto whatever char is in C on the same platform. However, Linux explicitly sets char to be unsigned and then our Rust code conflicts with that. And isn this case the sign is significant.

Rust for Linux works around this this with their rust::ffi module, but now that they've switched to the standard library's CStr type, they're running into it again with the as_ptr method.

Tyler mentioned https://docs.rs/ffi_11/latest/ffi_11/ which preserves the char / signed char / unsigned char distinction.

Grouping target modifier flags

The proposed unsigned-char option is essentially a target modifier. We have several more of these (e.g. llvm-args, no-redzone) in the Rust compiler and Josh suggested we distinguish them somehow. E.g. by giving them the same prefix or possibly creating a new config option (right now we have -C and -Z, maybe we could add -T for target modifiers) so they're distinct from the e.g. the codegen options.

Josh started a Zulip thread here: https://rust-lang.zulipchat.com/#narrow/channel/131828-t-compiler/topic/Grouping.20target.20modifier.20options.3F/with/546524232

#![register_tool] / rust#66079 / RFC#3808

Tyler looked at the RFC. The Crubit team started using register_tool but then moved to using an attribute instead. He proposed we could do something similar here, although it would require a new feature and RFC.

The team was open to seeing how it would work.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

3 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2025-10-09:

I've updated the top-level description to show everything we're tracking here (please let me know if anything's missing or incorrect!).

Comment by [Tomas Sedovic][] posted on 2025-10-10:

Deref/Receiver

  • Ding Xiang Fei keeps updating the PR: https://github.com/rust-lang/rust/pull/146095
  • They're also working on a document to explain the consequences of this split

Arbitrary Self Types

  • https://github.com/rust-lang/rust/issues/44874
  • Waiting on the Deref/Receiver work, no updates

derive(CoercePointee)

  • https://github.com/rust-lang/rust/pull/133820
  • Waiting on Arbitrary self types

Pass pointers to const in asm! blocks

  • RFC: https://github.com/rust-lang/rfcs/pull/3848
  • The Lang team went through the RFC with Alice Ryhl on 2025-10-08 and it's in FCP now

Field projections

  • Benno Lossin opened a PR here: https://github.com/rust-lang/rust/pull/146307
  • Being reviewed by the compiler folks

Providing \0 terminated file names with #[track_caller]

  • The feature has been implemented and stabilized with file_as_c_str as the method name: https://github.com/rust-lang/rust/pull/145664

Supertrait auto impl RFC

  • Ding Xiang Fei opened the RFC and works with the reviewers: https://github.com/rust-lang/rfcs/pull/3851

Other

  • Miguel Ojeda spoke to Linus about rustfmt and they came to agreement.
Comment by [Tomas Sedovic][] posted on 2025-10-24:

Layout of core::any::TypeId

Danilo asked about the layout of TypeId -- specifically its size and whether they can rely on it because they want to store it in a C struct. The struct's size is currently 16 bytes, but that's an implementation detail.

As a vibe check, Josh Triplett and Tyler Mandry were open to guaranteeing that it's going to be at most 16 bytes, but they wanted to reserve the option to reduce the size at some point. The next step is to have the full Lang and Libs teams discuss the proposal.

Danilo will open a PR to get that discussion started.

rustfmt

Miguel brought up the "trailing empty comment" workaround for the formatting issue that made the rounds on the Linux kernel a few weeks ago. The kernel style places each import on a single line:

#![allow(unused)]
fn main() {
    use crate::{
        fmt,
        page::AsPageIter,
    };
}

rustfmt compresses this to:

#![allow(unused)]
fn main() {
    use crate::{fmt, page::AsPageIter};
}

The workaround is to put an empty trailing comment at the end

#![allow(unused)]
fn main() {
    use crate::{
        fmt,
        page::AsPageIter, //
    };
}

This was deemed acceptable (for the time being) and merged into the mainline kernel: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4a9cb2eecc78fa9d388481762dd798fa770e1971

Miguel is in contact with rustfmt to support this behaviour without a workaround.

// PANIC: ... comments / clippy#15895

This is a proposal to add a lint that would require a PANIC comment (modeled after the SAFETY comment) to explain the circumstances during which the code will or won't panic.

Alejandra González was open to the suggestion and Henry Barker stepped up to implement it.

Deref/Receiver

During the experimentation work, Ding ran into an issue with overlapping impls (that was present even with #[unstable_feature_bound(..)]). We ran out of time but we'll discuss this offline and return to it at the next meeting.

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

No detailed updates available.
In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

1 detailed update available.

Comment by [Alice Ryhl][] posted on 2025-10-22:

This is our first update we’re posting for the in-place init work. Overall things are progressing well, with lively discussion happening on the newly minted t-lang/in-place-init Zulip channel. Here are the highlights since the lang team design meeting at the end of July:

MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

No detailed updates available.
Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

1 detailed update available.

Comment by [lcnr][] posted on 2025-10-23:

Since the last update we've fixed the hang in rayon in https://github.com/rust-lang/rust/pull/144991 and https://github.com/rust-lang/rust/pull/144732 which relied on https://github.com/rust-lang/rust/pull/143054 https://github.com/rust-lang/rust/pull/144955 https://github.com/rust-lang/rust/pull/144405 https://github.com/rust-lang/rust/pull/145706. This introduced some search graph bugs which we fixed in https://github.com/rust-lang/rust/pull/147061 https://github.com/rust-lang/rust/pull/147266.

We're mostly done with the opaque type support now. Doing so required a lot of quite involved changes:

  • https://github.com/rust-lang/rust/pull/145244 non-defining uses in borrowck
  • https://github.com/rust-lang/rust/pull/145925 non-defining uses in borrowck closure support
  • https://github.com/rust-lang/rust/pull/145711 non-defining uses in hir typeck
  • https://github.com/rust-lang/rust/pull/140375 eagerly compute sub_unification_table again
  • https://github.com/rust-lang/rust/pull/146329 item bounds
  • https://github.com/rust-lang/rust/pull/145993 function calls
  • https://github.com/rust-lang/rust/pull/146885 method selection
  • https://github.com/rust-lang/rust/pull/147249 fallback

We also fixed some additional self-contained issues and perf improvements: https://github.com/rust-lang/rust/pull/146725 https://github.com/rust-lang/rust/pull/147138 https://github.com/rust-lang/rust/pull/147152 https://github.com/rust-lang/rust/pull/145713 https://github.com/rust-lang/rust/pull/145951

We have also migrated rust-analyzer to entirely use the new solver instead of chalk. This required a large effort mainly by Jack Huey Chayim Refael Friedman and Shoyu Vanilla. That's some really impressive work on their end 🎉 See this list of merged PRs for an overview of what this required on the r-a side. Chayim Refael Friedman also landed some changes to the trait solver itself to simplify the integration: https://github.com/rust-lang/rust/pull/145377 https://github.com/rust-lang/rust/pull/146111 https://github.com/rust-lang/rust/pull/147723 https://github.com/rust-lang/rust/pull/146182.

We're still tracking the remaining issues in https://github.com/orgs/rust-lang/projects/61/views/1. Most of these issues are comparatively simple and I expect us to fix most of them over the next few months, getting us close to stabilization. We're currently doing another crater triage which may surface a few more issues.

Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

No detailed updates available.
Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

1 detailed update available.

Comment by [Weihang Lo][] posted on 2025-10-04:

Cargo tracking issue: https://github.com/rust-lang/cargo/issues/15844. The first implementation was https://github.com/rust-lang/cargo/pull/15845 in August that added build.analysis.enabled = true to unconditionally generate timing HTML. Further implementations tasks is listed in https://github.com/rust-lang/cargo/issues/15844#issuecomment-3192779748.

Haven't yet got any progress in September.

Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

1 detailed update available.

Comment by [Aapo Alasuutari][] posted on 2025-10-22:

Initial implementation of a Reborrow trait for types with only lifetimes with exclusive reference semantics is working but not yet upstreamed not in review. CoerceShared implementation is not yet started.

Proper composable implementation will likely require a different tactic than the current one. Safety and validity checks are currently absent as well and will require more work.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

1 detailed update available.

Comment by [Oliver Scherer][] posted on 2025-10-22:

I implemented an initial MVP supporting only tuples and primitives (tho those are just opaque things you can't interact with further), and getting offsets for the tuple fields as well as the size of the tuple: https://github.com/rust-lang/rust/pull/146923

There are two designs of how to expose this from a libs perspective, but after a sync meeting with scottmcm yesterday we came to the conclusion that neither is objectively better at this stage so we're just going to go with the nice end-user UX version for now. For details see the PR description.

Once the MVP lands, I will mentor various interested contributors who will keep adding fields to the Type struct and variants the TypeKind enum.

The next major step is restricting what information you can get from structs outside of the current module or crate. We want to honor visibility, so an initial step would be to just never show private fields, but we want to explore allowing private fields to be shown either just within the current module or via some opt-in marker trait

Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

No detailed updates available.
Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

1 detailed update available.

Comment by [Ross Sullivan][] posted on 2025-10-06:

Status update October 6, 2025

The build-dir was split out of target-dir as part of https://github.com/rust-lang/cargo/issues/14125 and scheduled for stabilization in Rust 1.91.0. 🎉

Before re-organizing the build-dir layout we wanted to improve the existing layout tests to make sure we do not make any unexpected changes. This testing harness improvement was merged in https://github.com/rust-lang/cargo/pull/15874.

The initial build-dir layout reorganization PR has been posted https://github.com/rust-lang/cargo/pull/15947 and discussion/reviews are under way.

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

No detailed updates available.
Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

No detailed updates available.
Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

1 detailed update available.

Comment by [Jack Huey][] posted on 2025-10-22:

Update:

Niko and I gave a talk at RustConf 2025 (and I represented that talk at RustChinaConf 2025) where we gave an update on this (and some intermediate insights).

We have started to seriously plan the shape of the final doc. We have some "blind spots" that we'd like to cover before finishing up, but overall we're feeling close to the finish line on interviews.

rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

1 detailed update available.

Comment by [Jakub Beránek][] posted on 2025-10-21:

We moved forward with the implementation, and the new job queue system is now being tested in production on a single test pull request. Most things seem to be working, but there are a few things to iron out and some profiling to be done. I expect that within a few weeks we could be ready to switch to the new system fully in production.

Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

1 detailed update available.

Comment by [Rémy Rakic][] posted on 2025-10-22:

Here's another summary of the most interesting developments since the last update:

  • reviews and updates have been done on the polonius alpha, and it has since landed
  • the last 2 trivial diagnostics failures were fixed
  • we've done perf runs, crater runs, completed gathering stats on crates.io for avg and outliers in CFG sizes, locals, loan and region counts, dataflow framework behavior on unexpected graph shapes and bitset invalidations
  • I worked on dataflow for borrowck: single pass analyses on acyclic CFGs, dataflow analyses on SCCs for cyclic CFGs
  • some more pieces of amanda's SCC rework have landed, with lcnr's help
  • lcnr's opaque type rework, borrowcking of nested items, and so on, also fixed some issues we mentioned in previous updates with member constraints for computing when loans are going out of scope
  • we also studied recent papers in flow-sensitive pointer analysis
  • I also started the loans-in-scope algorithm rework, and also have reachability acceleration with the CFG SCCs
  • the last 2 actual failures in the UI tests are soundness issues, related to liveness of captured regions for opaque types: some regions that should be live are not, which were done to help with precise capture and limit the impact of capturing unused regions that cannot be actually used in the hidden type. The unsoundness should not be observable with NLLs, but polonius alpha relies on liveness to propagate loans throughout the CFG: these dead regions prevent detecting some error-causing loan invalidations. The easiest fix would cause breakage in code that's now accepted. niko, jack and I have another possible solution and I'm trying to implement it now
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

No detailed updates available.
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

No detailed updates available.
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

1 detailed update available.

Comment by [Niko Matsakis][] posted on 2025-10-22:

Sized hierarchy

The focus right now is on the "non-const" parts of the proposal, as the "const" parts are blocked on the new trait solver (https://github.com/rust-lang/rust-project-goals/issues/113). Now that the types team FCP https://github.com/rust-lang/rust/pull/144064 has completed, work can proceed to land the implementation PRs. David Wood plans to split the RFC to separate out the "non-const" parts of the proposal so it can move independently, which will enable extern types.

To that end, there are three interesting T-lang design questions to be considered.

Naming of the traits

The RFC currently proposes the following names

  • Sized
  • MetaSized
  • PointeeSized

However, these names do not follow the "best practice" of naming the trait after the capability that it provides. As champion Niko is recommending we shift to the following names:

  • Sized -- should righly be called SizeOf, but oh well, not worth changing.
  • SizeOfVal -- named after the method size_of_val that you get access to.
  • Pointee -- the only thing you can do is point at it.

The last trait name is already used by the (unstable) std::ptr::Pointee trait. We do not want to have these literally be the same trait because that trait adds a Metadata associated type which would be backwards incompatible; if existing code uses T::Metadata to mean <T as SomeOtherTrait>::Metadata, it could introduce ambiguity if now T: Pointee due to defaults. My proposal is to rename std::ptr::Pointee to std::ptr::PointeeMetadata for now, since that trait is unstable and the design remains under some discussion. The two traits could either be merged eventually or remain separate.

Note that PointeeMetadata would be implemented automatically by the compiler for anything that implements Pointee.

Syntax opt-in

The RFC proposes that an explicit bound like T: MetaSized disabled the default T: Sized bound. However, this gives no signal that this trait bound is "special" or different than any other trait bound. Naming conventions can help here, signalling to users that these are special traits, but that leads to constraints on naming and may not scale as we consider using this mechanism to relax other defaults as proposed in my recent blog post. One idea is to use some form of syntax, so that T: MetaSized is just a regular bound, but (for example) T: =MetaSized indicates that this bound "disables" the default Sized bound. This gives users some signal that something special is going on. This = syntax is borrowing from semver constraints, although it's not a precise match (it does not mean that T: Sized doesn't hold, after all). Other proposals would be some other sigil (T: ?MetaSized, but it means "opt out from the traits above you"; T: #MetaSized, ...) or a keyword (no idea).

To help us get a feel for it, I'll use T: =Foo throughout this post.

Implicit trait supertrait bounds, edition interaction

In Rust 2024, a trait is implicitly ?Sized which gets mapped to =SizeOfVal:

#![allow(unused)]
fn main() {
trait Marker {} // cannot be implemented by extern types
}

This is not desirable but changing it would be backwards incompatible if traits have default methods that take advantage of this bound:

#![allow(unused)]
fn main() {
trait NotQuiteMarker {
    fn dummy(&self) {
        let s = size_of_val(self);
    }
}
}

We need to decide how to handle this. Options are

  • Just change it, breakage will be small (have to test that).
  • Default to =SizeOfVal but let users explicitly write =Pointee if they want that. Bad because all traits will be incompatible with extern types.
  • Default to =SizeOfVal only if defaulted methods are present. Bad because it's a backwards incompatible change to add a defaulted method now.
  • Default to =Pointee but add where Self: =SizeOfVal implicitly to defaulted methods. Now it's not backwards incompatible to add a new defaulted method, but it is backwards incompatible to change an existing method to have a default.

If we go with one of the latter options, Niko proposes that we should relax this in the next Edition (Rust 2026?) so that the default becomes Pointee (or maybe not even that, if we can).

Relaxing associated type bounds

Under the RFC, existing ?Sized bounds would be equivalent to =SizeOfVal. This is mostly fine but will cause problems in (at least) two specific cases: closure bounds and the Deref trait. For closures, we can adjust the bound since the associated type is unstable and due to the peculiarities of our Fn() -> T syntax. Failure to adjust the Deref bound in particular would prohibit the use of Rc<E> where E is an extern type, etc.

For deref bounds, David Wood is preparing a PR that simply changes the bound in a backwards incompatible way to assess breakage on crater. There is some chance the breakage will be small.

If the breakage proves problematic, or if we find other traits that need to be relaxed in a similar fashion, we do have the option of:

  • In Rust 2024, T: Deref becomes equivalent to T: Deref<Target: SizeOfVal> unless written like T: Deref<Target: =Pointee>. We add that annotation throughout stdlib.
  • In Rust 202X, we change the default, so that T: Deref does not add any special bounds, and existing Rust 2024 T: Deref is rewritten to T: Deref<Target: SizeOfVal> as needed.

Other notes

One topic that came up in discussion is that we may eventually wish to add a level "below" Pointee, perhaps Value, that signifies webassembly external values which cannot be pointed at. That is not currently under consideration but should be backwards compatible.

Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

No detailed updates available.
Progress
Point of contact

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

September Blog Post

The Rust project is currently working towards a slate of 41 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help

Promoting Parallel Front End (rust-lang/rust-project-goals#121)
Progress
Point of contact

Sparrow Li

Task owners

Sparrow Li

Help wanted:

Help test the deadlock code in the issue list and try to reproduce the issue

1 detailed update available.

Comment by [Sparrow Li][] posted on 2025-09-17:
  • Key developments: We have added more tests for deadlock issues. And we can say that deadlock problems are almost resolved. And we are currently addressing issues related to reproducible builds, and some of these have already been resolved.
  • Blockers: null
  • Help wanted: Help test the deadlock code in the issue list and try to reproduce the issue


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

No detailed updates available.
Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

No detailed updates available.
Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

1 detailed update available.

Comment by [Adam Gemmell][] posted on 2025-09-12:

Recently we've been working on feedback on the multi-staged format of the RFC. We've also shared the RFC outside of our sync call group to people from a variety of project teams and potential users too.

We're now receiving feedback that is much more detail-oriented, as opposed to being about the direction and scope of the RFC, which is a good indication that the overall strategy for shipping this RFC seems promising. We're continuing to address feedback to ensure the RFC is clear, consistent and technically feasible. David's feeling is that we've probably got another couple rounds of feedback from currently involved people and then we'll invite more people from various groups before publishing parts of the RFC formally.

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

No detailed updates available.
Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Progress
Point of contact

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

No detailed updates available.
Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

No detailed updates available.
Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

1 detailed update available.

Comment by [Predrag Gruevski][] posted on 2025-09-19:

Just removed the duplicate posts, guessing from a script that had a bad day.

Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

1 detailed update available.

Comment by [Benno Lossin][] posted on 2025-09-24:

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: @x->f/@mut x->f, @x.f/@mut x.f, x.@f/x.mut@f, x.ref.@f/x.@f. Also many alternatives for the sigils used: x@f, 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 are repr(transparent) and apply themselves to each field, so MaybeUninit<MyStruct> has a field of type MaybeUninit<MyField> (if MyStruct has a field of type MyField).
  • Pointers are types like &T, &mut T, cell::Ref[Mut]<'_, T>, *const T/*mut T, NonNull<T>. They support projecting Pointer<'_, Struct> to Pointer<'_, 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 the impl 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)
  • a new match operator that will project all mentioned fields (for &Enum this already is the behavior for match)

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.

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

No detailed updates available.
Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

No detailed updates available.
Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

1 detailed update available.

Comment by [Taylor Cramer][] posted on 2025-09-30:

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 impls

The current RFC proposes that

#![allow(unused)]
fn main() {
impl Supertrait for MyType {}

impl Subtrait for MyType {
    // Required in order to manually write `Supertrait` for MyType.
    extern impl 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 impls 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.

Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

No detailed updates available.
Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-09-16:

Key developments:

  • libtest2
    • libtest env variables were deprecated, reducing the API surface for custom test harnesses, https://github.com/rust-lang/rust/pull/145269
    • libtest2 was updated to reflect deprecations
    • https://github.com/assert-rs/libtest2/pull/105
    • libtest2 is now mostly in shape for use
  • json schema
    • https://github.com/assert-rs/libtest2/pull/107
    • https://github.com/assert-rs/libtest2/pull/108
    • https://github.com/assert-rs/libtest2/pull/111
    • https://github.com/assert-rs/libtest2/pull/120
    • starting exploration of extension through custom messages, see https://github.com/assert-rs/libtest2/pull/122

New areas found for further exploration

  • Failable discovery
  • Nested discovery
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

No detailed updates available.
Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

No detailed updates available.
Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

No detailed updates available.
Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

No detailed updates available.
In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

No detailed updates available.
MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

No detailed updates available.
Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

No detailed updates available.
Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

No detailed updates available.
Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-09-16:

Key developments:

  • https://github.com/crate-ci/cargo-plumbing/pull/53
  • https://github.com/crate-ci/cargo-plumbing/pull/62
  • https://github.com/crate-ci/cargo-plumbing/pull/68
  • https://github.com/crate-ci/cargo-plumbing/pull/96
  • Further schema discussions at https://github.com/crate-ci/cargo-plumbing/discussions/18
  • Writing up https://github.com/crate-ci/cargo-plumbing/issues/82

Major obstacles

  • Cargo, being designed for itself, doesn't allow working with arbitrary data, see https://github.com/crate-ci/cargo-plumbing/issues/82
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

No detailed updates available.
Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

No detailed updates available.
reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

No detailed updates available.
Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

No detailed updates available.
Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

No detailed updates available.
Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

No detailed updates available.
Rust Stabilization of MemorySanitizer and ThreadSanitizer Support (rust-lang/rust-project-goals#403)
Progress
Point of contact

Jakob Koschel

Task owners

[Bastian Kersting](https://github.com/1c3t3a), [Jakob Koschel](https://github.com/jakos-sec)

No detailed updates available.
Rust Vision Document (rust-lang/rust-project-goals#269)
Progress
Point of contact

Niko Matsakis

Task owners

vision team

No detailed updates available.
rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

1 detailed update available.

Comment by [James][] posted on 2025-09-17:

It is possible to now run the system with two different machines on two different architectures however there is work to be done to make this more robust.

We have worked on ironing out the last bits and pieces for dequeuing benchmarks as well as creating a new user interface to reflect multiple collectors doing work. Presently work is mostly on polishing the UI and handing edge cases through manual testing.

Queue Work:

  • https://github.com/rust-lang/rustc-perf/pull/2212
  • https://github.com/rust-lang/rustc-perf/pull/2214
  • https://github.com/rust-lang/rustc-perf/pull/2216
  • https://github.com/rust-lang/rustc-perf/pull/2221
  • https://github.com/rust-lang/rustc-perf/pull/2226
  • https://github.com/rust-lang/rustc-perf/pull/2230
  • https://github.com/rust-lang/rustc-perf/pull/2231

Ui:

  • https://github.com/rust-lang/rustc-perf/pull/2217
  • https://github.com/rust-lang/rustc-perf/pull/2220
  • https://github.com/rust-lang/rustc-perf/pull/2224
  • https://github.com/rust-lang/rustc-perf/pull/2227
  • https://github.com/rust-lang/rustc-perf/pull/2232
  • https://github.com/rust-lang/rustc-perf/pull/2233
  • https://github.com/rust-lang/rustc-perf/pull/2236
Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

No detailed updates available.
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-09-16:

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
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

No detailed updates available.
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

No detailed updates available.
Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

No detailed updates available.
Progress
Point of contact

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

bootstrap Team Champion Reports

This section contains champion reports for the bootstrap team.

Recent updates

The Rust project is currently working towards a slate of 1 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

2 detailed updates available.

Comment by [Pete LeVasseur][] posted on 2025-12-16:

Meeting notes here: FLS team meeting 2025-12-12

Key developments: We're close to completing the FLS release for 1.91.0, 1.91.1. We've started to operate as a team, merging a PR with the changelog entries, then opening up issues for each change required: ✅ #624(https://github.com/rust-lang/fls/issues/624), ✅ #625(https://github.com/rust-lang/fls/issues/625), ✅ #626(https://github.com/rust-lang/fls/issues/626), ⚠️ #623(https://github.com/rust-lang/fls/issues/623). #623(https://github.com/rust-lang/fls/issues/623) is still pending, as it requires a bit of alignment with the Reference on definitions and creation of a new example. Blockers: None currently Help wanted: We'd love more folks from the safety-critical community to contribute to picking up issues or opening an issue if you notice something is missing.

Comment by [Pete LeVasseur][] posted on 2025-11-21:

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.

cargo Team Champion Reports

This section contains champion reports for the cargo team.

Recent updates

The Rust project is currently working towards a slate of 10 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

3 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rfcs#3873 has been merged and an FCP has been started on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 - those both have some feedback for me to respond to that I'll get to as soon as I can

Comment by [David Wood][] posted on 2025-12-15:

rust-lang/rfcs#3873 is waiting on one checkbox before entering the final comment period. We had our sync meeting on the 11th and decided that we would enter FCP on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 after rust-lang/rfcs#3873 is accepted. We've responded to almost all of the feedback on the next two RFCs and expect the FCP to act as a forcing-function so that the relevant teams take a look, they can always register concerns if there are things we need to address, and if we need to make any major changes then we'll restart the FCP.

Comment by [David Wood][] posted on 2025-11-22:

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.

Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

2 detailed updates available.

Comment by [Predrag Gruevski][] posted on 2026-01-17:

I posted a "year in review" for cargo-semver-checks here: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/

It has a section on how I think we should move forward in 2026 and beyond: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/#the-path-forward-for-2026-and-beyond

Comment by [Predrag Gruevski][] posted on 2025-11-23:

Google Summer of Code 2025 is complete + finally some movement on cross-crate linting! 🚀

Key developments

  • Two students had a successful conclusion of Google Summer of Code working on cargo-semver-checksfind more details here!
  • rustdoc JSON now includes rlib information, following the design for cross-crate rustdoc JSON info created at RustWeek 2025: https://github.com/rust-lang/rust/pull/149043
  • A cargo issue was discovered that prevents this rlib info from being used; it's currently being triaged: https://github.com/rust-lang/cargo/issues/16291
  • Once that's resolved, we'll have enough here for a basic prototype. Getting features right in dependencies will likely require more work due to having many more cargo-related edge cases.
Finish the libtest json output experiment (rust-lang/rust-project-goals#255)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page)

Task owners

Ed Page

1 detailed update available.

Comment by [Ed Page][] posted on 2025-11-21:

Key developments:

  • libtest2:
    • #[test] macro added
    • Support for should_panic
    • Support for ignore
    • Support for custom error types
    • compile-fail tests for macros

Blockers

  • None

Help wanted:

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

3 detailed updates available.

Comment by [Eric Holk][] posted on 2025-12-06:

Hi @sladyn98 - feel free to ping me on Zulip about this.

Comment by [Ed Page][] posted on 2025-12-03:

The work is more on the compiler side atm, so Eric Holk and b-naber could speak more to where they could use help.

Comment by @sladyn98 posted on 2025-12-03:

Ed Page hey i would like to contribute to this I reached out on zulip. Bumping up the post in case it might have gone under the radar

CC Niko Matsakis

Prototype a new set of Cargo "plumbing" commands (rust-lang/rust-project-goals#264)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.
Prototype Cargo build analysis (rust-lang/rust-project-goals#398)
Progress
Point of contact

Weihang Lo

Champions

cargo (Weihang Lo)

Task owners

Help wanted Weihang Lo, Weihang Lo

4 detailed updates available.

Comment by [Weihang Lo][] posted on 2026-01-08:

Project Goal Update

The prototype of this project goal is basically complete.

Current state

This project goal introduces build analysis support in Cargo, with the aim of making build behavior understandable across multiple invocations, not just a single run.

At a high level, the prototype:

  • Records build metadata over time, including:
    • rebuild reasons
    • timing information
    • relevant invocation context
  • Stores this data locally in a structured log format suitable for later analysis
  • Exposes the data via unstable cargo report subcommands, such as:
    • cargo report sessions - list session IDs
    • cargo report timings - HTML timing report
    • cargo report rebuilds - Why things rebuilt

See https://doc.rust-lang.org/nightly/cargo/reference/unstable.html#build-analysis for a more thorough usage documentation


Path towards stabilization

Before this feature can be stabilized, the following unresolved questions must be answered.

They might not block stabilization, but need to be evaluated if it is fine to leave for future.

cargo report commands

This is a stabilization blocker.

  • [ ] Currently all three report commands (sessions, rebuilds, timings) implicitly inspect global log files when if not in a workspace.
    • Should this be explicit with a flag?
    • Should this be an error if not in a workspace?
  • [ ] Bikeshed on command names
    • Currently we have all nouns
      • For sessions
        • runs simple but ambiguous
        • Just log like git log
        • history user-friendly (docker history, shell history, though not alike)
      • For timings:
        • Not controversial, as we have --timings flag already
      • For rebuilds:
        • rebuild-reasons more explicit
    • Or move to action-oriented verbs:
    • cargo report list-sessions
    • cargo report analyze-timings (bazel analyze-profile https://bazel.build/docs/user-manual#analyze-profile)
    • cargo report explain-rebuilds
    • Or question-oriented verbs:
    • cargo report what-ran more general https://buck2.build/docs/developers/what-ran/
    • cargo report why-rebuilt/why-reran

cargo report sessions

  • Currently it prints a human-readable output without a format for programmable use cases.
    • Should we provide a programmable output (for example behind --message-format=json)?

cargo report rebuilds

  • Extend the report from fingerprint to new hash (-Cmetadata/-Cextra-filename)
    • We currently can't distinguish whether a fresh build is a real new build or just rustflags changed
    • https://github.com/rust-lang/cargo/pull/16456#discussion_r2662364819
  • Make each rebuilt reason more actionable and friendly for end-users.
  • Should we log the fingerprint values being compared, or just the diff result?
  • #t-cargo > logging unit fingerprint @ 💬

Log message schema

This is a stabilization blocker.

Log infrastructure

These are mostly future possibilities, not a stabilization blocker, as it is highly possible to do incremental improvements.

See also https://github.com/rust-lang/cargo/issues/16471#issuecomment-3724915770

Nested Cargo calls

See https://github.com/rust-lang/cargo/issues/16477.

Basically, we need to have a way to associate log files of nested Cargo calls. That helps other tools as well as cargo fix itself.

This is a stabilization blocker.

How contributors can help

Future contributors can help by:

A series of follow-up tasks has been cut to track remaining work:

  • https://github.com/rust-lang/cargo/issues/16470
  • https://github.com/rust-lang/cargo/issues/16471
  • https://github.com/rust-lang/cargo/issues/16472
  • https://github.com/rust-lang/cargo/issues/16473
  • https://github.com/rust-lang/cargo/issues/16474
  • https://github.com/rust-lang/cargo/issues/16475
  • https://github.com/rust-lang/cargo/issues/16477
  • https://github.com/rust-lang/cargo/issues/16488
Comment by [Weihang Lo][] posted on 2025-12-26:

Key developments:

Headline: You should always enable build analysis locally, if you are using nightly and want the timing info data always available.

[unstable]
build-analysis = true

[build.analysis]
enabled = true
  • More log events are emitted: https://github.com/rust-lang/cargo/pull/16390
    • dependency resolution time
    • unit-graph construction
    • unit-registration (which contain unit metadata)
  • Timing replay from cargo report timings now has almost the same feature parity as cargo build --timings, except CPU usage: https://github.com/rust-lang/cargo/pull/16414
  • Rename rebuild event to unit-fingerprint, and is emitted also for fresh unit: https://github.com/rust-lang/cargo/pull/16408.
  • Proposed a new cargo report sessions command so that people can retrieve previous sessions IDs not use the latest one: https://github.com/rust-lang/cargo/pull/16428
  • Proposed to remove --timings=json which timing info in log files should be a great replacement: https://github.com/rust-lang/cargo/pull/16420
  • Documenting efforts for having man pages for nested commands `cargo report : https://github.com/rust-lang/cargo/pull/16430 and https://github.com/rust-lang/cargo/pull/16432

Besides implementations, we also discussed about:

  • The interaction of --message-format and structured logging system, as well as log event schemas and formats: https://rust-lang.zulipchat.com/#narrow/channel/246057-t-cargo/topic/build.20analysis.20log.20format/with/558294271
  • A better name for RunId. We may lean towards SessionId which is a common name for logging/tracing ecosystem.
  • Nested Cargo calls to have a sticky session ID. At least a way to show they were invoked from the same top-level Cargo call.

Blockers: No, except my own availability

Help wanted: Same as https://github.com/rust-lang/rust-project-goals/issues/398#issuecomment-3571897575

Comment by [Weihang Lo][] posted on 2025-12-13:

Key developments: HTML replay logic has merge. Once it gets into nightly cargo report timings can open the timing report you have previously logged.

  • https://github.com/rust-lang/cargo/pull/16377
  • https://github.com/rust-lang/cargo/pull/16378
  • https://github.com/rust-lang/cargo/pull/16382

Blockers: No, except my own availability

Help wanted: Same as https://github.com/rust-lang/rust-project-goals/issues/398#issuecomment-3571897575

Comment by [Weihang Lo][] posted on 2025-11-24:

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.

  • https://github.com/rust-lang/cargo/pull/16203
  • https://github.com/rust-lang/cargo/pull/16282

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.

Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

1 detailed update available.

Comment by [Jane Lusby][] posted on 2025-11-21:

linking this here so people know why there hasn't been any progress on this project goal.

#t-compiler > 2025H2 Goal Review @ 💬

Rework Cargo Build Dir Layout (rust-lang/rust-project-goals#401)
Progress
Point of contact

Ross Sullivan

Champions

cargo (Weihang Lo)

Task owners

Ross Sullivan

3 detailed updates available.

Comment by [Ross Sullivan][] posted on 2026-01-15:

Status update January 15, 2026

Fine grain locking for build-dir was merged in https://github.com/rust-lang/cargo/pull/16155 and now available on nightly via -Zfine-grain-locking unstable flag. 🎉

There are some known issues we'd like to address before doing a formal call for testing. Notably, improving blocking messages, fixing potential thread starvation in Cargo's job queue when locks block, and investigate increasing rlimits to reduce risk of hitting max file descriptors for large projects.

I am hopeful that these issues will be resolved over the coming month and we can do a call for testing to start gathering feedback from the community on whether the new locking strategy improves workflows.

Comment by [Ross Sullivan][] posted on 2025-12-23:

Status update December 23, 2025

The majority of December was spent iterating on https://github.com/rust-lang/cargo/pull/16155 . As mentioned in the previous update, the original locking design was not correct and we have been working through other solutions.

As locking is tricky to get right and there are many scenarios Cargo needs to support, we are trying to descope the initial implementation to an MVP, even if that means we lose some of the concurrency. Once we have an MVP on nightly, we can start gathering feedback on the scenarios that need improvement and iterate.

I'm hopeful that we get an unstable -Zfine-grain-locking on nightly in January for folks to try out in their workflows.


Also we are considering adding an opt-in for the new build-dir layout using an env var (CARGO_BUILD_DIR_LAYOUT_V2=true) to allow tool authors to begin migrating to the new layout. https://github.com/rust-lang/cargo/pull/16336

Before stabilizing this, we are doing crater run to test the impact of the changes and proactively reaching out to projects to minimize breakage as much as possible. https://github.com/rust-lang/rust/pull/149852

Comment by [Ross Sullivan][] posted on 2025-11-21:

Status update November 21, 2025

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.

Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

4 detailed updates available.

Comment by [Ed Page][] posted on 2026-02-13:

Key developments

  • FCP has ended on frontmatter support, just awaiting merge (https://github.com/rust-lang/rust/pull/148051)
  • Cargo script has entered FCP (https://github.com/rust-lang/cargo/pull/16569)

Blockers

  • Potential issues around edition, see https://github.com/rust-lang/rust/issues/152254
Comment by [Ed Page][] posted on 2026-01-14:

Key developments

  • #146377 has been decided and merged

Blockers

  • T-lang discussing CR / text direction feedback: https://github.com/rust-lang/rust/pull/148051#issuecomment-3638326490
  • T-rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-12-15:

Key developments

  • A fence length limit was added in response to T-lang feedback (https://github.com/rust-lang/rust/pull/149358)
  • Whether to disallow or lint for CR inside of a frontmatter is under discussion (https://github.com/rust-lang/rust/pull/149823)

Blockers

  • https://github.com/rust-lang/rust/pull/146377
  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-11-21:

Key developments

  • rust-lang/rust#148051

Blockers:

  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Stabilize public/private dependencies (rust-lang/rust-project-goals#272)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page)

Task owners

Help wanted, Ed Page

No detailed updates available.

compiler Team Champion Reports

This section contains champion reports for the compiler team.

Recent updates

The Rust project is currently working towards a slate of 17 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

3 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rfcs#3873 has been merged and an FCP has been started on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 - those both have some feedback for me to respond to that I'll get to as soon as I can

Comment by [David Wood][] posted on 2025-12-15:

rust-lang/rfcs#3873 is waiting on one checkbox before entering the final comment period. We had our sync meeting on the 11th and decided that we would enter FCP on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 after rust-lang/rfcs#3873 is accepted. We've responded to almost all of the feedback on the next two RFCs and expect the FCP to act as a forcing-function so that the relevant teams take a look, they can always register concerns if there are things we need to address, and if we need to make any major changes then we'll restart the FCP.

Comment by [David Wood][] posted on 2025-11-22:

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.

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

3 detailed updates available.

Comment by [Joel Marcey][] posted on 2026-01-31:

The effort to fill the contracting role to support this project goal is in the process winding down. The interview and discussion process is nearly complete. We expect to make a final decision for the role in early February.

Comment by [Joel Marcey][] posted on 2026-01-20:

The Rust Foundation is opening up a short-term, approximately 3-month, contracting role to assist in our Rust/C++ Interop initiative. The primary work and deliverables for the role will be to make substantial progress on the Problem Space Mapping Rust Project Goal by collecting discrete problem statements and offering up recommendations on the work that should follow based upon the problems that you found.



If you are interested in how programming languages interoperate, are curious in understanding the problems therein, and are have a passion to think about how those problems may be resolved for the betterment of interop, then this work may be for you.

An ideal candidate will have experience with Rust programming. Having experience in C++ is strongly preferred as well. If you have direct experience with actual engineering that required interoperating between Rust and C++ codebases, that's even better.



If you are interested, please email me (email address found in my GitHub profile) or contact me directly on Zulip by Tuesday, January 27 and we can take it from there to see if there may be a potential fit for further discussion.

Thank you.

Comment by [Jon Bauman][] posted on 2025-11-26:

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.

Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

2 detailed updates available.

Comment by [Frank King][] posted on 2025-12-18:
Comment by [Frank King][] posted on 2025-11-21:

Status update:

Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

2 detailed updates available.

Comment by [Ian McCormack][] posted on 2026-01-09:

Here's our January status update!

  • Yesterday, we posted an MCP for our retag intrinsics. While that's in progress, we'll start adapting our current prototype to remove our dependence on MIR-level retags. Once that's finished, we'll be ready to submit a PR.

  • We published our first monthly blog post about BorrowSanitizer.

  • Our overall goal for 2026 is to transition from a research prototype to a functional tool. Three key features have yet to be implemented: garbage collection, error reporting, and support for atomic memory accesses. Once these are complete, we'll be able to start testing real-world libraries and auditing our results against Miri.

Comment by [Ian McCormack][] posted on 2025-12-16:

Here's our December status update!

  • We have revised our prototype of the pre-RFC based on Ralf Jung's feedback. Now, instead of having two different retag functions for operands and places, we emit a single __rust_retag intrinsic in every situation. We also track interior mutability precisely. At this point, the implementation is mostly stable and seems to be ready for an MCP.

  • There's been some discussion here and in the pre-RFC about whether or not Rust will still have explicit MIR retag statements. We plan on revising our implementation so that we no longer rely on MIR retags to determine where to insert our lower-level retag calls. This should be a relatively straightforward change to the current prototype. If anything, it should make these changes easier to merge upstream, since they will no longer affect Miri.

  • BorrowSanitizer continues to gain new features, and we've started testing it on our first real crate (lru) (which has uncovered a few new bugs in our implementation). The two core Tree Borrows features that we have left to support are error reporting and garbage collection. Once these are finished, we will be able to expand our testing to more real-world libraries and confirm that we are passing each of Miri's test cases (and likely find more bugs lurking in our implementation). Our instrumentation pass ignores global and thread-local state for now, and it does not support atomic memory accesses outside of atomic load and store instructions. These operations should be relatively straightforward to add once we've finished higher-priority items.

  • Performance is slow. We do not know exactly how slow yet, since we've been focusing on feature support over benchmarking and optimization. This is at least partially due to the lack of garbage collection, based on what we're seeing from profiling. We will have a better sense of what our performance is like once we can compare against Miri on more real-world test cases.

As for what's next, we plan on posting an MCP soon, now that it's clear that we will be able to do without MIR retags. You can expect a more detailed status update on BorrowSanitizer by the end of January. This will discuss our implementation and plans for 2026. We will post that here and on our project website.

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

4 detailed updates available.

Comment by [Manuel Drehwald][] posted on 2026-01-16:

Key developments:

std::autodiff is moving closer to nightly, and std::offload is gaining various performance, feature, and hardware support improvements.

autodiff

Jakub Beránek, @sgasho, and I continued working on enabling autodiff in nightly. We have a PR up that builds autodiff in CI, and verified that the artifacts can be installed and work on Linux. For apple however, we noticed that any autodiff usage hangs. After some investigation, it turns out that we ended up embedding two LLVM copies, one in rustc, and one in Enzyme. It should be comparably easy to get rid of the second one. Once we verified that this fixes the build, we'll merge the PR to enable autodiff on both targets in nightly.

offload

A lot of interesting updates on the performance, feature, and hardware support side.

  1. Marcelo Domínguez, @kevinsala, @jdoerfert, and I started implementing the first benchmarks, since that's generally the best way to find missing features or performance issues. We were positively surprised by how good the out-of-the-box performance was. We will implement a few more benchmarks and post the results once we have verified them. We also implemented multiple PRs which implement bugfixes, cleanups, and needed features like support for scalars. We also started working on LLVM optimizations which make sure that we can achieve even better performance.

  2. I noticed that our offload intrinsic allowed running Rust code on the GPU, but it wasn't of much help when calling gpu vendor libraries like cuBLAS. In https://github.com/rust-lang/rust/pull/150683 I implemented a new helper intrinsic which allows calling those functions conveniently, without having to manually move data to or from the device. It will benefit from the same LLVM optimizations as our full offload intrinsic. It also a bit simpler to set up on the compiler and linker side, so it already works with std and mangled kernel names, something that we still have to improve for our main offload intrinsic.

  3. A lot of work happened on the LLVM offload side for SPIRV and Intel GPU support. At the moment, our Rust frontend is tested on NVIDIA and AMD server and consumer GPUs, as well as AMD HPC and Lapotop APUs. Karol Zwolak reached out since he wants to help with with also running Rust on Intel GPUs. Offload relies on LLVM which started gaining Intel support, so hopefully we won't need much work beyond a new intel-gpu target and a new stdarch module. There is also work on a new spirv target for rustc, which we could also support if it goes through LLVM. Due to some open questions around typed pointers it does not seem clear yet whether it will, so we will have to wait.

  4. Nikita started working on updating our submodule to LLVM 22. This hopefully does not only brings some compile and runtime performance improvements, but also greatly simplifies how we can build and use offload. Once it landed I'll refactor our bootstraping logic, and as part of that start building offload in CI.

Comment by [Manuel Drehwald][] posted on 2025-12-26:

Time for the next round of updates. Again, most of the updates were on the GPU side, but with some notable autodiff improvements too.

autodiff:

  1. @sgasho finished his work on using dlopen to load enzyme and the pr landed. This allowed Jakub Beránek and me to start working on distributing Enzyme via a standalone component.

  2. As a first step, I added a nicer error if we fail to find or dlopen our Enzyme backend. I also removed most of our autodiff fallbacks, we now unconditionally enable our macro frontend on nightly: https://github.com/rust-lang/rust/pull/150133 You may notice that cargo expand now works on autodiff code. This also allowed the first bug reports about ICE (internal compiler error) in our macro parser logic.

  3. Kobzol opened a PR to build Enzyme in CI. In theory, I should have been able to download that artifact, put it into my sysroot, and use the latest nightly to automatically load it. If that had worked, we could have just merged his PR, and everyone could have started using AD on nightly. Of course, things are never that easy. Even though both Enzyme, LLVM, and rustc were built in CI, the LLVM version shipped along with rustc does not seem compatible with the LLVM version Enzyme was built against. We assume some slight cmake mismatch during our CI builds, which we will have to debug.

offload:

  1. On the gpu side, Marcelo Domínguez finished his cleanup PR, and along the way also fixed using multiple kernels within a single codebase. When developing the offload MVP I had taken a lot of inspiration from the LLVM-IR generated by clang - and it looks like I had gotten one of the (way too many) LLVM attributes wrong. That caused some metadata to be fused when multiple kernels are present, confusing our offload backend. We started to find more bugs when working on benchmarks, more about the fixes for those in the next update.

  2. I finished cleaning up my offload build PR, and Oliver Scherer reviewed and approved it. Once the dev-guide gets synced, you should see much simpler usage instructions. Now it's just up to me to automate the last part, then you can compile offload code purely with cargo or rustc. I also improved how we build offload, which allows us to build it both in CI and locally. CI had some very specific requirements to not increase build times, since our x86-64-dist runner is already quite slow.

  3. Our first benchmarks directly linked against NVIDIA and AMD intrinsics on llvm-ir level. However, we already had an nvptx Rust module for a while, and since recently also an amdgpu module which nicely wraps those intrinsics. I just synced the stdarch repository into rustc a few minutes ago, so from now on, we can replace both with the corresponding Rust functions. In the near future we should get a higher level GPU module, which abstracts away naming differences between vendors.

  4. Most of my past rustc contributions were related to LLVM projects or plugins (Offload and Enzyme), and I increasingly encountered myself asking other people for updates or backports of our LLVM submodule, since upstream LLVM has fixes which were not yet merged into our LLVM submodule. Our llvm working group is quite small and I didn't want to burden them too much with my requests, so I recently asked them to join it, which also got approved. In the future I intend to help a little with the maintenance here.

Comment by [Manuel Drehwald][] posted on 2025-12-02:

It's only been two weeks, but we got a good number of updates, so I already wanted to share them.

autodiff

  1. On the autodiff side, we landed the support for rlib and better docs. This means that our autodiff frontend is "almost" complete, since there are almost no cases left where you can't apply autodiff. There are a few features like custom-derivatives or support for dyn arguments that I'd like to add, but they are currently waiting for better docs on the Enzyme side. There is also a long-term goal off replacing the fat-lto requirement with the less invasive embed-bc requirement, but this proved to be tricky in the past and only affects compile times.
  2. @sgasho picked up my old PR to dlopen enzyme, and found the culprit of it failing after my last rebase. A proper fix might take a bit longer, but it might be worth waiting for. As a reminder, using dlopen in the future allows us to ship autodiff on nightly without increasing the size of rustc and therefore without making our infra team sad.

All in all, we have landed most of the hard work here, so that's a very comfortable position to be in before enabling it on nightly.

offload

  1. We have landed the intrinsic implementation of Marcelo Domínguez, so now you can offload functions with almost arbitrary arguments. In my first prototype, I had limited it to pointers to 256 f64 values. The updated usage example continues to live here in our docs. As you can see, we still require #[cfg(target_os=X)] annotations. Under the hood, the LLVM-IR which we generate is also still a bit convoluted. In his next PRs, he'll clean up the generated IR, and introduce an offload macro that users shall call instead of the internal offload intrinsic.
  2. I spend more time on enabling offload in our CI, to enable std::offload in nightly. After multiple iterations and support from LLVM offload devs, we found a cmake config that does not run into bugs, should not increase Rust CI time too much, and works with both in-tree llvm/clang builds, as well as external clang's (the current case in our Rust CI).
  3. I spend more time on simplifying the usage instructions in the dev guide. We started with two cargo calls, one rustc call, two clang calls, and two clang-helper binary calls. I was able to remove the rustc and one of the clang-offload-packager calls, by directly calling the underlying LLVM APIs. I also have an unmerged PR which removes the two clang calls. Once I cleaned it up and landed it, we would be down to only two cargo calls and one binary call to clang-linker-wrapper. Once I automated this last wrapper (and enabled offload in CI), nightly users should be able to experiment with std::offload.
Comment by [Manuel Drehwald][] posted on 2025-11-19:

Automatic Differentiation

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.

  1. As part of my cleanup I went through old issues, and realized we now partly support rlib's! That's a huge improvement, because it means you can use autodiff not only in your 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.
  2. I started documentation improvements in https://github.com/rust-lang/rust/pull/149082 and https://github.com/rust-lang/rust/pull/148201, which should be visible on the website from tomorrow onwards. They are likely still not perfect, so please keep opening issues if you have questions.
  3. We now provide a helpful error message if a user forgets enabling lto=fat: https://github.com/rust-lang/rust/pull/148855
  4. After two months of work, @sgasho managed to add Rust CI to enzyme! Unfortunately, Enzyme devs broke and disabled it directly, so we'll need to talk about maintaining it as part of shipping Enzyme in nightly.

I have the following elements on my TODO list as part shipping AD on nightly

  1. Re-enable macOS build (probably easy)
  2. Talk with Enzyme Devs about maintenance
  3. Merge rlib support (under review)
  4. upstream ADbenchmarks from r-l/enzyme to r-l/r as codegen tests (easy)
  5. Write a block post/article for https://blog.rust-lang.org/inside-rust/

GPU offload

  1. The llvm dev talk about GPU programming went great, I got to talk to a lot of other developers in the area of llvm offload. I hope to use some of the gained knowledge soon. Concrete steps planned are the integration of libc-gpu for IO from kernels, as well as moving over my code from the OpenMP API to the slightly lower level liboffload API.
  2. We confirmed that our gpu offload prototype works on more hardware. By now we have the latest AMD APU generation covered, as well as an MI 250X and an RTX 4050. My own Laptop with a slightly older AMD Ryzen 7 PRO 7840U unfortunately turned out to be not supported by AMD drivers.
  3. The offload intrinsic PR by Marcelo Domínguez is now marked as ready, and I left my second round of review. Hopefully, we can land it soon!
  4. I spend some time trying to build and potentially ship the needed offload changes in nightly, unfortunately I still fail to build it in CI: https://github.com/rust-lang/rust/pull/148671.

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.

Getting Rust for Linux into stable Rust: compiler features (rust-lang/rust-project-goals#407)
Progress
Point of contact

Tomas Sedovic

Champions

compiler (Wesley Wiser)

Task owners

(depending on the flag)

4 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2026-01-16:

Update from the 2026-01-14 meeting:

#![register_tool] rust#66079

Tyler Mandry proposed FCP of the RFC#3808 and nominated it for a Lang discussion.

-Zdebuginfo-compression rust#120953

Wesley Wiser proposed stabilization: rust#150625.

Josh Triplett suggested trying to bring zlib-rs in the kernel as a case study.

-Zdirect-access-external-data rust#127488

rust#150494 was merged two days ago, what reminds is updating the documentation and stabilizing the feature.

There's an ongoing discussion about the feature on the Rust Zulip as well.

Comment by [Tomas Sedovic][] posted on 2025-12-05:

Update from the 2025-12-03 meeting:

-Zharden-sls

Wesley reviewed it again, provided a qualification, more changes requested.

Comment by [Tomas Sedovic][] posted on 2025-11-28:

Update form the 2025-11-19 meeting:

-Zharden-sls / rust#136597

Andrew addressed the comment and rebased the PR. It's waiting for a review again.

#![register_tool] / rust#66079

Tyler 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.

Comment by [Tomas Sedovic][] posted on 2025-11-19:

Update from the 2025-11-05 meeting.

-Zharden-sls / rust#136597

Wesley Wiser left a comment on the PR, Andr

-Zno-jump-tables / rust#145974

Merged, expected to ship in Rust 1.93. The Linux kernel added support for the new name for the option (-Cjump-tables=n).

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

3 detailed updates available.

Comment by [Eric Holk][] posted on 2025-12-06:

Hi @sladyn98 - feel free to ping me on Zulip about this.

Comment by [Ed Page][] posted on 2025-12-03:

The work is more on the compiler side atm, so Eric Holk and b-naber could speak more to where they could use help.

Comment by @sladyn98 posted on 2025-12-03:

Ed Page hey i would like to contribute to this I reached out on zulip. Bumping up the post in case it might have gone under the radar

CC Niko Matsakis

Production-ready cranelift backend (rust-lang/rust-project-goals#397)
Progress Will not complete
Point of contact

Folkert de Vries

Champions

compiler (bjorn3)

Task owners

bjorn3, Folkert de Vries, [Trifecta Tech Foundation]

1 detailed update available.

Comment by [Folkert de Vries][] posted on 2025-12-01:

We did not receive the funding we needed to work on this goal, so no progress has been made.

Overall I think the improvements we felt comfortable promising are on the low side. Overall the amount of time spent in codegen for realistic changes to real code bases was smaller than expected, meaning that the improvements that cranelift can deliver for the end-user experience are smaller.

We still believe larger gains can be made with more effort, but did not feel confident in promising hard numbers.

So for now, let's close this.

Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

1 detailed update available.

Comment by [Aapo Alasuutari][] posted on 2025-12-17:

Purpose

A refresher on what we want to achieve here: the most basic form of reborrowing we want to enable is this:

#![allow(unused)]
fn main() {
// Note: not Clone or Copy
#[derive(Reborrow)]
struct MyMutMarker<'a>(...);

// ...

let marker: MyMarkerMut = MyMutMarker::new();
some_call(marker);
some_call(marker);
}

ie. make it possible for an owned value to be passed into a call twice and have Rust inject a reborrow at each call site to produce a new bitwise copy of the original value for the passing purposes, and mark the original value as disabled for reads and writes for the duration of the borrow.

A notable complication appears with implementing such reborrowing in userland using explicit cals when dealing with returned values:

#![allow(unused)]
fn main() {
return some_call(marker.reborrow());
}

If the borrowed lifetime escapes through the return value, then this will not compile as the borrowed lifetime is based on a value local to this function. Alongside convenience, this is the major reason for the Reborrow traits work.

CoerceShared is a secondary trait that enables equivalent reborrowing that only disables the original value for writes, ie. matching the &mut T to &T coercion.

Update

We have the Reborrow trait working, albeit currently with a bug in which the marker must be bound as let mut. We are working towards a working CoerceShared trait in the following form:

#![allow(unused)]
fn main() {
trait CoerceShared<Target: Copy> {}
}

Originally the trait had a type Target ADT but this turned out to be unnecessary, as there is no reason to particularly disallow multiple coercion targets. The original reason for using an ADT to disallow multiple coercion targets was based on the trait also having an unsafe method, at which point unscrupulous users could use the trait as a generic coercion trait. Because the trait method was found to be unnecessary, the fear is also unnecessary.

This means that the trait has better chances of working with multiple coercing lifetimes (think a collection of &muts all coercing to &s, or only some of them). However, we are currently avoiding any support of multiple lifetimes as we want to avoid dealing with rmeta before we have the basic functionality working.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

3 detailed updates available.

Comment by [Oliver Scherer][] posted on 2026-02-09:
  • @BD103 added slices, arrays and raw pointer support
    • https://github.com/rust-lang/rust/pull/151019
    • https://github.com/rust-lang/rust/pull/151031
    • https://github.com/rust-lang/rust/pull/151118
    • https://github.com/rust-lang/rust/pull/151119
  • Asuna added all of our primitives
    • https://github.com/rust-lang/rust/pull/151123
  • Jamie Hill-Daniel gave us references
    • https://github.com/rust-lang/rust/pull/151222
  • @izagawd made it possible to extract some info from dyn Trait
    • https://github.com/rust-lang/rust/pull/151239

There is ongoing work for Adts and function pointers, both of which will land as MVPs and will need some work to make them respect semver or generally become useful in practice

Removing the 'static bound from try_as_dyn turned out to have many warts, so I'm limiting it to a much smaller subset and will have borrowck emit the 'static requirement if the other rules do not apply (instead of having an unconditional 'static requirement)

Comment by [Oliver Scherer][] posted on 2026-01-14:
  • https://github.com/rust-lang/rust/pull/146923 has landed, and we even got the first contribs adding array support to reflection.
    • there are lots more types and type information that we could support, and it's rather easy to add more. Happy to review any work here.
  • https://github.com/rust-lang/rust/pull/150033 has landed, and I'm working on removing the 'static requirement in https://github.com/rust-lang/rust/pull/150161
Comment by [Oliver Scherer][] posted on 2025-12-15:

Updates

  • https://github.com/rust-lang/rust/pull/148820 adds a way to mark functions and intrinsics as only callable during CTFE
  • https://github.com/rust-lang/rust/pull/144363 has been unblocked and just needs some minor cosmetic work

Blockers

  • https://github.com/rust-lang/rust/pull/146923 (reflection MVP) has not been reviewed yet
Relink don't Rebuild (rust-lang/rust-project-goals#400)
Progress Will not complete
Point of contact

Jane Lusby

Champions

cargo (Weihang Lo), compiler (Oliver Scherer)

Task owners

@dropbear32, @osiewicz

1 detailed update available.

Comment by [Jane Lusby][] posted on 2025-11-21:

linking this here so people know why there hasn't been any progress on this project goal.

#t-compiler > 2025H2 Goal Review @ 💬

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-11-19:

This project goal has been completed. I updated the first issue to reflect it. Closing the issue then.

rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

2 detailed updates available.

Comment by [Jakub Beránek][] posted on 2025-12-15:

We have enabled the second x64 machine, so we now have benchmarks running in parallel 🎉 There are some smaller things to improve, but next year we can move onto running benchmarks on Arm collectors.

Comment by [Jakub Beránek][] posted on 2025-11-19:

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.

SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

5 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rust#143924 has been merged, enabling scalable vector types to be defined on nightly, and I'm working on a patch to introduce unstable intrinsics/scalable vector types to std::arch

Comment by [Niko Matsakis][] posted on 2025-12-19:

Update to the previous post.

Tyler Mandry pointed me at this thread, where lcnr posted this nice blog post that he wrote detailing more about (C).

Key insights:

  • Because the use of size_of_val would still cause post-mono errors when invoked on types that are not SizeOfVal, you know that adding SizeOfVal into the function's where-clause bounds is not a breaking change, even though adding a where clause is a breaking change more generally.
  • But, to David Wood's point, it does mean that there is a change to Rust's semver rules: adding size_of_val would become a breaking change, where it is not today.

This may well be the best option though, particularly as it allows us to make changes to the defaults across-the-board. A change to Rust's semver rules is not a breaking change in the usual sense. It is a notable shift.

Comment by [Niko Matsakis][] posted on 2025-12-18:

Update: David and I chatted on Zulip. Key points:

David has made "progress on the non-Sized Hierarchy part of the goal, the infrastructure for defining scalable vector types has been merged (with them being Sized in the interim) and that'll make it easier to iterate on those and find issues that need solving".

On the Sized hierarchy part of the goal, no progress. We discussed options for migrating. There seem to be three big options:

(A) The conservative-but-obvious route where the T: Derefin the old edition is expanded to T: Deref<Target: SizeOfVal> (but in the new edition it means T: Deref<Target: Pointee>, i.e., no additional bounds). The main downside is that new Edition code using T: Deref can't call old Edition code using T: Deref as the old edition code has stronger bounds. Therefore new edition code must either use stronger bounds than it needs or wait until that old edition code has been updated.

(B) You do something smart with Edition.Old code where you figure out if the bound can be loose or strict by bottom-up computation. So T: Deref in the old could mean either T: Deref<Target: Pointee> or T: Deref<Target: SizeOfVal>, depending on what the function actually does.

(C) You make Edition.Old code always mean T: Deref<Target: Pointee> and you still allow calls to size_of_val but have them cause post-monomorphization errors if used inappropriately. In Edition.New you use stricter checking.

Options (B) and (C) have the downside that changes to the function body (adding a call to size_of_val, specifically) in the old edition can stop callers from compiling. In the case of Option (B), that breakage is at type-check time, because it can change the where-clauses. In Option (C), the breakage is post-monomorphization.

Option (A) has the disadvantage that it takes longer for the new bounds to roll out.

Given this, (A) seems the preferred path. We discussed options for how to encourage that roll-out. We discussed the idea of a lint that would warn Edition.Old code that its bounds are stronger than needed and suggest rewriting to T: Deref<Target: Pointee> to explicitly disable the stronger Edition.Old default. This lint could be implemented in one of two ways

  • at type-check time, by tracking what parts of the environment are used by the trait solver. This may be feasible in the new trait solver, someone from @rust-lang/types would have to say.
  • at post-mono time, by tracking which functions actually call size_of_val and propagating that information back to callers. You could then compare against the generic bounds declared on the caller.

The former is more useful (knowing what parts of the environment are necessary could be useful for more things, e.g., better caching); the latter may be easier or more precise.

Comment by [David Wood][] posted on 2025-12-15:

I haven't made any progress on Deref::Target yet, but I have been focusing on landing rust-lang/rust#143924 which has went through two rounds of review and will hopefully be approved soon.

Comment by [David Wood][] posted on 2025-11-22:

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

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

crates-io Team Champion Reports

This section contains champion reports for the crates-io team.

Recent updates

The Rust project is currently working towards a slate of 1 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Implement Open API Namespace Support (rust-lang/rust-project-goals#256)
Progress
Point of contact

Help Wanted

Champions

cargo (Ed Page), compiler (b-naber), crates-io (Carol Nichols)

Task owners

b-naber, Ed Page

3 detailed updates available.

Comment by [Eric Holk][] posted on 2025-12-06:

Hi @sladyn98 - feel free to ping me on Zulip about this.

Comment by [Ed Page][] posted on 2025-12-03:

The work is more on the compiler side atm, so Eric Holk and b-naber could speak more to where they could use help.

Comment by @sladyn98 posted on 2025-12-03:

Ed Page hey i would like to contribute to this I reached out on zulip. Bumping up the post in case it might have gone under the radar

CC Niko Matsakis

infra Team Champion Reports

This section contains champion reports for the infra team.

Recent updates

The Rust project is currently working towards a slate of 2 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Run more tests for GCC backend in the Rust's CI (rust-lang/rust-project-goals#402)
Progress Completed
Point of contact

Guillaume Gomez

Champions

compiler (Wesley Wiser), infra (Marco Ieni)

Task owners

Guillaume Gomez

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-11-19:

This project goal has been completed. I updated the first issue to reflect it. Closing the issue then.

rustc-perf improvements (rust-lang/rust-project-goals#275)
Progress
Point of contact

James

Champions

compiler (David Wood), infra (Jakub Beránek)

Task owners

James, Jakub Beránek, David Wood

2 detailed updates available.

Comment by [Jakub Beránek][] posted on 2025-12-15:

We have enabled the second x64 machine, so we now have benchmarks running in parallel 🎉 There are some smaller things to improve, but next year we can move onto running benchmarks on Arm collectors.

Comment by [Jakub Beránek][] posted on 2025-11-19:

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.

lang Team Champion Reports

This section contains champion reports for the lang team.

Recent updates

The Rust project is currently working towards a slate of 17 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

3 detailed updates available.

Comment by [Joel Marcey][] posted on 2026-01-31:

The effort to fill the contracting role to support this project goal is in the process winding down. The interview and discussion process is nearly complete. We expect to make a final decision for the role in early February.

Comment by [Joel Marcey][] posted on 2026-01-20:

The Rust Foundation is opening up a short-term, approximately 3-month, contracting role to assist in our Rust/C++ Interop initiative. The primary work and deliverables for the role will be to make substantial progress on the Problem Space Mapping Rust Project Goal by collecting discrete problem statements and offering up recommendations on the work that should follow based upon the problems that you found.



If you are interested in how programming languages interoperate, are curious in understanding the problems therein, and are have a passion to think about how those problems may be resolved for the betterment of interop, then this work may be for you.

An ideal candidate will have experience with Rust programming. Having experience in C++ is strongly preferred as well. If you have direct experience with actual engineering that required interoperating between Rust and C++ codebases, that's even better.



If you are interested, please email me (email address found in my GitHub profile) or contact me directly on Zulip by Tuesday, January 27 and we can take it from there to see if there may be a potential fit for further discussion.

Thank you.

Comment by [Jon Bauman][] posted on 2025-11-26:

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

Boxy

Champions

lang (Niko Matsakis)

Task owners

Boxy, Noah Lev

7 detailed updates available.

Comment by [Niko Matsakis][] posted on 2026-02-13:

Latest updates:

Boxy and I have met (and continue to meet) and work on modeling const generics in a-mir-formality. We're still working on laying the groundwork.

There is a proposed project goal for next year: https://rust-lang.github.io/rust-project-goals/2026/const-generics.html

Comment by [Boxy][] posted on 2026-01-30:

In addition to what niko posted previously there's been a lot of other stuff happening. A lot of people have opened PRs to improve mGCA this month: León Orell Valerian Liehr Noah Lev @enthropy7 Kivooeo @mu001999 @Human9000-bit Redddy @Keith-Cancel @AprilNEA

A rough list of things that have been improved for mGCA:

  • Lots of new expressions now supported by mGCA: const constructors, tuple constructor calls, array expressions, tuple expression, literals
  • associated_const_equality has been merged into min_generic_const_args. the former was effectively dependent on the latter already so this just makes it nicer to use the former :)
  • traits can now be dyn compatible if all associated constants are type consts and are specified in the trait object (e.g. dyn Trait<ASSOC = 10>)
  • type consts are enforced to be non-generic
  • a bunch of ICEs have been fixed
  • camelid has been working on "non-min" version of mGCA which will allow arbitrary expressions to be used in the type system (a blog post with more detail will be published once this actually lands)

In non-mGCA updates, as niko says, we've been meeting regularly to make progress on modelling const generics in a-mir-formality. I've also been spending time thinking about the interactions between adt_const_params and ADTs with privacy/safety invariants and I think I know how to structure the RFC in this area so can make progress on that again

There's some more detail about the various bits of work people have done and who did what here: #project-const-generics > perfectly adequately sized wins @ 💬

Comment by [Niko Matsakis][] posted on 2026-01-27:

Boxy and I have established a regular time to check-in on formalizing this within a-mir-formality. Today we mostly worked on the "model" of const values, starting with this

#![allow(unused)]
fn main() {
#[term]
pub enum ConstData {
    // Sort of equivalent to `ValTreeKind::Branch`
    #[cast]
    RigidValue(RigidConstData),

    // Sort of equivalent to `ValTreeKind::Leaf`
    #[cast]
    Scalar(ScalarValue),

    #[variable(ParameterKind::Const)]
    Variable(Variable),
}



#[term]
pub enum ScalarValue {
    #[grammar(u8($v0))]
    U8(u8),
    #[grammar(u16($v0))]
    U16(u16),
    #[grammar(u32($v0))]
    U32(u32),
    #[grammar(u64($v0))]
    U64(u64),
    #[grammar(i8($v0))]
    I8(i8),
    #[grammar(i16($v0))]
    I16(i16),
    #[grammar(i32($v0))]
    I32(i32),
    #[grammar(i64($v0))]
    I64(i64),
    #[grammar($v0)]
    Bool(bool),
    #[grammar(usize($v0))]
    Usize(usize),
    #[grammar(isize($v0))]
    Isize(isize),
}


#[term($name $<parameters> { $,values })]
pub struct RigidConstData {
    pub name: RigidName,
    pub parameters: Parameters,
    pub values: Vec<Const>,
}
}

i.e., a const value can be a scalar value (as today) or a struct literal like Foo { ... } (which would also cover tuples and things). We got the various tests passing. Huzzah!

Comment by [Boxy][] posted on 2025-12-30:

Ah another thing I forgot to mention. David Wood spent some time looking into the name mangling scheme for adt_const_params stuff to make sure it would be fine to stabilize and it seems it is so that's another step closer to adt_const_params being stabilizable

Comment by [Boxy][] posted on 2025-12-30:

Ah I forgot to mention, even though MGCA has a tonne of work left to do I expect it should be somewhat approachable for people to help out with. So if people are interested in getting involved now is a good time :)

Comment by [Boxy][] posted on 2025-12-30:

Since the last update both of my PRs I mentioned have landed, allowing for constructing ADTs in const arguments while making use of generic parameters. This makes MGCA effectively a "full" prototype where it can now fully demonstrate the core concept of the feature. There's still a lot of work left to do but now we're at the point of finishing out the feature :)

Once again huge thanks to camelid for sticking with me throughout this. Also thanks to errs, oli and lcnr for reviewing some of the work and chatting with me about possible impl decisions.

Some examples of what is possible with MGCA as of the end of this goal cycle:

#![allow(unused)]
#![feature(const_default, const_trait_impl, min_generic_const_args)]

fn main() {
trait Trait {
    #[type_const]
    const ASSOC: usize;
}

fn mk_array<T: const Default + Trait>() -> [T; T::ASSOC] {
    [const { T::default() }; _]
}
}
#![allow(unused)]
#![feature(adt_const_params, min_generic_const_args)]

fn main() {
fn foo<const N: Option<u32>>() {}

trait Trait {
    #[type_const]
    const ASSOC: usize;
}

fn bar<T: Trait, const N: u32>() {
    // the initializer of `_0` is a `N` which is a legal const argument
    // so this is ok.
    foo::<{ Some::<u32> { 0: N } }>();

    // this is allowed as mgca supports uses of assoc consts in the
    // type system. ie `<T as Trait>::ASSOC` is a legal const argument
    foo::<{ Some::<u32> { 0: <T as Trait>::ASSOC } }>();

    // this on the other hand is not allowed as `N + 1` is not a legal
    // const argument
    foo::<{ Some::<u32> { 0: N + 1 } }>(); // ERROR
}
}

As for adt_const_params we now have a zulip stream specifically for discussion of the upcoming RFC and the drafting of the RFC: #project-const-generics/adt_const_params-rfc. I've gotten part of the way through actually writing the RFC itself though it's gone slower than I had originally hoped as I've also been spending more time thinking through the implications of allowing private data in const generics.

I've debugged the remaining two ICEs making adt_const_params not fully ready for stabilization and written some brief instructions on how to resolve them. One ICE has been incidentally fixed (though more masked) by some work that Kivooeo has been doing on MGCA. The other has been picked up by someone I'm not sure the github handle of so that will also be getting fixed soon.

Comment by [Boxy][] posted on 2025-11-29:

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.

Continue Experimentation with Pin Ergonomics (rust-lang/rust-project-goals#389)
Progress
Point of contact

Frank King

Champions

compiler (Oliver Scherer), lang (TC)

Task owners

Frank King

2 detailed updates available.

Comment by [Frank King][] posted on 2025-12-18:
Comment by [Frank King][] posted on 2025-11-21:

Status update:

Design a language feature to solve Field Projections (rust-lang/rust-project-goals#390)
Progress
Point of contact

Benno Lossin

Champions

lang (Tyler Mandry)

Task owners

Benno Lossin

TL;DR.
  • 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.

7 detailed updates available.

Comment by [Benno Lossin][] posted on 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.

Comment by [Benno Lossin][] posted on 2026-01-01:

TL;DR:

Comment by [Benno Lossin][] posted on 2025-12-25:

Wiki Project

We started a wiki project at https://rust-lang.github.io/beyond-refs to map out the solution space. We intend to grow it into the single source of truth for the current state of the field projection proposal as well as unfinished and obsolete ideas and connections between them. Additionally, we will aim to add the same kind of information for the in-place initialization effort, since it has overlap with field projections and, more importantly, has a similarly large solution space.

In the beginning you might find many stub pages in the wiki, which we will work on making more complete. We will also mark pages that contain old or abandoned ideas as such as well as mark the current proposal.

This issue will continue to receive regular detailed updates, which are designed for those keeping reasonably up-to-date with the feature. For anyone out of the loop, the wiki project will be a much better place when it contains more content.

Comment by [Benno Lossin][] posted on 2025-12-20:

Field-by-Field Projections vs One-Shot Projections

We have used several different names for these two ways of implementing projections. The first is also called 1-level projections and the second multi-level projections.

The field-by-field approach uses field representing types (FRTs), which represent a single field of a struct with no indirection. When writing something like @x.y.z, we perform the place operation twice, first using the FRT field_of!(X, y) and then again with field_of!(T, z) where T is the resulting type of the first projection.

The second approach called one-shot projections instead extends FRTs with projections, these are compositions of FRTs, can be empty and dynamic. Using these we desugar @x.y.z to a single place operation.

Field-by-field projections have the advantage that they simplify the implementation for users of the feature, the compiler implementation and the mental model that people will have to keep in mind when interacting with field projections. However, they also have pretty big downsides, which either are fundamental to their design or would require significant complification of the feature:

  • They have less expressiveness than one-shot projections. For example, when moving out a subsubfield of x: &own Struct by doing let a = @x.field.a, we have to move out field, which prevents us from later writing let b = @x.field.b. One-shot projections allow us to track individual subsubfields with the borrow checker.
  • Field-by-field projections also make it difficult to define type-changing projections in an inference friendly way. Projecting through multiple fields could result in several changes of types in between, so we would have to require only canonical projections in certain places. However, this requires certain intermediate types for which defining their safety invariants is very complex.

We additionally note that the single function call desugaring is also a simplification that also lends itself much better when explaining what the @ syntax does.

All of this points in the direction of proceeding with one-shot projections and we will most likely do that. However, we must note that the field-by-field approach might yield easier trait definitions that make implementing the various place operations more manageable. There are several open issues on how to design the field-by-field API in the place variation (the previous proposal did have this mapped out clearly, but it does not translate very well to places), which would require significant effort to solve. So at this point we cannot really give a fair comparison. Our initial scouting of the solutions revealed that they all have some sort of limitation (as we explained above for intermediate projection types for example), which make field-by-field projections less desirable. So for the moment, we are set on one-shot projections, but when the time comes to write the RFC we need to revisit the idea of field-by-field projections.

Comment by [Benno Lossin][] posted on 2025-12-16:

Non-Indirected Containers

Types like MaybeUninit<T>, Cell<T>, ManuallyDrop<T>, RefCell<T> etc. currently do not fit into our virtual places model, since they don't have an indirection. They contain the place directly inline (and some are even repr(transparent)). For this reason, we currently don't have projections available for &mut MaybeUninit<T>.

Enter our new trait PlaceWrapper which these types implement in order to make projections available for them. We call these types place wrappers. Here is the definition of the trait:

#![allow(unused)]
fn main() {
pub unsafe trait PlaceWrapper<P: Projection<Source = Self::Target>>: HasPlace {
    type WrappedProjection: Projection<Source = Self>;

    fn wrap_projection(p: P) -> Self::WrappedProjection;
}
}

This trait should only be implemented when Self doesn't contain the place as an indirection (so for example Box must not implement the trait). When this trait is implemented, then Self has "virtual fields" available (actually all kinds of place projections). The name of these virtual fields/projections is the same as the ones of the contained place. But their output type is controlled by this trait.

As an example, here is the implementation for MaybeUninit:

#![allow(unused)]
fn main() {
impl<T, P: Projection<Source = T>> PlaceWrapper<P> for MaybeUninit<T> {
    type WrappedProjection = TransparentProjection<P, MaybeUninit<T>, MaybeUninit<P::Target>>;

    fn wrap_projection(p: P) -> Self::WrappedProjection {
        TransparentProjection(p, PhantomData, PhantomData)
    }
}
}

Where TransparentProjection will be available in the standard library defined as:

#![allow(unused)]
fn main() {
pub struct TransparentProjection<P, Src, Tgt>(P, PhantomData<Src>, PhantomData<Tgt>);

impl<P: Projection, Src, Tgt> Projection for TransparentProjection<P, Src, Tgt> {
    type Source = Src;
    type Target = Tgt;

    fn offset(&self) -> usize {
        self.0.offset()
    }
}
}

When there is ambiguity, because the wrapper and the wrapped types both have the same field, the wrapper's field takes precedence (this is the same as it currently works for Deref). It is still possible to refer to the wrapped field by first dereferencing the container, so x.field refers to the wrapper's field and (*x).field refers to the field of the wrapped type.

Comment by [Benno Lossin][] posted on 2025-12-12:

Canonical Projections

We have discussed canonical projections and come up with the following solution:

#![allow(unused)]
fn main() {
pub trait CanonicalReborrow: HasPlace {
    type Output<'a, P: Projection<Source = Self::Target>>: HasPlace<Target = P::Target>
    where
        Self: PlaceBorrow<'a, P, Self::Output<'a, P>>;
}
}

Implementing this trait permits using the syntax @$place_expr where the place's origin is of the type Self (for example @x.y where x: Self and y is an identifier or tuple index, or @x.y.z etc). It is desugared to be:

#![allow(unused)]
fn main() {
@<<Self as CanonicalReborrow>::Output<'_, projection_from_place_expr!($place_expr)>> $place_expr
}

(The names of the trait, associated type and syntax are not final, better suggestions welcome.)

Reasoning

  • We need the Output associated type to support the @x.y syntax for Arc and ArcRef.
  • We put the FRT and lifetime parameter on Output in order to force implementers to always provide a canonical reborrow, so if @x.a works, then @x.b also works (when b also is a field of the struct contained by x).
    • This (sadly or luckily) also has the effect that making @x.a and @x.b return different wrapper types is more difficult to implement and requires a fair bit of trait dancing. We should think about discouraging this in the documentation.
Comment by [Benno Lossin][] posted on 2025-12-07:

Since we have chosen virtual places as the new approach, we reviewed what open questions are most pressing for the design. Our discussion resulted in the following five questions:

  1. Should we have 1-level projections xor multi-level projections?
  2. What is the semantic meaning of the borrow checker rules (BorrowKind)?
  3. How should we add "canonical projections" for types such that we have nice and short syntax (like x~y or x.@y)?
  4. What to do about non-indirected containers (Cell, MaybeUninit, Mutex, etc)?
  5. How does one inspect/query Projection types?

We will focus on these questions in December as well as implementing FRTs.

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

2 detailed updates available.

Comment by [Pete LeVasseur][] posted on 2025-12-16:

Meeting notes here: FLS team meeting 2025-12-12

Key developments: We're close to completing the FLS release for 1.91.0, 1.91.1. We've started to operate as a team, merging a PR with the changelog entries, then opening up issues for each change required: ✅ #624(https://github.com/rust-lang/fls/issues/624), ✅ #625(https://github.com/rust-lang/fls/issues/625), ✅ #626(https://github.com/rust-lang/fls/issues/626), ⚠️ #623(https://github.com/rust-lang/fls/issues/623). #623(https://github.com/rust-lang/fls/issues/623) is still pending, as it requires a bit of alignment with the Reference on definitions and creation of a new example. Blockers: None currently Help wanted: We'd love more folks from the safety-critical community to contribute to picking up issues or opening an issue if you notice something is missing.

Comment by [Pete LeVasseur][] posted on 2025-11-21:

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.

Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

2 detailed updates available.

Comment by [Ian McCormack][] posted on 2026-01-09:

Here's our January status update!

  • Yesterday, we posted an MCP for our retag intrinsics. While that's in progress, we'll start adapting our current prototype to remove our dependence on MIR-level retags. Once that's finished, we'll be ready to submit a PR.

  • We published our first monthly blog post about BorrowSanitizer.

  • Our overall goal for 2026 is to transition from a research prototype to a functional tool. Three key features have yet to be implemented: garbage collection, error reporting, and support for atomic memory accesses. Once these are complete, we'll be able to start testing real-world libraries and auditing our results against Miri.

Comment by [Ian McCormack][] posted on 2025-12-16:

Here's our December status update!

  • We have revised our prototype of the pre-RFC based on Ralf Jung's feedback. Now, instead of having two different retag functions for operands and places, we emit a single __rust_retag intrinsic in every situation. We also track interior mutability precisely. At this point, the implementation is mostly stable and seems to be ready for an MCP.

  • There's been some discussion here and in the pre-RFC about whether or not Rust will still have explicit MIR retag statements. We plan on revising our implementation so that we no longer rely on MIR retags to determine where to insert our lower-level retag calls. This should be a relatively straightforward change to the current prototype. If anything, it should make these changes easier to merge upstream, since they will no longer affect Miri.

  • BorrowSanitizer continues to gain new features, and we've started testing it on our first real crate (lru) (which has uncovered a few new bugs in our implementation). The two core Tree Borrows features that we have left to support are error reporting and garbage collection. Once these are finished, we will be able to expand our testing to more real-world libraries and confirm that we are passing each of Miri's test cases (and likely find more bugs lurking in our implementation). Our instrumentation pass ignores global and thread-local state for now, and it does not support atomic memory accesses outside of atomic load and store instructions. These operations should be relatively straightforward to add once we've finished higher-priority items.

  • Performance is slow. We do not know exactly how slow yet, since we've been focusing on feature support over benchmarking and optimization. This is at least partially due to the lack of garbage collection, based on what we're seeing from profiling. We will have a better sense of what our performance is like once we can compare against Miri on more real-world test cases.

As for what's next, we plan on posting an MCP soon, now that it's clear that we will be able to do without MIR retags. You can expect a more detailed status update on BorrowSanitizer by the end of January. This will discuss our implementation and plans for 2026. We will post that here and on our project website.

Ergonomic ref-counting: RFC decision and preview (rust-lang/rust-project-goals#107)
Progress
Point of contact

Niko Matsakis

Champions

compiler (Santiago Pastorino), lang (Niko Matsakis)

Task owners

Niko Matsakis, Santiago Pastorino

No detailed updates available.
Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

1 detailed update available.

Comment by [Taylor Cramer][] posted on 2025-12-17:

Current status:

  • The RFC for auto impl supertraits has been updated to address SemVer compatibility issues.
  • There is a parsing PR kicking off an experimental implementation. The tracking issue for this experimental implementation is here.
Finish the std::offload module (rust-lang/rust-project-goals#109)
Progress
Point of contact

Manuel Drehwald

Champions

compiler (Manuel Drehwald), lang (TC)

Task owners

Manuel Drehwald, LLVM offload/GPU contributors

4 detailed updates available.

Comment by [Manuel Drehwald][] posted on 2026-01-16:

Key developments:

std::autodiff is moving closer to nightly, and std::offload is gaining various performance, feature, and hardware support improvements.

autodiff

Jakub Beránek, @sgasho, and I continued working on enabling autodiff in nightly. We have a PR up that builds autodiff in CI, and verified that the artifacts can be installed and work on Linux. For apple however, we noticed that any autodiff usage hangs. After some investigation, it turns out that we ended up embedding two LLVM copies, one in rustc, and one in Enzyme. It should be comparably easy to get rid of the second one. Once we verified that this fixes the build, we'll merge the PR to enable autodiff on both targets in nightly.

offload

A lot of interesting updates on the performance, feature, and hardware support side.

  1. Marcelo Domínguez, @kevinsala, @jdoerfert, and I started implementing the first benchmarks, since that's generally the best way to find missing features or performance issues. We were positively surprised by how good the out-of-the-box performance was. We will implement a few more benchmarks and post the results once we have verified them. We also implemented multiple PRs which implement bugfixes, cleanups, and needed features like support for scalars. We also started working on LLVM optimizations which make sure that we can achieve even better performance.

  2. I noticed that our offload intrinsic allowed running Rust code on the GPU, but it wasn't of much help when calling gpu vendor libraries like cuBLAS. In https://github.com/rust-lang/rust/pull/150683 I implemented a new helper intrinsic which allows calling those functions conveniently, without having to manually move data to or from the device. It will benefit from the same LLVM optimizations as our full offload intrinsic. It also a bit simpler to set up on the compiler and linker side, so it already works with std and mangled kernel names, something that we still have to improve for our main offload intrinsic.

  3. A lot of work happened on the LLVM offload side for SPIRV and Intel GPU support. At the moment, our Rust frontend is tested on NVIDIA and AMD server and consumer GPUs, as well as AMD HPC and Lapotop APUs. Karol Zwolak reached out since he wants to help with with also running Rust on Intel GPUs. Offload relies on LLVM which started gaining Intel support, so hopefully we won't need much work beyond a new intel-gpu target and a new stdarch module. There is also work on a new spirv target for rustc, which we could also support if it goes through LLVM. Due to some open questions around typed pointers it does not seem clear yet whether it will, so we will have to wait.

  4. Nikita started working on updating our submodule to LLVM 22. This hopefully does not only brings some compile and runtime performance improvements, but also greatly simplifies how we can build and use offload. Once it landed I'll refactor our bootstraping logic, and as part of that start building offload in CI.

Comment by [Manuel Drehwald][] posted on 2025-12-26:

Time for the next round of updates. Again, most of the updates were on the GPU side, but with some notable autodiff improvements too.

autodiff:

  1. @sgasho finished his work on using dlopen to load enzyme and the pr landed. This allowed Jakub Beránek and me to start working on distributing Enzyme via a standalone component.

  2. As a first step, I added a nicer error if we fail to find or dlopen our Enzyme backend. I also removed most of our autodiff fallbacks, we now unconditionally enable our macro frontend on nightly: https://github.com/rust-lang/rust/pull/150133 You may notice that cargo expand now works on autodiff code. This also allowed the first bug reports about ICE (internal compiler error) in our macro parser logic.

  3. Kobzol opened a PR to build Enzyme in CI. In theory, I should have been able to download that artifact, put it into my sysroot, and use the latest nightly to automatically load it. If that had worked, we could have just merged his PR, and everyone could have started using AD on nightly. Of course, things are never that easy. Even though both Enzyme, LLVM, and rustc were built in CI, the LLVM version shipped along with rustc does not seem compatible with the LLVM version Enzyme was built against. We assume some slight cmake mismatch during our CI builds, which we will have to debug.

offload:

  1. On the gpu side, Marcelo Domínguez finished his cleanup PR, and along the way also fixed using multiple kernels within a single codebase. When developing the offload MVP I had taken a lot of inspiration from the LLVM-IR generated by clang - and it looks like I had gotten one of the (way too many) LLVM attributes wrong. That caused some metadata to be fused when multiple kernels are present, confusing our offload backend. We started to find more bugs when working on benchmarks, more about the fixes for those in the next update.

  2. I finished cleaning up my offload build PR, and Oliver Scherer reviewed and approved it. Once the dev-guide gets synced, you should see much simpler usage instructions. Now it's just up to me to automate the last part, then you can compile offload code purely with cargo or rustc. I also improved how we build offload, which allows us to build it both in CI and locally. CI had some very specific requirements to not increase build times, since our x86-64-dist runner is already quite slow.

  3. Our first benchmarks directly linked against NVIDIA and AMD intrinsics on llvm-ir level. However, we already had an nvptx Rust module for a while, and since recently also an amdgpu module which nicely wraps those intrinsics. I just synced the stdarch repository into rustc a few minutes ago, so from now on, we can replace both with the corresponding Rust functions. In the near future we should get a higher level GPU module, which abstracts away naming differences between vendors.

  4. Most of my past rustc contributions were related to LLVM projects or plugins (Offload and Enzyme), and I increasingly encountered myself asking other people for updates or backports of our LLVM submodule, since upstream LLVM has fixes which were not yet merged into our LLVM submodule. Our llvm working group is quite small and I didn't want to burden them too much with my requests, so I recently asked them to join it, which also got approved. In the future I intend to help a little with the maintenance here.

Comment by [Manuel Drehwald][] posted on 2025-12-02:

It's only been two weeks, but we got a good number of updates, so I already wanted to share them.

autodiff

  1. On the autodiff side, we landed the support for rlib and better docs. This means that our autodiff frontend is "almost" complete, since there are almost no cases left where you can't apply autodiff. There are a few features like custom-derivatives or support for dyn arguments that I'd like to add, but they are currently waiting for better docs on the Enzyme side. There is also a long-term goal off replacing the fat-lto requirement with the less invasive embed-bc requirement, but this proved to be tricky in the past and only affects compile times.
  2. @sgasho picked up my old PR to dlopen enzyme, and found the culprit of it failing after my last rebase. A proper fix might take a bit longer, but it might be worth waiting for. As a reminder, using dlopen in the future allows us to ship autodiff on nightly without increasing the size of rustc and therefore without making our infra team sad.

All in all, we have landed most of the hard work here, so that's a very comfortable position to be in before enabling it on nightly.

offload

  1. We have landed the intrinsic implementation of Marcelo Domínguez, so now you can offload functions with almost arbitrary arguments. In my first prototype, I had limited it to pointers to 256 f64 values. The updated usage example continues to live here in our docs. As you can see, we still require #[cfg(target_os=X)] annotations. Under the hood, the LLVM-IR which we generate is also still a bit convoluted. In his next PRs, he'll clean up the generated IR, and introduce an offload macro that users shall call instead of the internal offload intrinsic.
  2. I spend more time on enabling offload in our CI, to enable std::offload in nightly. After multiple iterations and support from LLVM offload devs, we found a cmake config that does not run into bugs, should not increase Rust CI time too much, and works with both in-tree llvm/clang builds, as well as external clang's (the current case in our Rust CI).
  3. I spend more time on simplifying the usage instructions in the dev guide. We started with two cargo calls, one rustc call, two clang calls, and two clang-helper binary calls. I was able to remove the rustc and one of the clang-offload-packager calls, by directly calling the underlying LLVM APIs. I also have an unmerged PR which removes the two clang calls. Once I cleaned it up and landed it, we would be down to only two cargo calls and one binary call to clang-linker-wrapper. Once I automated this last wrapper (and enabled offload in CI), nightly users should be able to experiment with std::offload.
Comment by [Manuel Drehwald][] posted on 2025-11-19:

Automatic Differentiation

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.

  1. As part of my cleanup I went through old issues, and realized we now partly support rlib's! That's a huge improvement, because it means you can use autodiff not only in your 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.
  2. I started documentation improvements in https://github.com/rust-lang/rust/pull/149082 and https://github.com/rust-lang/rust/pull/148201, which should be visible on the website from tomorrow onwards. They are likely still not perfect, so please keep opening issues if you have questions.
  3. We now provide a helpful error message if a user forgets enabling lto=fat: https://github.com/rust-lang/rust/pull/148855
  4. After two months of work, @sgasho managed to add Rust CI to enzyme! Unfortunately, Enzyme devs broke and disabled it directly, so we'll need to talk about maintaining it as part of shipping Enzyme in nightly.

I have the following elements on my TODO list as part shipping AD on nightly

  1. Re-enable macOS build (probably easy)
  2. Talk with Enzyme Devs about maintenance
  3. Merge rlib support (under review)
  4. upstream ADbenchmarks from r-l/enzyme to r-l/r as codegen tests (easy)
  5. Write a block post/article for https://blog.rust-lang.org/inside-rust/

GPU offload

  1. The llvm dev talk about GPU programming went great, I got to talk to a lot of other developers in the area of llvm offload. I hope to use some of the gained knowledge soon. Concrete steps planned are the integration of libc-gpu for IO from kernels, as well as moving over my code from the OpenMP API to the slightly lower level liboffload API.
  2. We confirmed that our gpu offload prototype works on more hardware. By now we have the latest AMD APU generation covered, as well as an MI 250X and an RTX 4050. My own Laptop with a slightly older AMD Ryzen 7 PRO 7840U unfortunately turned out to be not supported by AMD drivers.
  3. The offload intrinsic PR by Marcelo Domínguez is now marked as ready, and I left my second round of review. Hopefully, we can land it soon!
  4. I spend some time trying to build and potentially ship the needed offload changes in nightly, unfortunately I still fail to build it in CI: https://github.com/rust-lang/rust/pull/148671.

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.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

5 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2026-01-19:

Update from the 2026-01-14 meeting.

Deref / Receiver

Ding's arbitrary_self_types: Split the Autoderef chain rust#146095 is waiting on reviews. It updates the method resolution to essentially: deref_chain(T).flat_map(|U| receiver_chain(U)).

The perf run was a wash and a carter has completed yesterday. Analysis pending.

RFC #3851: Supertrait Auto-impl

Ding has submitted a Rust Project goal for Supertrait Auto Impl.

Arbitrary Self Types rust#44874

We've discovered the #[feature(arbitrary_self_types_pointer)] feature gate. As the Lang consensus is to not support the Receiver trait on raw pointer types we're probably going to remove it (but this needs further discussion). This was a remnant from the original proposal, but the Lang has changed direction since.

derive(CoercePointee) rust#123430

Ding is working on a fix to prevent accidental specialization of the trait implementation. rust#149968 is adding an interim fix.

Alice opened a Reference PR for rust#136776. There are questions around the behaviour of the as cast vs. coercions.

Pass pointers to const in assembly rfc#3848

Gary opened implementation for the RFC: rust#138618.

In-place initialization goal#395

Ding is writing a post to describe all the open proposals including Alice's new one that she brouhght up during the LPC 2025. He'll merge it in: https://rust-lang.github.io/beyond-refs.

Field Projections goal#390

Benno updated the Field Representing Types PR to the latest design. This makes the PR much simpler.

Tyler opened a wiki to keep all the proposals, resources in one place: https://rust-lang.github.io/beyond-refs.

Macros, attributes, derives, etc.

Josh brought up his work on adding more capable declarative macros for writing attributes and derives. He's asked the Rust for Linux team for what they need to stop using proc macros.

Miguel noted they've just added dependency on syn, but they would like to remove it some day if their could.

Benno provided a few cases of large macros that he thought were unlikely to be replacable by declarative-style ones. Josh suggested there may be a way and suggested an asynchronous discussion.

Comment by [Tomas Sedovic][] posted on 2025-12-18:

Quick bit of great news: Rust in the Linux kernel is no longer treated as an experiment, it's here to stay 🎉

https://lwn.net/SubscriberLink/1050174/63aa7da43214c3ce/

Comment by [Tomas Sedovic][] posted on 2025-12-05:

Update from the 2025-12-03 meeting.

Deref / Receiver

Ding keeps working on the Reference draft. The idea is still not well-proliferated and people are not convinced this is a good way to go. We hope the method-probing section in Reference PR could clear thins up.

We're keeping the supertrait auto-impl experiment as an alternative.

RFC #3851: Supertrait Auto-impl

Ding addressed Predrag's requests on SemVer compatibility. He's also opened an implementation PR: https://github.com/rust-lang/rust/pull/149335. Here's the tracking issue: https://github.com/rust-lang/rust/issues/149556.

derive(CoercePointee)

Ding opened a PR to require additional checks for DispatchFromDyn: https://github.com/rust-lang/rust/pull/149068

In-place initialization

Ding will prepare material for a discussion at the LPC (Linux Plumbers Conference). We're looking to hear feedback on the end-user syntax for it.

The feature is going quite large, Ding will check with Tyler on the whether this might need a series of RFCs.

The various proposals on the table continue being discussed and there are signs (albeit slow) of convergence. The placing function and guaranteed return ones are superseded by outpointer. The more ergonomic ideas can be built on top. The guaranteed value placement one would be valuable in the compiler regardless and we're waiting for Olivier to refine it.

The feeling is that we've now clarified the constraints that the proposals must operate under.

Field projections

Nadri's Custom places proposal is looking good at least for the user-facing bits, but the whole thing is growing into a large undertaking. Benno's been focused on academic work that's getting wrapped up soon. The two will sync afterwards.

Comment by [Tomas Sedovic][] posted on 2025-11-28:

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#112504

This 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.

Fix for imports_granularity is not respected for #[cfg]'d items / rustfmt#6666

Ding opened a PR to fix this: https://github.com/rust-lang/rustfmt/issues/6666

rustfmt trailing comma hack

Ding and Manish were talking about writing up a proper fix for the vertical layout that's currently being solved by the , //, hack

TypeId layout

This 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 / Receiver

Following TC's recommendation, Ding is drafting the Reference PR.

Arbitrary Self Types and 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

RFC #3848: Pass pointers to const in assembly

Merged!

In-place initialization

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.

Alice has been nominated and accepted as language-advisor. Fantastic news and congratulations!

Comment by [Tomas Sedovic][] posted on 2025-11-19:

Update from the 2025-11-05 meeting.

Deref/Receiver

Ding 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.

Arbitrary Self Types and derive(CoercePointee) / tracking issue #44874

theemathas 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 .

RFC #3851: Supertrait Auto-impl

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

Field projections

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).

Inlining C code into Rust code

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.

In-place initialization (rust-lang/rust-project-goals#395)
Progress
Point of contact

Alice Ryhl

Champions

lang (Taylor Cramer)

Task owners

Benno Lossin, Alice Ryhl, Michael Goulet, Taylor Cramer, Josh Triplett, Gary Guo, Yoshua Wuyts

1 detailed update available.

Comment by [Alice Ryhl][] posted on 2026-01-31:

A proposal to continue this goal in the next goal period was merged: https://github.com/rust-lang/rust-project-goals/pull/477

MIR move elimination (rust-lang/rust-project-goals#396)
Progress
Point of contact

Amanieu d'Antras

Champions

lang (Amanieu d'Antras)

Task owners

Amanieu d'Antras

1 detailed update available.

Comment by [Amanieu d'Antras][] posted on 2025-12-17:

The RFC draft was reviewed in detail and Ralf Jung pointed out that the proposed semantics introduce issues because they rely on "no-behavior" (NB) with regards to choosing an address for a local. This can lead to surprising "time-traveling" behavior where the set of possible addresses that a local may have (and whether 2 locals can have the same address) depends on information from the future. For example:

#![allow(unused)]
fn main() {
// This program has DB
let x = String::new();
let xaddr = &raw const x;
let y = x; // Move out of x and de-initialize it.
let yaddr = &raw const y;
x = String::new(); // assuming this does not change the address of x
// x and y are both live here. Therefore, they can't have the same address.
assume(xaddr != yaddr);
drop(x);
drop(y);
}
#![allow(unused)]
fn main() {
// This program has UB
let x = String::new();
let xaddr = &raw const x;
let y = x; // Move out of x and de-initialize it.
let yaddr = &raw const y;
// So far, there has been no constraint that would force the addresses to be different.
// Therefore we can demonically choose them to be the same. Therefore, this is UB.
assume(xaddr != yaddr);
// If the addresses are the same, this next line triggers NB. But actually this next
// line is unreachable in that case because we already got UB above...
x = String::new();
// x and y are both live here.
drop(x);
drop(y);
}

With that said, there is still a possibility of achieving the optimization, but the scope will need to be scaled down a bit. Specifically, we would need to:

  • no longer perform a "partial free"/"partial allocation" when initializing or moving out of a single field of a struct. The lifetime of a local starts when any part of it is initialized and ends when it is fully moved out.
  • allow a local's address to change when it is re-initialized after having been fully moved out, which eliminates the need for NB.

This reduces the optimization opportunities since we can't merge arbitrary sub-field moves, but it still allows for eliminating moves when constructing a struct from multiple values.

The next step is for me to rework the RFC draft to reflect this.

Progress
Point of contact

Aapo Alasuutari

Champions

compiler (Oliver Scherer), lang (Tyler Mandry)

Task owners

Aapo Alasuutari

1 detailed update available.

Comment by [Aapo Alasuutari][] posted on 2025-12-17:

Purpose

A refresher on what we want to achieve here: the most basic form of reborrowing we want to enable is this:

#![allow(unused)]
fn main() {
// Note: not Clone or Copy
#[derive(Reborrow)]
struct MyMutMarker<'a>(...);

// ...

let marker: MyMarkerMut = MyMutMarker::new();
some_call(marker);
some_call(marker);
}

ie. make it possible for an owned value to be passed into a call twice and have Rust inject a reborrow at each call site to produce a new bitwise copy of the original value for the passing purposes, and mark the original value as disabled for reads and writes for the duration of the borrow.

A notable complication appears with implementing such reborrowing in userland using explicit cals when dealing with returned values:

#![allow(unused)]
fn main() {
return some_call(marker.reborrow());
}

If the borrowed lifetime escapes through the return value, then this will not compile as the borrowed lifetime is based on a value local to this function. Alongside convenience, this is the major reason for the Reborrow traits work.

CoerceShared is a secondary trait that enables equivalent reborrowing that only disables the original value for writes, ie. matching the &mut T to &T coercion.

Update

We have the Reborrow trait working, albeit currently with a bug in which the marker must be bound as let mut. We are working towards a working CoerceShared trait in the following form:

#![allow(unused)]
fn main() {
trait CoerceShared<Target: Copy> {}
}

Originally the trait had a type Target ADT but this turned out to be unnecessary, as there is no reason to particularly disallow multiple coercion targets. The original reason for using an ADT to disallow multiple coercion targets was based on the trait also having an unsafe method, at which point unscrupulous users could use the trait as a generic coercion trait. Because the trait method was found to be unnecessary, the fear is also unnecessary.

This means that the trait has better chances of working with multiple coercing lifetimes (think a collection of &muts all coercing to &s, or only some of them). However, we are currently avoiding any support of multiple lifetimes as we want to avoid dealing with rmeta before we have the basic functionality working.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

3 detailed updates available.

Comment by [Oliver Scherer][] posted on 2026-02-09:
  • @BD103 added slices, arrays and raw pointer support
    • https://github.com/rust-lang/rust/pull/151019
    • https://github.com/rust-lang/rust/pull/151031
    • https://github.com/rust-lang/rust/pull/151118
    • https://github.com/rust-lang/rust/pull/151119
  • Asuna added all of our primitives
    • https://github.com/rust-lang/rust/pull/151123
  • Jamie Hill-Daniel gave us references
    • https://github.com/rust-lang/rust/pull/151222
  • @izagawd made it possible to extract some info from dyn Trait
    • https://github.com/rust-lang/rust/pull/151239

There is ongoing work for Adts and function pointers, both of which will land as MVPs and will need some work to make them respect semver or generally become useful in practice

Removing the 'static bound from try_as_dyn turned out to have many warts, so I'm limiting it to a much smaller subset and will have borrowck emit the 'static requirement if the other rules do not apply (instead of having an unconditional 'static requirement)

Comment by [Oliver Scherer][] posted on 2026-01-14:
  • https://github.com/rust-lang/rust/pull/146923 has landed, and we even got the first contribs adding array support to reflection.
    • there are lots more types and type information that we could support, and it's rather easy to add more. Happy to review any work here.
  • https://github.com/rust-lang/rust/pull/150033 has landed, and I'm working on removing the 'static requirement in https://github.com/rust-lang/rust/pull/150161
Comment by [Oliver Scherer][] posted on 2025-12-15:

Updates

  • https://github.com/rust-lang/rust/pull/148820 adds a way to mark functions and intrinsics as only callable during CTFE
  • https://github.com/rust-lang/rust/pull/144363 has been unblocked and just needs some minor cosmetic work

Blockers

  • https://github.com/rust-lang/rust/pull/146923 (reflection MVP) has not been reviewed yet
Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

4 detailed updates available.

Comment by [Ed Page][] posted on 2026-02-13:

Key developments

  • FCP has ended on frontmatter support, just awaiting merge (https://github.com/rust-lang/rust/pull/148051)
  • Cargo script has entered FCP (https://github.com/rust-lang/cargo/pull/16569)

Blockers

  • Potential issues around edition, see https://github.com/rust-lang/rust/issues/152254
Comment by [Ed Page][] posted on 2026-01-14:

Key developments

  • #146377 has been decided and merged

Blockers

  • T-lang discussing CR / text direction feedback: https://github.com/rust-lang/rust/pull/148051#issuecomment-3638326490
  • T-rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-12-15:

Key developments

  • A fence length limit was added in response to T-lang feedback (https://github.com/rust-lang/rust/pull/149358)
  • Whether to disallow or lint for CR inside of a frontmatter is under discussion (https://github.com/rust-lang/rust/pull/149823)

Blockers

  • https://github.com/rust-lang/rust/pull/146377
  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-11-21:

Key developments

  • rust-lang/rust#148051

Blockers:

  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

5 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rust#143924 has been merged, enabling scalable vector types to be defined on nightly, and I'm working on a patch to introduce unstable intrinsics/scalable vector types to std::arch

Comment by [Niko Matsakis][] posted on 2025-12-19:

Update to the previous post.

Tyler Mandry pointed me at this thread, where lcnr posted this nice blog post that he wrote detailing more about (C).

Key insights:

  • Because the use of size_of_val would still cause post-mono errors when invoked on types that are not SizeOfVal, you know that adding SizeOfVal into the function's where-clause bounds is not a breaking change, even though adding a where clause is a breaking change more generally.
  • But, to David Wood's point, it does mean that there is a change to Rust's semver rules: adding size_of_val would become a breaking change, where it is not today.

This may well be the best option though, particularly as it allows us to make changes to the defaults across-the-board. A change to Rust's semver rules is not a breaking change in the usual sense. It is a notable shift.

Comment by [Niko Matsakis][] posted on 2025-12-18:

Update: David and I chatted on Zulip. Key points:

David has made "progress on the non-Sized Hierarchy part of the goal, the infrastructure for defining scalable vector types has been merged (with them being Sized in the interim) and that'll make it easier to iterate on those and find issues that need solving".

On the Sized hierarchy part of the goal, no progress. We discussed options for migrating. There seem to be three big options:

(A) The conservative-but-obvious route where the T: Derefin the old edition is expanded to T: Deref<Target: SizeOfVal> (but in the new edition it means T: Deref<Target: Pointee>, i.e., no additional bounds). The main downside is that new Edition code using T: Deref can't call old Edition code using T: Deref as the old edition code has stronger bounds. Therefore new edition code must either use stronger bounds than it needs or wait until that old edition code has been updated.

(B) You do something smart with Edition.Old code where you figure out if the bound can be loose or strict by bottom-up computation. So T: Deref in the old could mean either T: Deref<Target: Pointee> or T: Deref<Target: SizeOfVal>, depending on what the function actually does.

(C) You make Edition.Old code always mean T: Deref<Target: Pointee> and you still allow calls to size_of_val but have them cause post-monomorphization errors if used inappropriately. In Edition.New you use stricter checking.

Options (B) and (C) have the downside that changes to the function body (adding a call to size_of_val, specifically) in the old edition can stop callers from compiling. In the case of Option (B), that breakage is at type-check time, because it can change the where-clauses. In Option (C), the breakage is post-monomorphization.

Option (A) has the disadvantage that it takes longer for the new bounds to roll out.

Given this, (A) seems the preferred path. We discussed options for how to encourage that roll-out. We discussed the idea of a lint that would warn Edition.Old code that its bounds are stronger than needed and suggest rewriting to T: Deref<Target: Pointee> to explicitly disable the stronger Edition.Old default. This lint could be implemented in one of two ways

  • at type-check time, by tracking what parts of the environment are used by the trait solver. This may be feasible in the new trait solver, someone from @rust-lang/types would have to say.
  • at post-mono time, by tracking which functions actually call size_of_val and propagating that information back to callers. You could then compare against the generic bounds declared on the caller.

The former is more useful (knowing what parts of the environment are necessary could be useful for more things, e.g., better caching); the latter may be easier or more precise.

Comment by [David Wood][] posted on 2025-12-15:

I haven't made any progress on Deref::Target yet, but I have been focusing on landing rust-lang/rust#143924 which has went through two rounds of review and will hopefully be approved soon.

Comment by [David Wood][] posted on 2025-11-22:

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

Jack Wrenn

Champions

compiler (Jack Wrenn), lang (Scott McMurray)

Task owners

Jacob Pratt, Jack Wrenn, Luca Versari

No detailed updates available.

lang-docs Team Champion Reports

This section contains champion reports for the lang-docs team.

Recent updates

The Rust project is currently working towards a slate of 3 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

1 detailed update available.

Comment by [Josh Triplett][] posted on 2025-12-17:

In addition to further ongoing work on reference material (some of which is on track to be merged), we've had some extensive discussions about reference processes, maintenance, and stability markers. Niko Matsakis is putting together a summary and proposal for next steps.

Getting Rust for Linux into stable Rust: language features (rust-lang/rust-project-goals#116)
Progress
Point of contact

Tomas Sedovic

Champions

lang (Josh Triplett), lang-docs (TC)

Task owners

Ding Xiang Fei

5 detailed updates available.

Comment by [Tomas Sedovic][] posted on 2026-01-19:

Update from the 2026-01-14 meeting.

Deref / Receiver

Ding's arbitrary_self_types: Split the Autoderef chain rust#146095 is waiting on reviews. It updates the method resolution to essentially: deref_chain(T).flat_map(|U| receiver_chain(U)).

The perf run was a wash and a carter has completed yesterday. Analysis pending.

RFC #3851: Supertrait Auto-impl

Ding has submitted a Rust Project goal for Supertrait Auto Impl.

Arbitrary Self Types rust#44874

We've discovered the #[feature(arbitrary_self_types_pointer)] feature gate. As the Lang consensus is to not support the Receiver trait on raw pointer types we're probably going to remove it (but this needs further discussion). This was a remnant from the original proposal, but the Lang has changed direction since.

derive(CoercePointee) rust#123430

Ding is working on a fix to prevent accidental specialization of the trait implementation. rust#149968 is adding an interim fix.

Alice opened a Reference PR for rust#136776. There are questions around the behaviour of the as cast vs. coercions.

Pass pointers to const in assembly rfc#3848

Gary opened implementation for the RFC: rust#138618.

In-place initialization goal#395

Ding is writing a post to describe all the open proposals including Alice's new one that she brouhght up during the LPC 2025. He'll merge it in: https://rust-lang.github.io/beyond-refs.

Field Projections goal#390

Benno updated the Field Representing Types PR to the latest design. This makes the PR much simpler.

Tyler opened a wiki to keep all the proposals, resources in one place: https://rust-lang.github.io/beyond-refs.

Macros, attributes, derives, etc.

Josh brought up his work on adding more capable declarative macros for writing attributes and derives. He's asked the Rust for Linux team for what they need to stop using proc macros.

Miguel noted they've just added dependency on syn, but they would like to remove it some day if their could.

Benno provided a few cases of large macros that he thought were unlikely to be replacable by declarative-style ones. Josh suggested there may be a way and suggested an asynchronous discussion.

Comment by [Tomas Sedovic][] posted on 2025-12-18:

Quick bit of great news: Rust in the Linux kernel is no longer treated as an experiment, it's here to stay 🎉

https://lwn.net/SubscriberLink/1050174/63aa7da43214c3ce/

Comment by [Tomas Sedovic][] posted on 2025-12-05:

Update from the 2025-12-03 meeting.

Deref / Receiver

Ding keeps working on the Reference draft. The idea is still not well-proliferated and people are not convinced this is a good way to go. We hope the method-probing section in Reference PR could clear thins up.

We're keeping the supertrait auto-impl experiment as an alternative.

RFC #3851: Supertrait Auto-impl

Ding addressed Predrag's requests on SemVer compatibility. He's also opened an implementation PR: https://github.com/rust-lang/rust/pull/149335. Here's the tracking issue: https://github.com/rust-lang/rust/issues/149556.

derive(CoercePointee)

Ding opened a PR to require additional checks for DispatchFromDyn: https://github.com/rust-lang/rust/pull/149068

In-place initialization

Ding will prepare material for a discussion at the LPC (Linux Plumbers Conference). We're looking to hear feedback on the end-user syntax for it.

The feature is going quite large, Ding will check with Tyler on the whether this might need a series of RFCs.

The various proposals on the table continue being discussed and there are signs (albeit slow) of convergence. The placing function and guaranteed return ones are superseded by outpointer. The more ergonomic ideas can be built on top. The guaranteed value placement one would be valuable in the compiler regardless and we're waiting for Olivier to refine it.

The feeling is that we've now clarified the constraints that the proposals must operate under.

Field projections

Nadri's Custom places proposal is looking good at least for the user-facing bits, but the whole thing is growing into a large undertaking. Benno's been focused on academic work that's getting wrapped up soon. The two will sync afterwards.

Comment by [Tomas Sedovic][] posted on 2025-11-28:

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#112504

This 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.

Fix for imports_granularity is not respected for #[cfg]'d items / rustfmt#6666

Ding opened a PR to fix this: https://github.com/rust-lang/rustfmt/issues/6666

rustfmt trailing comma hack

Ding and Manish were talking about writing up a proper fix for the vertical layout that's currently being solved by the , //, hack

TypeId layout

This 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 / Receiver

Following TC's recommendation, Ding is drafting the Reference PR.

Arbitrary Self Types and 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

RFC #3848: Pass pointers to const in assembly

Merged!

In-place initialization

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.

Alice has been nominated and accepted as language-advisor. Fantastic news and congratulations!

Comment by [Tomas Sedovic][] posted on 2025-11-19:

Update from the 2025-11-05 meeting.

Deref/Receiver

Ding 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.

Arbitrary Self Types and derive(CoercePointee) / tracking issue #44874

theemathas 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 .

RFC #3851: Supertrait Auto-impl

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

Field projections

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).

Inlining C code into Rust code

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.

Stabilize cargo-script (rust-lang/rust-project-goals#119)
Progress
Point of contact

Ed Page

Champions

cargo (Ed Page), lang (Josh Triplett), lang-docs (Josh Triplett)

Task owners

Ed Page

4 detailed updates available.

Comment by [Ed Page][] posted on 2026-02-13:

Key developments

  • FCP has ended on frontmatter support, just awaiting merge (https://github.com/rust-lang/rust/pull/148051)
  • Cargo script has entered FCP (https://github.com/rust-lang/cargo/pull/16569)

Blockers

  • Potential issues around edition, see https://github.com/rust-lang/rust/issues/152254
Comment by [Ed Page][] posted on 2026-01-14:

Key developments

  • #146377 has been decided and merged

Blockers

  • T-lang discussing CR / text direction feedback: https://github.com/rust-lang/rust/pull/148051#issuecomment-3638326490
  • T-rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-12-15:

Key developments

  • A fence length limit was added in response to T-lang feedback (https://github.com/rust-lang/rust/pull/149358)
  • Whether to disallow or lint for CR inside of a frontmatter is under discussion (https://github.com/rust-lang/rust/pull/149823)

Blockers

  • https://github.com/rust-lang/rust/pull/146377
  • rustdoc deciding on and implementing how they want frontmatter handled in doctests
Comment by [Ed Page][] posted on 2025-11-21:

Key developments

  • rust-lang/rust#148051

Blockers:

  • rustdoc deciding on and implementing how they want frontmatter handled in doctests

libs Team Champion Reports

This section contains champion reports for the libs team.

Recent updates

The Rust project is currently working towards a slate of 4 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Progress
Point of contact

David Wood

Champions

cargo (Eric Huss), compiler (David Wood), libs (Amanieu d'Antras)

Task owners

Adam Gemmell, David Wood

3 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rfcs#3873 has been merged and an FCP has been started on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 - those both have some feedback for me to respond to that I'll get to as soon as I can

Comment by [David Wood][] posted on 2025-12-15:

rust-lang/rfcs#3873 is waiting on one checkbox before entering the final comment period. We had our sync meeting on the 11th and decided that we would enter FCP on rust-lang/rfcs#3874 and rust-lang/rfcs#3875 after rust-lang/rfcs#3873 is accepted. We've responded to almost all of the feedback on the next two RFCs and expect the FCP to act as a forcing-function so that the relevant teams take a look, they can always register concerns if there are things we need to address, and if we need to make any major changes then we'll restart the FCP.

Comment by [David Wood][] posted on 2025-11-22:

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.

C++/Rust Interop Problem Space Mapping (rust-lang/rust-project-goals#388)
Progress
Point of contact

Joel Marcey

Champions

compiler (Oliver Scherer), lang (Tyler Mandry), libs (David Tolnay)

Task owners

Joel Marcey

3 detailed updates available.

Comment by [Joel Marcey][] posted on 2026-01-31:

The effort to fill the contracting role to support this project goal is in the process winding down. The interview and discussion process is nearly complete. We expect to make a final decision for the role in early February.

Comment by [Joel Marcey][] posted on 2026-01-20:

The Rust Foundation is opening up a short-term, approximately 3-month, contracting role to assist in our Rust/C++ Interop initiative. The primary work and deliverables for the role will be to make substantial progress on the Problem Space Mapping Rust Project Goal by collecting discrete problem statements and offering up recommendations on the work that should follow based upon the problems that you found.



If you are interested in how programming languages interoperate, are curious in understanding the problems therein, and are have a passion to think about how those problems may be resolved for the betterment of interop, then this work may be for you.

An ideal candidate will have experience with Rust programming. Having experience in C++ is strongly preferred as well. If you have direct experience with actual engineering that required interoperating between Rust and C++ codebases, that's even better.



If you are interested, please email me (email address found in my GitHub profile) or contact me directly on Zulip by Tuesday, January 27 and we can take it from there to see if there may be a potential fit for further discussion.

Thank you.

Comment by [Jon Bauman][] posted on 2025-11-26:

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.

reflection and comptime (rust-lang/rust-project-goals#406)
Progress
Point of contact

Oliver Scherer

Champions

compiler (Oliver Scherer), lang (Scott McMurray), libs (Josh Triplett)

Task owners

oli-obk

3 detailed updates available.

Comment by [Oliver Scherer][] posted on 2026-02-09:
  • @BD103 added slices, arrays and raw pointer support
    • https://github.com/rust-lang/rust/pull/151019
    • https://github.com/rust-lang/rust/pull/151031
    • https://github.com/rust-lang/rust/pull/151118
    • https://github.com/rust-lang/rust/pull/151119
  • Asuna added all of our primitives
    • https://github.com/rust-lang/rust/pull/151123
  • Jamie Hill-Daniel gave us references
    • https://github.com/rust-lang/rust/pull/151222
  • @izagawd made it possible to extract some info from dyn Trait
    • https://github.com/rust-lang/rust/pull/151239

There is ongoing work for Adts and function pointers, both of which will land as MVPs and will need some work to make them respect semver or generally become useful in practice

Removing the 'static bound from try_as_dyn turned out to have many warts, so I'm limiting it to a much smaller subset and will have borrowck emit the 'static requirement if the other rules do not apply (instead of having an unconditional 'static requirement)

Comment by [Oliver Scherer][] posted on 2026-01-14:
  • https://github.com/rust-lang/rust/pull/146923 has landed, and we even got the first contribs adding array support to reflection.
    • there are lots more types and type information that we could support, and it's rather easy to add more. Happy to review any work here.
  • https://github.com/rust-lang/rust/pull/150033 has landed, and I'm working on removing the 'static requirement in https://github.com/rust-lang/rust/pull/150161
Comment by [Oliver Scherer][] posted on 2025-12-15:

Updates

  • https://github.com/rust-lang/rust/pull/148820 adds a way to mark functions and intrinsics as only callable during CTFE
  • https://github.com/rust-lang/rust/pull/144363 has been unblocked and just needs some minor cosmetic work

Blockers

  • https://github.com/rust-lang/rust/pull/146923 (reflection MVP) has not been reviewed yet
SVE and SME on AArch64 (rust-lang/rust-project-goals#270)
Progress
Point of contact

David Wood

Champions

compiler (David Wood), lang (Niko Matsakis), libs (Amanieu d'Antras)

Task owners

David Wood

5 detailed updates available.

Comment by [David Wood][] posted on 2026-01-15:

rust-lang/rust#143924 has been merged, enabling scalable vector types to be defined on nightly, and I'm working on a patch to introduce unstable intrinsics/scalable vector types to std::arch

Comment by [Niko Matsakis][] posted on 2025-12-19:

Update to the previous post.

Tyler Mandry pointed me at this thread, where lcnr posted this nice blog post that he wrote detailing more about (C).

Key insights:

  • Because the use of size_of_val would still cause post-mono errors when invoked on types that are not SizeOfVal, you know that adding SizeOfVal into the function's where-clause bounds is not a breaking change, even though adding a where clause is a breaking change more generally.
  • But, to David Wood's point, it does mean that there is a change to Rust's semver rules: adding size_of_val would become a breaking change, where it is not today.

This may well be the best option though, particularly as it allows us to make changes to the defaults across-the-board. A change to Rust's semver rules is not a breaking change in the usual sense. It is a notable shift.

Comment by [Niko Matsakis][] posted on 2025-12-18:

Update: David and I chatted on Zulip. Key points:

David has made "progress on the non-Sized Hierarchy part of the goal, the infrastructure for defining scalable vector types has been merged (with them being Sized in the interim) and that'll make it easier to iterate on those and find issues that need solving".

On the Sized hierarchy part of the goal, no progress. We discussed options for migrating. There seem to be three big options:

(A) The conservative-but-obvious route where the T: Derefin the old edition is expanded to T: Deref<Target: SizeOfVal> (but in the new edition it means T: Deref<Target: Pointee>, i.e., no additional bounds). The main downside is that new Edition code using T: Deref can't call old Edition code using T: Deref as the old edition code has stronger bounds. Therefore new edition code must either use stronger bounds than it needs or wait until that old edition code has been updated.

(B) You do something smart with Edition.Old code where you figure out if the bound can be loose or strict by bottom-up computation. So T: Deref in the old could mean either T: Deref<Target: Pointee> or T: Deref<Target: SizeOfVal>, depending on what the function actually does.

(C) You make Edition.Old code always mean T: Deref<Target: Pointee> and you still allow calls to size_of_val but have them cause post-monomorphization errors if used inappropriately. In Edition.New you use stricter checking.

Options (B) and (C) have the downside that changes to the function body (adding a call to size_of_val, specifically) in the old edition can stop callers from compiling. In the case of Option (B), that breakage is at type-check time, because it can change the where-clauses. In Option (C), the breakage is post-monomorphization.

Option (A) has the disadvantage that it takes longer for the new bounds to roll out.

Given this, (A) seems the preferred path. We discussed options for how to encourage that roll-out. We discussed the idea of a lint that would warn Edition.Old code that its bounds are stronger than needed and suggest rewriting to T: Deref<Target: Pointee> to explicitly disable the stronger Edition.Old default. This lint could be implemented in one of two ways

  • at type-check time, by tracking what parts of the environment are used by the trait solver. This may be feasible in the new trait solver, someone from @rust-lang/types would have to say.
  • at post-mono time, by tracking which functions actually call size_of_val and propagating that information back to callers. You could then compare against the generic bounds declared on the caller.

The former is more useful (knowing what parts of the environment are necessary could be useful for more things, e.g., better caching); the latter may be easier or more precise.

Comment by [David Wood][] posted on 2025-12-15:

I haven't made any progress on Deref::Target yet, but I have been focusing on landing rust-lang/rust#143924 which has went through two rounds of review and will hopefully be approved soon.

Comment by [David Wood][] posted on 2025-11-22:

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.

opsem Team Champion Reports

This section contains champion reports for the opsem team.

Recent updates

The Rust project is currently working towards a slate of 2 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Comprehensive niche checks for Rust (rust-lang/rust-project-goals#262)
Progress
Point of contact

Bastian Kersting

Champions

compiler (Ben Kimock), opsem (Ben Kimock)

Task owners

Bastian Kersting], Jakob Koschel

No detailed updates available.
Emit Retags in Codegen (rust-lang/rust-project-goals#392)
Progress
Point of contact

Ian McCormack

Champions

compiler (Ralf Jung), opsem (Ralf Jung)

Task owners

Ian McCormack

2 detailed updates available.

Comment by [Ian McCormack][] posted on 2026-01-09:

Here's our January status update!

  • Yesterday, we posted an MCP for our retag intrinsics. While that's in progress, we'll start adapting our current prototype to remove our dependence on MIR-level retags. Once that's finished, we'll be ready to submit a PR.

  • We published our first monthly blog post about BorrowSanitizer.

  • Our overall goal for 2026 is to transition from a research prototype to a functional tool. Three key features have yet to be implemented: garbage collection, error reporting, and support for atomic memory accesses. Once these are complete, we'll be able to start testing real-world libraries and auditing our results against Miri.

Comment by [Ian McCormack][] posted on 2025-12-16:

Here's our December status update!

  • We have revised our prototype of the pre-RFC based on Ralf Jung's feedback. Now, instead of having two different retag functions for operands and places, we emit a single __rust_retag intrinsic in every situation. We also track interior mutability precisely. At this point, the implementation is mostly stable and seems to be ready for an MCP.

  • There's been some discussion here and in the pre-RFC about whether or not Rust will still have explicit MIR retag statements. We plan on revising our implementation so that we no longer rely on MIR retags to determine where to insert our lower-level retag calls. This should be a relatively straightforward change to the current prototype. If anything, it should make these changes easier to merge upstream, since they will no longer affect Miri.

  • BorrowSanitizer continues to gain new features, and we've started testing it on our first real crate (lru) (which has uncovered a few new bugs in our implementation). The two core Tree Borrows features that we have left to support are error reporting and garbage collection. Once these are finished, we will be able to expand our testing to more real-world libraries and confirm that we are passing each of Miri's test cases (and likely find more bugs lurking in our implementation). Our instrumentation pass ignores global and thread-local state for now, and it does not support atomic memory accesses outside of atomic load and store instructions. These operations should be relatively straightforward to add once we've finished higher-priority items.

  • Performance is slow. We do not know exactly how slow yet, since we've been focusing on feature support over benchmarking and optimization. This is at least partially due to the lack of garbage collection, based on what we're seeing from profiling. We will have a better sense of what our performance is like once we can compare against Miri on more real-world test cases.

As for what's next, we plan on posting an MCP soon, now that it's clear that we will be able to do without MIR retags. You can expect a more detailed status update on BorrowSanitizer by the end of January. This will discuss our implementation and plans for 2026. We will post that here and on our project website.

rustdoc Team Champion Reports

This section contains champion reports for the rustdoc team.

Recent updates

The Rust project is currently working towards a slate of 3 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Add a team charter for rustdoc team (rust-lang/rust-project-goals#387)
Progress Completed
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-11-21:

Done in https://github.com/rust-lang/rust-forge/pull/852.

Continue resolving `cargo-semver-checks` blockers for merging into cargo (rust-lang/rust-project-goals#104)
Progress
Point of contact

Predrag Gruevski

Champions

cargo (Ed Page), rustdoc (Alona Enraght-Moony)

Task owners

Predrag Gruevski

2 detailed updates available.

Comment by [Predrag Gruevski][] posted on 2026-01-17:

I posted a "year in review" for cargo-semver-checks here: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/

It has a section on how I think we should move forward in 2026 and beyond: https://predr.ag/blog/cargo-semver-checks-2025-year-in-review/#the-path-forward-for-2026-and-beyond

Comment by [Predrag Gruevski][] posted on 2025-11-23:

Google Summer of Code 2025 is complete + finally some movement on cross-crate linting! 🚀

Key developments

  • Two students had a successful conclusion of Google Summer of Code working on cargo-semver-checksfind more details here!
  • rustdoc JSON now includes rlib information, following the design for cross-crate rustdoc JSON info created at RustWeek 2025: https://github.com/rust-lang/rust/pull/149043
  • A cargo issue was discovered that prevents this rlib info from being used; it's currently being triaged: https://github.com/rust-lang/cargo/issues/16291
  • Once that's resolved, we'll have enough here for a basic prototype. Getting features right in dependencies will likely require more work due to having many more cargo-related edge cases.
Stabilize rustdoc `doc_cfg` feature (rust-lang/rust-project-goals#404)
Progress
Point of contact

Guillaume Gomez

Champions

rustdoc (Guillaume Gomez)

Task owners

Guillaume Gomez

1 detailed update available.

Comment by [Guillaume Gomez][] posted on 2025-12-17:

Opened stabilization PR but we have blockers I didn't hear of, so stabilization will be postponed until then.

spec Team Champion Reports

This section contains champion reports for the spec team.

Recent updates

The Rust project is currently working towards a slate of 2 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Develop the capabilities to keep the FLS up to date (rust-lang/rust-project-goals#391)
Progress
Point of contact

Pete LeVasseur

Champions

bootstrap (Jakub Beránek), lang (Niko Matsakis), spec (Pete LeVasseur)

Task owners

Pete LeVasseur, Contributors from Ferrous Systems and others TBD, t-spec and contributors from Ferrous Systems

2 detailed updates available.

Comment by [Pete LeVasseur][] posted on 2025-12-16:

Meeting notes here: FLS team meeting 2025-12-12

Key developments: We're close to completing the FLS release for 1.91.0, 1.91.1. We've started to operate as a team, merging a PR with the changelog entries, then opening up issues for each change required: ✅ #624(https://github.com/rust-lang/fls/issues/624), ✅ #625(https://github.com/rust-lang/fls/issues/625), ✅ #626(https://github.com/rust-lang/fls/issues/626), ⚠️ #623(https://github.com/rust-lang/fls/issues/623). #623(https://github.com/rust-lang/fls/issues/623) is still pending, as it requires a bit of alignment with the Reference on definitions and creation of a new example. Blockers: None currently Help wanted: We'd love more folks from the safety-critical community to contribute to picking up issues or opening an issue if you notice something is missing.

Comment by [Pete LeVasseur][] posted on 2025-11-21:

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.

Expand the Rust Reference to specify more aspects of the Rust language (rust-lang/rust-project-goals#394)
Progress
Point of contact

Josh Triplett

Champions

lang-docs (Josh Triplett), spec (Josh Triplett)

Task owners

Amanieu d'Antras, Guillaume Gomez, Jack Huey, Josh Triplett, lcnr, Mara Bos, Vadim Petrochenkov, Jane Lusby

1 detailed update available.

Comment by [Josh Triplett][] posted on 2025-12-17:

In addition to further ongoing work on reference material (some of which is on track to be merged), we've had some extensive discussions about reference processes, maintenance, and stability markers. Niko Matsakis is putting together a summary and proposal for next steps.

types Team Champion Reports

This section contains champion reports for the types team.

Recent updates

The Rust project is currently working towards a slate of 5 project goals, with 0 of them designated as Roadmap 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.

Roadmap goals

Goals looking for help


Other goal updates

Borrow checking in a-mir-formality (rust-lang/rust-project-goals#122)
Progress
Point of contact

Niko Matsakis

Champions

types (Niko Matsakis)

Task owners

Niko Matsakis, tiif

5 detailed updates available.

Comment by [Niko Matsakis][] posted on 2025-12-17:

Update: opened https://github.com/rust-lang/a-mir-formality/pull/210 with today's work. We are discussing how to move the checker to support polonius-alpha. To that end, we introduced feature gates (so that a-mir-formality can model nightly features) and did some refactoring of the type checker aiming at allowing outlives to become flow-sensitive.

Comment by [Niko Matsakis][] posted on 2025-12-10:

Update: opened https://github.com/rust-lang/a-mir-formality/pull/207 which contains support for &mut, wrote some new tests (including one FIXME), and added a test for NLL Problem Case #3 (which behaved as expected).

One interesting thing (cc Ralf Jung) is that we have diverged from MiniRust in a few minor ways:

  • We do not support embedding value expressions in place expressions.
  • Where MiniRust has a AddrOf operator that uses the PtrType to decide what kind of operation it is, we have added a Ref MIR operation. This is in part because we need information that is not present in MiniRust, specifically a lifetime.
  • We have also opted to extend goto with the ability to take multiple successors, so that goto b1, b2 can be seen as "goto either b1 or b2 non-deterministically" (the actual opsem would probably be to always go to b1, making this a way to add "fake edges", but the analysis should not assume that).
Comment by [Niko Matsakis][] posted on 2025-12-03:

The PR also includes two big improvements to the a-mir-formality framework:

  • support for (for_all) rules that can handle "iteration"
  • tracking proof trees, making it much easier to tell why something is accepted that should not be
Comment by [Niko Matsakis][] posted on 2025-12-03:

PR https://github.com/rust-lang/a-mir-formality/pull/206 contains a "first draft" for the NLL rules. It checks for loan violations (e.g., mutating borrowed data) as well as some notion of outlives requirements. It does not check for move errors and there aren't a lot of tests yet.

Comment by [Niko Matsakis][] posted on 2025-11-19:

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.

Evolving trait hierarchies (rust-lang/rust-project-goals#393)
Progress
Point of contact

Taylor Cramer

Champions

lang (Taylor Cramer), types (Oliver Scherer)

Task owners

Taylor Cramer, Taylor Cramer & others

1 detailed update available.

Comment by [Taylor Cramer][] posted on 2025-12-17:

Current status:

  • The RFC for auto impl supertraits has been updated to address SemVer compatibility issues.
  • There is a parsing PR kicking off an experimental implementation. The tracking issue for this experimental implementation is here.
Next-generation trait solver (rust-lang/rust-project-goals#113)
Progress
Point of contact

lcnr

Champions

types (lcnr)

Task owners

Boxy, Michael Goulet, lcnr

2 detailed updates available.

Comment by [lcnr][] posted on 2026-01-19:

There hasn't been too much progress over the last few weeks and I've been mostly taking a Christmas break. Nicholas Nethercote has been looking into the performance of the new trait solver, cleaning up canonicalization and slightly improving its performance: https://github.com/rust-lang/rust/pull/150748 https://github.com/rust-lang/rust/pull/150859.

Shoyu Vanilla looked into https://github.com/rust-lang/trait-system-refactor-initiative/issues/251 and uncovered the underlying bug there. While this issue also affects the old solver and the proper fix for it requires where-bounds on binders, we can work around this bug in the trait solver for now and intend to do so.

We've started another crater run with all our recent changes and adwin has started to triage it, uncovering one new issue up until now. Intend to continue going through that over the next few weeks.

There's also a lot in-progress work going on. I am collaborating with Niko Matsakis to specify and later RFC the cycle semantics of Rust. León Orell Valerian Liehr is working on a replacement for the rustdoc's auto trait impl synthesis: https://github.com/rust-lang/rust/pull/149019. @tiff is working on a fix a MIR borrowck unsoundness: https://github.com/rust-lang/trait-system-refactor-initiative/issues/159. Shoyu Vanilla and I are improving the way we propagate inference constraints from the expected return type to function arguments, fixing https://github.com/rust-lang/trait-system-refactor-initiative/issues/259.

Comment by [lcnr][] posted on 2025-12-15:

We've continued to fix a bunch of smaller issues over the last month. Tim (Theemathas Chirananthavat) helped uncover a new potential issue due to non-fatal overflow which we'll have to consider before stabilizing the new solver: https://github.com/rust-lang/trait-system-refactor-initiative/issues/258.

I fixed two issues myself in https://github.com/rust-lang/rust/pull/148823 and https://github.com/rust-lang/rust/pull/148865.

tiif with help by Boxy fixed query cycles when evaluating constants in where-clauses: https://github.com/rust-lang/rust/pull/148698.

adwin fixed a subtle issues involving coroutine witnesses in https://github.com/rust-lang/rust/pull/149167 after having diagnosed the underlying issue there last month. They've also fixed a smaller diagnostics issue in https://github.com/rust-lang/rust/pull/149299. Finally, they've also fixed an edge case of impl well-formedness checking in https://github.com/rust-lang/rust/pull/149345.

Shoyu Vanilla fixed a broken interaction of aliases and fudging in https://github.com/rust-lang/rust/pull/149320. Looking into fudging and HIR typeck Expectation handling also uncovered a bunch of broken edge-cases and I've openedhttps://github.com/rust-lang/rust/issues/149379 to track these separately.

I have recently spent some time thinking about the remaining necessary work and posted a write-up on my personal blog: https://lcnr.de/blog/2025/12/01/next-solver-update.html. I am currently trying to get a clearer perspective on our cycle handling while slowly working towards an RFC for the changes there. This is challenging as we don't have a good theoretical foundation here yet.

Stabilizable Polonius support on nightly (rust-lang/rust-project-goals#118)
Progress
Point of contact

Rémy Rakic

Champions

types (Jack Huey)

Task owners

Amanda Stjerna, Rémy Rakic, Niko Matsakis

4 detailed updates available.

Comment by [Rémy Rakic][] posted on 2026-01-30:

This month's update:

  • tiif is making progress on https://github.com/rust-lang/trait-system-refactor-initiative/issues/159
  • 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.
  • https://github.com/rust-lang/rust/pull/149639 has now landed, and https://github.com/rust-lang/rust/pull/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 🤞
Comment by [Rémy Rakic][] posted on 2025-12-31:
  • I should be able to open a PR in the next couple days

done in https://github.com/rust-lang/rust/pull/150551

Comment by [Rémy Rakic][] posted on 2025-12-30:

This month's key developments were:

  • borrowck support in a-mir-formality has been progressing steadily — it has its own dedicated updates in https://github.com/rust-lang/rust-project-goals/issues/122 for more details
  • we were also able to find a suitable project for the master's student project on a-mir-formality (and they accepted and should start around February) and which will help expand our testing coverage for the polonius alpha as well.
  • tiif has kept making progress on fixing opaque type soundness issue https://github.com/rust-lang/trait-system-refactor-initiative/issues/159. It is the one remaining blocker for passing all tests. By itself it will not immediately fix the two remaining (soundness) issues with opaque type region liveness, but we'll able to use the same supporting code to ensure the regions are indeed live where they need to be.
  • I quickly cleaned up some inefficiencies in constraint conversion, it hasn't landed yet but it maybe won't need to because of the next item
  • but most of the time this month was spent on this final item: we have the first interesting results from the rewriting effort. After a handful of wrong starts, I have a branch almost ready to switch the constraint graph to be lazy and computed during traversal. It removes the need to index the numerous list of constraints, or to convert liveness data to a different shape. It thus greatly reduces the current alpha overhead (some rare cases look faster than NLLs but I don't yet know why, maybe due to being able to better use the sparseness, low connectivity of the constraint graph, and a small number of loans). The overhead wasn't entirely removed of course: the worst offending benchmark has a +5% wall-time regression, but icounts are worse looking (+13%). This was also only benchmarking the algorithm itself, without the improvements to the rest of borrowck mentioned in previous updates. I should be able to open a PR in the next couple days, once I figure out how to best convert the polonius mermaid graph dump to the new lazy localized constraint generation.
  • and finally, happy holidays everyone!
Comment by [Rémy Rakic][] posted on 2025-11-25:

Key developments:

  • I prototyped building blocks to fix the liveness soundness issue, but this was deemed too brittle.
  • so we prepared a meeting for the types team to discuss the problem, and possible solutions.
  • it turns out the issue is related to another soundness issue for opaque types in the new trait solver, https://github.com/rust-lang/trait-system-refactor-initiative/issues/159, and that tiif is already working on. The same solution is needed for both issues: with the full implied bounds available for opaque types in liveness, we'll able to require all the regions outliving the opaque lower bound to be live, while ignoring the unrelated regions (that the hidden type cannot use anyway). There will be no relevant dead region through which loans flow, and code relying on unused lifetimes being dead (like a lot of ed2024 code with the default capture changes) will still compile
  • we prepared another types-team meeting to discuss polonius in general, and the alpha algorithm in particular, to share knowledge among the team. This will also be helpful to then on apply member constraints in a location-sensitive manner, since right now they're applied at the SCC level and we need to make sure these constraints with the choice regions are present in the localized subset graph.
  • niko and tiif have made a lot of progress on adding support for borrow checking in a-mir-formality, so I've also joined these meetings, since we'll also want to model the alpha.
  • I've looked into Prusti's Place Capability Graphs, and plan to see how to integrate the alpha there, and if possible with the fuzzing capabilities mentioned in the paper, with the usual goal to expand testing as we've mentioned many times
  • we also had some discussion for a possible masters' student project, and thought about different practical and theoretical topics
Type System Documentation (rust-lang/rust-project-goals#405)
Progress
Point of contact

Boxy

Champions

types (Boxy)

Task owners

Boxy, lcnr

3 detailed updates available.

Comment by [Boxy][] posted on 2026-01-30:

Nothing this month, been busy with other stuff :)

Comment by [Boxy][] posted on 2025-12-30:

This month I've written some documentation for how Const Generics is implemented in the compiler. This mostly covers the implementation of the stable functionality as the unstable features are quite in flux right now. These docs can be found here: https://rustc-dev-guide.rust-lang.org/const-generics.html

Comment by [Boxy][] posted on 2025-11-29:

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.

Goal motivations

The motivation section for a goal should sell the reader on why this is an important problem to address.

The first paragraph should begin with a concise summary of the high-level goal and why it’s important. This is a kind of summary that helps the reader to get oriented.

The status quo section then goes into deeper detail on the problem and how things work today. It should answer the following questions

  • Who is the target audience? Is it a particular group of Rust users, such as those working in a specific domain? Contributors?
  • What do these users do now when they have this problem, and what are the shortcomings of that?

The next few steps can explain how you plan to change that and why these are the right next steps to take.

Finally, the shiny future section can put the goal into a longer term context. It’s ok if the goal doesn’t have a shiny future beyond the next few steps.

Roadmaps

Each time period, the goal program owner selects a small set of the proposed goals (typically 2-3) as roadmap goals. These goals are highlighted specially.

The criteria for a goal to be considered as a roadmap goal:

  • Tell a story: Roadmap goals further some aspect of Rust’s story that we want to be better understood.
  • Broad impact and interest: Roadmap goals should be impactful and/or interesting to a broad swath of Rust’s user base.
  • Take time: While not required, it is common that roadmap goals take multiple goal sessions to complete. Therefore, the roadmap goals often continue from goal period to goal period.

Invited goals

Invited goals are goals accepted whose main implementation tasks have no assigned owner. Teams accept invited goals to represent work that they feel is important but where nobody is available to do the work. These goals are a great place to get started in contributing to Rust. If you see an invited goal you think you could help with, reach out to the point of contact listed on the goal: they are volunteering to mentor.

Goal point of contacts

Every goal has a single point of contact. This is the person responsible for authoring updates and generally tracking the status of the goal. They will get regular pings to provide updates.

We require a single point of contact to avoid confusion. But of course it is possible for that person to delegate the actual authoring of updates to others.

For simple goals, the point of contact is usually the person who owns the implementation.

Team asks

A team ask is the thing that you need from a Rust team to make progress. The precise asks can vary from “Discussion and moral support” (basically, regular vibe checks) up until specific RFC or stabilization decisions. Asks cannot require a specific outcome (e.g., the ask cannot be “guarantee me that you will accept the RFC), as project goals are not meant to substitute for a real decision process.

The list of recognized asks is shown below:

  • The Ask column indicates the text that should appear in your project goal table.
  • The aka column is a shorter name for the ask used in the condensed RFC tables.
  • The description column describes what you are asking for.
AskakaDescription
“Allocate funds”Alloc fundsallocate funding
“Discussion and moral support”Good vibesapprove of this direction and be prepared for light discussion on Zulip or elsewhere
“Deploy to production”Deploydeploy code to production (e.g., on crates.io
“Standard reviews”r?review PRs (PRs are not expected to be unduly large or complicated)
“Dedicated reviewer”Ded. r?assign a specific person (or people) to review a series of PRs, appropriate for large or complex asks
“Lang-team experiment”Experimentbegin a lang-team experiment authorizing experimental impl of lang changes before an RFC is written; limited to trusted contributors
“Design meeting”Design mtg.hold a synchronous meeting to review a proposal and provide feedback (no decision expected)
“RFC decision”RFCreview an RFC and deciding whether to accept
“RFC secondary review”RFC rev.briefly review an RFC without need of a formal decision
“Org decision”Orgreach a decision on an organizational or policy matter
“MCP decision”MCPaccept a Major Change Proposal
“ACP decision”ACPaccept an API Change Proposal
“Review/revise Reference PR”Reference textassign a lang-docs team liaison to finalize edits to Rust Reference
“Stabilization decision”Stabilize.reach a decision on a stabilization proposal
“Policy decision”Policymake a decision related to team policy
“FCP decision(s)”FCPmake formal decision(s) that require ‘checkboxes’ and a FCP (Final Comment Period)
“Blog post approval”Blogapprove of posting about this on the main Rust blog
“Miscellaneous”Miscdo some one-off action as described in the notes

Owners

To be fully accepted, each goal needs a set of owners, usually a single person or a small group, who are responsible for completing the work. Each goal also includes a list of tasks to be completed over the six months following its start, and most tasks should have designated owners.

Goals without owners can only be accepted in provisional form.

Owners keep things moving

Owners are the ones ultimately responsible for the goal being completed. They stay on top of the current status and make sure that things keep moving. When there is disagreement about the best path forward, owners are expected to make sure they understand the tradeoffs involved and then to use their good judgment to resolve it in the best way.

When concerns are raised with their design, owners are expected to embody not only the letter but also the spirit of the Rust Code of Conduct. They treasure dissent as an opportunity to improve their design. But they also know that every good design requires compromises and tradeoffs and likely cannot meet every need.

Owners own the proposal, teams own the decision

Even though owners are the ones who author the proposal, Rust teams are the ones to make the final decision. Teams can ultimately overrule an owner: they can ask the owner to come back with a modified proposal that weighs the tradeoffs differently. This is right and appropriate, because teams are the ones we recognize as having the best broad understanding of the domain they maintain. But teams should use their power judiciously, because the owner is typically the one who understands the tradeoffs for this particular goal most deeply.

Owners report regularly on progress

One of the key responsibilities of the owner is regular status reporting. Each active project goal is given a tracking issue. Owners are expected to post updates on that tracking issue when they are pinged by the bot. The project will be posting regular blog posts that are generated in a semi-automated fashion from these updates: if the post doesn’t have new information, then we will simply report that the owner has not provided an update. We will also reach out to owners who are not providing updates to see whether the goal is in fact stalled and should be removed from the active list.

Ownership is a position of trust

Giving someone ownership of a goal is an act of faith — it means that we consider them to be an individual of high judgment who understands Rust and its values and will act accordingly. This implies to me that we are unlikely to take a goal if the owner is not known to the project. They don’t necessarily have to have worked on Rust, but they have to have enough of a reputation that we can evaluate whether they’re going to do a good job.’

The project goal template includes a number of elements designed to increase trust:

  • The “shiny future” and design axioms give a “preview” of how owner is thinking about the problem and the way that tradeoffs will be resolved.
  • The milestones section indicates the rough order in which they will approach the problem.

Design axioms

Each project goal includes a design axioms section. Design axioms capture the guidelines you will use to drive your design. Since goals generally come early in the process, the final design is not known – axioms are a way to clarify the constraints you will be keeping in mind as you work on your design. Axioms will also help you operate more efficiently, since you can refer back to them to help resolve tradeoffs more quickly.

Examples

Axioms about axioms

  • Axioms capture constraints. Axioms capture the things you are trying to achieve. The goal ultimately is that your design satisfies all of them as much as possible.
  • Axioms express tradeoffs. Axioms are ordered, and – in case of conflict – the axioms that come earlier in the list take precedence. Since axioms capture constraints, this doesn’t mean you just ignore the axioms that take lower precedence, but it usually means you meet them in a “less good” way. For example, maybe consider a lint instead of a hard error?
  • Axioms should be specific to your goal. Rust has general design axioms that
  • Axioms are short and memorable. The structure of an axiom should begin with a short, memorable bolded phrase – something you can recite in meetings. Then a few sentences that explain in more detail or elaborate.

Axioms about the project goal program

  • Goals are a contract. Goals are meant to be a contract between the owner and project teams. The owner commits to doing the work. The project commits to supporting that work.
  • Goals aren’t everything, but they are our priorities. Goals are not meant to cover all the work the project will do. But goals do get prioritized over other work to ensure the project meets its commitments.
  • Goals cover a problem, not a solution. As much as possible, the goal should describe the problem to be solved, not the precise solution. This also implies that accepting a goal means the project is committing that the problem is a priority: we are not committing to accept any particular solution.
  • Owners are first-among-equals. Rust endeavors to run an open, participatory process, but ultimately achieving any concrete goal requires someone (or a small set of people) to take ownership of that goal. Owners are entrusted to listen, take broad input, and steer a well-reasoned course in the tradeoffs they make towards implementing the goal. But this power is not unlimited: owners make proposals, but teams are ultimately the ones that decide whether to accept them.
  • To everything, there is a season. While there will be room for accepting new goals that come up during the year, we primarily want to pick goals during a fixed time period and use the rest of the year to execute.

Axioms about Rust itself

Still a work in progress! See the Rust design axioms repository.

Frequently asked questions

Where can I read more about axioms?

Axioms are very similar to approaches used in a number of places…

RFC

The RFC proposing the goal program has been opened. See RFC #3614.

2025H1

Status: Accepted RFC #3764 has been accepted, establishing 40 total Rust project goals for 2025H1.

Summary

Propose a slate of 40 project goals for 2025H1, including 3 flagship goals:

Motivation

The 2025H1 goal slate consists of 40 project goals, of which we have selected 3 as flagship goals. Flagship goals represent the goals expected to have the broadest overall impact.

How the goal process works

Project goals are proposed bottom-up by a point of contact, somebody who is willing to commit resources (time, money, leadership) to seeing the work get done. The point of contact identifies the problem they want to address and sketches the solution of how they want to do so. They also identify the support they will need from the Rust teams (typically things like review bandwidth or feedback on RFCs). Teams then read the goals and provide feedback. If the goal is approved, teams are committing to support the point of contact in their work.

Project goals can vary in scope from an internal refactoring that affects only one team to a larger cross-cutting initiative. No matter its scope, accepting a goal should never be interpreted as a promise that the team will make any future decision (e.g., accepting an RFC that has yet to be written). Rather, it is a promise that the team are aligned on the contents of the goal thus far (including the design axioms and other notes) and will prioritize giving feedback and support as needed.

Of the proposed goals, a small subset are selected by the roadmap owner as flagship goals. Flagship goals are chosen for their high impact (many Rust users will be impacted) and their shovel-ready nature (the org is well-aligned around a concrete plan). Flagship goals are the ones that will feature most prominently in our public messaging and which should be prioritized by Rust teams where needed.

Rust’s mission

Our goals are selected to further Rust’s mission of empowering everyone to build reliable and efficient software. Rust targets programs that prioritize

  • reliability and robustness;
  • performance, memory usage, and resource consumption; and
  • long-term maintenance and extensibility.

We consider “any two out of the three” as the right heuristic for projects where Rust is a strong contender or possibly the best option.

Axioms for selecting goals

We believe that…

  • Rust must deliver on its promise of peak performance and high reliability. Rust’s maximum advantage is in applications that require peak performance or low-level systems capabilities. We must continue to innovate and support those areas above all.
  • Rust’s goals require high productivity and ergonomics. Being attentive to ergonomics broadens Rust impact by making it more appealing for projects that value reliability and maintenance but which don’t have strict performance requirements.
  • Slow and steady wins the race. We don’t want to create stress via unrealistic, ambitious goals. We want to make steady progress each goal period on important problems.

Guide-level explanation

Flagship goals

The flagship goals proposed for this roadmap are as follows:

Why these particular flagship goals?

Async. This work continues our drive to improve support for async programming in Rust. In 2024H2 we stabilized async closures; explored the generator design space; and began work on the dynosaur crate, an experimental proc-macro to provide dynamic dispatch for async functions in traits. In 2025H1 our plan is to deliver (1) improved support for async-fn-in-traits, completely subsuming the functionality of the async-trait crate; (2) progress towards sync and async generators, simplifying the creation of iterators and async data streams; (3) and improve the ergonomics of Pin, making lower-level async coding more approachable. These items together start to unblock the creation of the next generation of async libraries in the wider ecosystem, as progress there has been blocked on a stable solution for async traits and streams.

Rust for Linux. This goal continues our work from 2024H2 in supporting the experimental support for Rust development in the Linux kernel. Whereas in 2024H2 we were focused on stabilizing required language features, our focus in 2025H1 is stabilizing compiler flags and tooling options. We will (1) implement RFC #3716 which lays out a design for ABI-modifying flags; (2) take the first step towards stabilizing build-std by creating a stable way to rebuild core with specific compiler options; (3) extend rustdoc, clippy, and the compiler with features that extract metadata for integration into other build systems (in this case, the kernel’s build system).

Rust All Hands 2025. May 15, 2025 marks the 10-year anniversary of Rust’s 1.0 release; it also marks 10 years since the creation of the Rust subteams. At the time there were 6 Rust teams with 24 people in total. There are now 57 teams with 166 people. In-person All Hands meetings are an effective way to help these maintainers get to know one another with high-bandwidth discussions. This year, the Rust project will be coming together for RustWeek 2025, a joint event organized with RustNL. Participating project teams will use the time to share knowledge, make plans, or just get to know one another better. One particular goal for the All Hands is reviewing a draft of the Rust Vision Doc, a document that aims to take stock of where Rust is and lay out high-level goals for the next few years.

Project goals

The full slate of project goals are as follows. These goals all have identified owners who will drive the work forward as well as a viable work plan. The goals include asks from the listed Rust teams, which are cataloged in the reference-level explanation section below.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as an owner. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactProgress
Expose experimental LLVM features for GPU offloadingManuel Drehwald⚠️
Scalable Polonius support on nightlyRémy Rakic⚠️
Organize Rust All-Hands 2025Mara Bos⚠️
Use annotate-snippets for rustc diagnostic outputScott Schafer⚠️
SVE and SME on AArch64David Wood⚠️
Bring the Async Rust experience closer to parity with sync RustTyler Mandry⚠️
build-stdDavid Wood⚠️
Prototype a new set of Cargo “plumbing” commandsHelp Wanted⚠️
Stabilize cargo-scriptEd Page⚠️
Continue resolving cargo-semver-checks blockers for merging into cargoPredrag Gruevski⚠️
Making compiletest more maintainable: reworking directive handlingJieyou Xu⚠️
Prepare const traits for stabilizationOliver Scherer⚠️
Externally Implementable ItemsMara Bos⚠️
Experiment with ergonomic ref-countingSantiago Pastorino⚠️
Model coherence in a-mir-formalityNiko Matsakis⚠️
Improve state machine codegenFolkert de Vries⚠️
Finish the libtest json output experimentEd Page⚠️
Declarative (macro_rules!) macro improvementsJosh Triplett⚠️
Metrics InitiativeJane Lusby⚠️
“Stabilizable” prototype for expanded const genericsBoxy⚠️
Next-generation trait solverlcnr⚠️
Null and enum-discriminant runtime checks in debug buildsBastian Kersting⚠️
Implement Open API Namespace SupportHelp Wanted⚠️
Optimizing Clippy & lintingAlejandra González⚠️
Promoting Parallel Front EndSparrow Li⚠️
rustc-perf improvementsDavid Wood⚠️
Stabilize public/private dependenciesHelp Wanted⚠️
Extend pubgrub to match cargo’s dependency resolutionJacob Finkelman⚠️
Implement restrictions, prepare for stabilizationJacob Pratt⚠️
Stabilize tooling needed by Rust for LinuxNiko Matsakis⚠️
Rust Vision DocumentNiko Matsakis⚠️
Research: How to achieve safety when linking separately compiled codeMara Bos⚠️
Evaluate approaches for seamless interop between C++ and RustTyler Mandry⚠️
Nightly support for ergonomic SIMD multiversioningLuca Versari⚠️
Publish first rust-lang-owned release of “FLS”Joel Marcey⚠️
Run the 2025H1 project goal programNiko Matsakis⚠️
Publish first version of StableMIR on crates.ioCelina G. Val⚠️
Instrument the Rust standard library with safety contractsCelina G. Val⚠️
Unsafe FieldsJack Wrenn⚠️
Secure quorum-based cryptographic verification and mirroring for crates.iowalterhpearce⚠️

Reference-level explanation

The following table highlights the asks from each affected team. The rows are goals and columns are asks being made of the team. The contents of each cell may contain extra notes (or sometimes footnotes) with more details. Teams often use these notes to indicate the person on the team signed up to do the work, for example.

bootstrap team

cargo team

*1: 1 hour Overall Design and threat model (from here)

*2: 1 hour General design/implementation for index verification (from here)

*3: 1 hour Design for novel incremental download mechanism for bandwidth conservation (from here)

clippy team

GoalStabilize.
Optimizing Clippy & linting
Rust-for-Linux
↳ Clippy configuration

compiler team

*1: 2-3 meetings expected; all involve lang (from here)

*2: RFC #3716, currently in PFCP (from here)

*3: For each of the relevant compiler flags (from here)

*4: Esteban Kuber will be the reviewer (from here)

*5: Update performance regression policy (from here)

crates-io team

*1: 1 hour Overall Design, threat model, and discussion of key management and quorums (from here)

*2: 1 hour General design/implementation for automated index signing (from here)

infra team

*1: rustc-perf improvements, testing infrastructure (from here)

*2: 3 hours of design and threat model discussion. Specific production infrastructure setup will come at a later time after the initial proof of concept. (from here)

lang team

GoalExperimentDesign mtg.RFCStabilize.Policy
“Stabilizable” prototype for expanded const generics
Async
↳ Implementable trait aliases
↳ Pin ergonomicsComplete
↳ Return type notationComplete
↳ Trait for generators (sync)2 meetings expected
↳ Unsafe bindersStretch goal
Declarative (macro_rules!) macro improvements*3
↳ Design and iteration for macro fragment fields
↳ Design for macro metavariable constructs
macro_rules! attributes
macro_rules! derives
Evaluate approaches for seamless interop between C++ and Rust*1
Experiment with ergonomic ref-counting
Expose experimental LLVM features for GPU offloadingComplete
Externally Implementable ItemsComplete
Implement restrictions, prepare for stabilization
Improve state machine codegen
Nightly support for ergonomic SIMD multiversioning
Null and enum-discriminant runtime checks in debug builds
Prepare const traits for stabilizationComplete*2(stretch goal)
Research: How to achieve safety when linking separately compiled codeNiko Matsakis
SVE and SME on AArch64
↳ Extending type system to support scalable vectors
↳ Investigate SME support
Stabilize cargo-script
↳ Stabilize language feature frontmatter
Unsafe Fields

*1: 2-3 meetings expected; all involve lang (from here)

*2: first meeting scheduled for Jan; second meeting may be required (from here)

*3: Discussed with Eric Holk and Vincenzo Palazzo; lang would decide whether to delegate specific matters to wg-macros (from here)

lang-docs team

leadership-council team

*1: Create supporting subteam + Zulip stream (from here)

*2: approve creation of new team (from here)

*3: Complete for event (from here)

*4: Prepare one or two plenary sessions (from here)

*5: Decide on team swag; suggestions very welcome! (from here)

*6: 1 hour synchronously discussing the threat models, policy, and quorum mechanism. Note: The ask from the Leadership Council is not a detailed exploration of how we address these threat models; rather, this will be a presentation of the threat models and a policy decision that the project cares about those threat models, along with the specific explanation of why a quorum is desirable to address those threat models. (from here)

libs team

libs-api team

*1: 2-3 meetings expected; all involve lang (from here)

opsem team

project-stable-mir team

release team

rustdoc team

spec team

testing-devex team

types team

GoalRFCRFC rev.Stabilize.FCP
“Stabilizable” prototype for expanded const generics
Async
↳ Implementable trait aliases
↳ Return type notation
↳ Unsafe bindersStretch goal
Model coherence in a-mir-formality
Next-generation trait solver*1
Prepare const traits for stabilization*2
↳ Formalize const-traits in a-mir-formality
SVE and SME on AArch64
↳ Extending type system to support scalable vectors
↳ Investigate SME support
↳ Land nightly experiment for SVE types
Scalable Polonius support on nightly

*1: for necessary refactorings (from here)

*2: Types team needs to validate the approach (from here)

wg-macros team

GoalPolicy
Declarative (macro_rules!) macro improvements*1
↳ Design for macro metavariable constructs

*1: Discussed with Eric Holk and Vincenzo Palazzo; lang would decide whether to delegate specific matters to wg-macros (from here)

Definitions

Definitions for terms used above:

  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What goals were not accepted?

The following goals were proposed but ultimately not accepted, either for want of resources or consensus. In some cases narrower versions of these goals were prepared.

GoalPoint of contactTask Owners and Champions
Field Projections@y86-devHelp wanted
Rust Specification TestingConnor Horman

What do the column names like “Ded. r?” mean?

Those column names refer to specific things that can be asked of teams:

AskakaDescription
“Allocate funds”Alloc fundsallocate funding
“Discussion and moral support”Good vibesapprove of this direction and be prepared for light discussion on Zulip or elsewhere
“Deploy to production”Deploydeploy code to production (e.g., on crates.io
“Standard reviews”r?review PRs (PRs are not expected to be unduly large or complicated)
“Dedicated reviewer”Ded. r?assign a specific person (or people) to review a series of PRs, appropriate for large or complex asks
“Lang-team experiment”Experimentbegin a lang-team experiment authorizing experimental impl of lang changes before an RFC is written; limited to trusted contributors
“Design meeting”Design mtg.hold a synchronous meeting to review a proposal and provide feedback (no decision expected)
“RFC decision”RFCreview an RFC and deciding whether to accept
“RFC secondary review”RFC rev.briefly review an RFC without need of a formal decision
“Org decision”Orgreach a decision on an organizational or policy matter
“MCP decision”MCPaccept a Major Change Proposal
“ACP decision”ACPaccept an API Change Proposal
“Review/revise Reference PR”Reference textassign a lang-docs team liaison to finalize edits to Rust Reference
“Stabilization decision”Stabilize.reach a decision on a stabilization proposal
“Policy decision”Policymake a decision related to team policy
“FCP decision(s)”FCPmake formal decision(s) that require ‘checkboxes’ and a FCP (Final Comment Period)
“Blog post approval”Blogapprove of posting about this on the main Rust blog
“Miscellaneous”Miscdo some one-off action as described in the notes

Goals

This page lists the 40 project goals proposed for 2025h1.

Just because a goal is listed on this list does not mean the goal has been accepted. The owner of the goal process makes the final decisions on which goals to include and prepares an RFC to ask approval from the teams.

Flagship goals

Flagship goals represent the goals expected to have the broadest overall impact. Learn about flagship goals.

Other goals

These are the other proposed goals.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as an owner. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactProgress
Expose experimental LLVM features for GPU offloadingManuel Drehwald⚠️
Scalable Polonius support on nightlyRémy Rakic⚠️
Use annotate-snippets for rustc diagnostic outputScott Schafer⚠️
build-stdDavid Wood⚠️
Prototype a new set of Cargo “plumbing” commandsHelp Wanted⚠️
Stabilize cargo-scriptEd Page⚠️
Continue resolving cargo-semver-checks blockers for merging into cargoPredrag Gruevski⚠️
Making compiletest more maintainable: reworking directive handlingJieyou Xu⚠️
Prepare const traits for stabilizationOliver Scherer⚠️
Externally Implementable ItemsMara Bos⚠️
Experiment with ergonomic ref-countingSantiago Pastorino⚠️
Model coherence in a-mir-formalityNiko Matsakis⚠️
Improve state machine codegenFolkert de Vries⚠️
Finish the libtest json output experimentEd Page⚠️
Declarative (macro_rules!) macro improvementsJosh Triplett⚠️
Metrics InitiativeJane Lusby⚠️
“Stabilizable” prototype for expanded const genericsBoxy⚠️
Next-generation trait solverlcnr⚠️
Null and enum-discriminant runtime checks in debug buildsBastian Kersting⚠️
Implement Open API Namespace SupportHelp Wanted⚠️
Optimizing Clippy & lintingAlejandra González⚠️
Promoting Parallel Front EndSparrow Li⚠️
rustc-perf improvementsDavid Wood⚠️
Stabilize public/private dependenciesHelp Wanted⚠️
Extend pubgrub to match cargo’s dependency resolutionJacob Finkelman⚠️
Implement restrictions, prepare for stabilizationJacob Pratt⚠️
Rust Vision DocumentNiko Matsakis⚠️
Research: How to achieve safety when linking separately compiled codeMara Bos⚠️
Evaluate approaches for seamless interop between C++ and RustTyler Mandry⚠️
Nightly support for ergonomic SIMD multiversioningLuca Versari⚠️
Publish first rust-lang-owned release of “FLS”Joel Marcey⚠️
Run the 2025H1 project goal programNiko Matsakis⚠️
Publish first version of StableMIR on crates.ioCelina G. Val⚠️
Instrument the Rust standard library with safety contractsCelina G. Val⚠️
Unsafe FieldsJack Wrenn⚠️
Secure quorum-based cryptographic verification and mirroring for crates.iowalterhpearce⚠️

Expose experimental LLVM features for GPU offloading

Metadata
Point of contactManuel Drehwald
StatusAccepted
Tracking issuerust-lang/rust-project-goals#109
Other tracking issuesrust-lang/rust#124509, rust-lang/rust#124509
Zulip channel[#wg-autodiff][channel]
Teamscompiler, lang
Task ownersManuel Drehwald
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/390790-wg-autodiff

Summary

Expose experimental LLVM features for GPU offloading and allow combining it with the std::autodiff feature.

Motivation

Scientific computing, high performance computing (HPC), and machine learning (ML) all share the interesting challenge in that they each, to different degrees, care about highly efficient library and algorithm implementations, but that these libraries and algorithms are not always used by people with deep experience in computer science. Rust is in a unique position because ownership, lifetimes, and the strong type system can prevent many bugs. At the same time strong alias information allows compelling performance optimizations in these fields, with performance gains well beyond that otherwise seen when comparing C++ with Rust. This is due to how automatic differentiation and GPU offloading strongly benefit from aliasing information.

The status quo

Thanks to PyO3, Rust has excellent interoperability with Python. Conversely, C++ has a relatively weak interop story. This can lead Python libraries to using slowed C libraries as a backend instead, just to ease bundling and integration. Fortran is mostly used in legacy places and hardly used for new projects.

As a solution, many researchers try to limit themself to features which are offered by compilers and libraries built on top of Python, like JAX, PyTorch, or, more recently, Mojo. Rust has a lot of features which make it more suitable to develop a fast and reliable backend for performance critical software than those languages. However, it lacks GPU support which developers now expect.

Almost every language has some way of calling hand-written CUDA/ROCm/Sycl kernels, but the interesting feature of languages like Julia, or of libraries like JAX, is that they offer users the ability to write kernels in the language the users already know, or a subset of it, without having to learn anything new. Minor performance penalties are not that critical in such cases, if the alternative are a CPU-only solution. Otherwise worthwhile projects such as Rust-CUDA end up going unmaintained due to being too much effort to maintain outside of LLVM or the Rust project.

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

The next six months

We are requesting support from the Rust project for continued experimentation:

  1. Merge an MVP #[offloading] fork which is able to run simple functions using rayon parallelism on a GPU, showing a speed-up.
  2. Show an example of how to combine #[offloading] with #[autodiff] to run a differentiated function on a GPU.

The “shiny future” we are working towards

The purpose of this goal is to enable continued experimentation with the underlying LLVM functionality. The eventual goal of this experimentation is that three important LLVM features (batching, autodiff, offloading) can be combined and work nicely together. The hope is that we will have state-of-the-art libraries like faer to cover linear algebra, and that we will start to see more and more libraries in other languages using Rust with these features as their backend. Cases which don’t require interactive exploration will also become more popular in pure Rust.

Caveats to this future

There is not yet consensus amongst the relevant Rust teams as to how and/or whether this functionality should be exposed on stable. Some concerns that continued experimentation will hopefully help to resolve:

  • How effective and general purpose is this functionality?
  • How complex is this functionality to support, and how does that trade off with the value it provides? What is the right point on the spectrum of tradeoffs?
  • Can code using these Rust features still compile and run on backends other than LLVM, and on all supported targets? If not, how should we manage the backend-specific nature of it?
  • Can we avoid tying Rust features too closely to the specific properties of any backend or target, such that we’re confident these features can remain stable over decades of future landscape changes?
  • Can we fully implement every feature of the provided functionality (as more than a no-op) on fully open systems, despite the heavily proprietary nature of parts of the GPU and accelerator landscape?

Design axioms

Offloading

  • We try to provide a safe, simple and opaque offloading interface.
  • The “unit” of offloading is a function.
  • We try to not expose explicit data movement if Rust’s ownership model gives us enough information.
  • Users can offload functions which contains parallel CPU code, but do not have final control over how the parallelism will be translated to co-processors.
  • We accept that hand-written CUDA/ROCm/etc. kernels might be faster, but actively try to reduce differences.
  • We accept that we might need to provide additional control to the user to guide parallelism, if performance differences remain unacceptably large.
  • Offloaded code might not return the exact same values as code executed on the CPU. We will work with t-opsem to develop clear rules.

Autodiff

  • std::autodiff has been upstreamed as part of the last Project Goal. There are till open PRs under review, but I expect them to be merged still in 2024.
  • Currently we work on adding custom-derivatives and will upstream support for batching/vectorization next, but both will be small PRs once the basic infrastructure is in place.
  • Some features like safety checks or “TypeTrees” which will improve performance and catch usage mistakes were removed from the previous upstreaming PRs to make reviewing easier. We will upstream them at the side, but those are only 100-300 loc each, and thus should be easy to review.

Add your design axioms here. Design axioms clarify the constraints and tradeoffs you will use as you do your design work. These are most important for project goals where the route to the solution has significant ambiguity (e.g., designing a language feature or an API), as they communicate to your reader how you plan to approach the problem. If this goal is more aimed at implementation, then design axioms are less important. Read more about design axioms.

Ownership and team asks

Owner: Manuel Drehwald

Manuel S. Drehwald is working 5 days per week on this, sponsored by LLNL and the University of Toronto (UofT). He has a background in HPC and worked on a Rust compiler fork, as well as an LLVM-based autodiff tool for the last 3 years during his undergrad. He is now in a research-based master’s degree program. Supervision and discussion on the LLVM side will happen with Johannes Doerfert and Tom Scogland.

Minimal “smoke test” reviews will be needed from the compiler-team. The Rust language changes at this stage are expected to be a minimal wrapper around the underlying LLVM functionality and the compiler team need only vet that the feature will not hinder usability for ordinary Rust users or cause undue burden on the compiler architecture itself. There is no requirement to vet the quality or usability of the design.

TaskOwner(s) or team(s)Notes
DevelopmentManuel Drehwald
Lang-team experimentTeam langComplete
Standard reviewsTeam compiler

Outputs and milestones

Outputs

  • An #[offload] rustc-builtin-macro which makes a function definition known to the LLVM offloading backend.

    • Made a PR to enable LLVM’s offloading runtime backend.
    • Merge the offload macro frontend
    • Merge the offload Middle-end
  • An offload!([GPU1, GPU2, TPU1], foo(x, y,z)); macro (placeholder name) which will execute function foo on the specified devices.

  • An #[autodiff] rustc-builtin-macro which differentiates a given function.

    • Merge the Autodiff macro frontend
    • Merge the Autodiff Enzyme backend
    • Merge the Autodiff Middle-end
  • A #[batching] rustc-builtin-macro which fuses N function calls into one call, enabling better vectorization.

Milestones

  • The first offloading step is the automatic copying of a slice or vector of floats to a device and back.

  • The second offloading step is the automatic translation of a (default) Clone implementation to create a host-to-device and device-to-host copy implementation for user types.

  • The third offloading step is to run some embarrassingly parallel Rust code (e.g. scalar times Vector) on the GPU.

  • Fourth we have examples of how rayon code runs faster on a co-processor using offloading.

  • Stretch-goal: combining autodiff and offloading in one example that runs differentiated code on a GPU.

Frequently asked questions

Why do you implement these features only on the LLVM backend?

Performance-wise, we have LLVM and GCC as performant backends. Modularity-wise, we have LLVM and especially Cranelift being nice to modify. It seems reasonable that LLVM thus is the first backend to have support for new features in this field. Especially the offloading support should be supportable by other compiler backends, given pre-existing work like OpenMP offloading and WebGPU.

Do these changes have to happen in the compiler?

Yes, given how Rust works today.

However, both features could be implemented in user-space if the Rust compiler someday supported reflection. In this case we could ask the compiler for the optimized backend IR for a given function. We would then need use either the AD or offloading abilities of the LLVM library to modify the IR, generating a new function. The user would then be able to call that newly generated function. This would require some discussion on how we can have crates in the ecosystem that work with various LLVM versions, since crates are usually expected to have a MSRV, but the LLVM (and like GCC/Cranelift) backend will have breaking changes, unlike Rust.

Batching?

This is offered by all autodiff tools. JAX has an extra command for it, whereas Enzyme (the autodiff backend) combines batching with autodiff. We might want to split these since both have value on their own.

Some libraries also offer array-of-struct vs struct-of-array features which are related but often have limited usability or performance when implemented in userspace.

Writing a GPU backend in 6 months sounds tough…

True. But similar to the autodiff work, we’re exposing something that’s already existing in the backend.

Rust, Julia, C++, Carbon, Fortran, Chappel, Haskell, Bend, Python, etc. should not all have write their own GPU or autodiff backends. Most of these already share compiler optimization through LLVM or GCC, so let’s also share this. Of course, we should still push to use our Rust specific magic.

How about Safety?

We want all these features to be safe by default, and are happy to not expose some features if the gain is too small for the safety risk. As an example, Enzyme can compute the derivative with respect to a global. That’s probably too niche, and could be discouraged (and unsafe) for Rust.

Scalable Polonius support on nightly

Metadata
Point of contactRémy Rakic
StatusAccepted
Tracking issuerust-lang/rust-project-goals#118
Zulip channel[#t-types/polonius][channel]
Teamstypes
Task ownersAmanda Stjerna, Rémy Rakic, Niko Matsakis
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/186049-t-types.2Fpolonius

Summary

Keep working on implementing a native rustc version of the Polonius next generation borrow checking algorithm, that would scale better than the previous datalog implementation, continuing from the 2024h2 goal.

Motivation

Polonius is an improved version of the borrow checker that resolves common limitations of the borrow checker and which is needed to support future patterns such as “lending iterators” (see #92985). Its model also prepares us for further improvements in the future.

Some support exists on nightly, but this older prototype has no path to stabilization due to scalability issues. We need an improved architecture and implementation to fix these issues.

The next six months

  • Complete the ongoing work to land polonius on nightly

The “shiny future” we are working towards

Stable support for Polonius.

Ownership and team asks

Owner: lqd

Other support provided by Amanda Stjerna as part of her PhD.

TaskOwner(s) or team(s)Notes
Design reviewNiko Matsakis
ImplementationRémy Rakic, Amanda Stjerna
Standard reviewsTeam typesMatthew Jasper

Support needed from the project

We expect most support to be needed from the types team, for design, reviews, interactions with the trait solver, and so on. We expect Niko Matsakis, leading the polonius working group and design, to provide guidance and design time, and Michael Goulet and Matthew Jasper to help with reviews.

Outputs and milestones

Outputs

Nightly implementation of polonius that passes NLL problem case #3 and accepts lending iterators (#92985).

Performance should be reasonable enough that we can run the full test suite, do crater runs, and test it on CI, without significant slowdowns. We do not expect to be production-ready yet by then, and therefore the implementation would still be gated under a nightly -Z feature flag.

As our model is a superset of NLLs, we expect little to no diagnostics regressions, but improvements would probably still be needed for the new errors.

Milestones

Note: some of these are currently being worked on as part of the 2024h2 goal, and could be completed before the 2025h1 period.

MilestoneContributorNotes
Factoring out higher-ranked concerns from the main pathAmanda Stjerna
↳ [x] rewrite invalid universe constraints with outlives 'static constraintsPR 123720
↳ [ ] completely remove placeholdersin progress PR 130227
Location-sensitive prototype on nightlyRémy Rakicin progress
↳ [x] create structures for location-dependent outlives constraints
↳ [x] build new constraint graph from typeck constraints and liveness constraints
↳ [x] update NLLs for required changes to local & region liveness, loan liveness & loan scopes, (possibly unreachable) kills, bidirectional traversal & active loans
↳ [ ] limit regressions about diagnostics when using the new constraints on diagnostics tailored to the old constraints
↳ [ ] land on nightly under a -Z flag
[x] Debugging / dump tool for analysis of location-sensitive analysisRémy Rakic
[ ] Tests and validation of location-sensitive PoloniusRémy Rakic
↳ [ ] make the full test suite passin progress
↳ [ ] do a crater run for assertions and backwards-compatibility
↳ [ ] expand test suite with tests about the new capabilities
[ ] Location-sensitive pass on nightly, tested on CIRémy Rakic

Organize Rust All-Hands 2025

Metadata
Point of contactMara Bos
StatusAccepted
FlagshipYes
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#263
Teamsleadership-council
Task ownersall participants, every project member, project members, team leads (or delegate), Mara Bos, Planning team, Rust Foundation, RustNL, RustNL and moderator team, leadership-council

Summary

Organise another Rust All-Hands in 2025!

Motivation

It’s been too long since we’ve had a Rust All-Hands. Time to bring it back!

The status quo

Previous Rust All-Hands events were very useful and successful, but after the changes at Mozilla, we haven’t had a Rust All-Hands in six years. Meanwhile, the project has grown a lot, making it much harder and expensive to organise a new Rust All-Hands.

A few months ago, when Jack brought up having a new Rust All-Hands in the Leadership Council meeting, Mara proposed having the new Rust All-Hands at RustWeek 2025 by RustNL, which will take place in the Netherlands around the 10th birthday of Rust 1.0. Both RustNL and the Rust Leadership Council agreed.

See https://blog.rust-lang.org/inside-rust/2024/09/02/all-hands.html

The next 6 months

  • Prepare the all-hands and everything around it.
  • Have a social and informal “pre-all hands day” on Rust’s 10th birtday: May 15, 2025.
  • Have a two-day all-hands on May 16 and May 17, 2025.
  • During the all hands, coordinate reviews of the proposed Rust Vision Doc

The “shiny future” we are working towards

The immediate goal is a very successful and productive Rust All-Hands 2025. Hopefully, this will be the first step towards the larger goal of having regular Rust All-Hands again.

We should be able to use the feedback and lessons learned from this event for the next ones, and to figure out what the right frequency would be (yearly or less often). Repeating an event tends to be much easier than organising one from scratch.

Design axioms

  • Accessibility. Ideally, everyone in the project should be able to attend the Rust All-Hands
  • Productivity and effectivity. We should optimally make use of the event, to make it worth everyone’s time.
  • Low stress. The event or the planning of it should not burn anyone out. It is a tool to help the project and its members, after all!
  • Space for social events. The goal is not just to work on technical things together, but also to get to know each other and become a closer team.

Ownership and team asks

Owner: Mara

TaskOwner(s) or team(s)Notes
Pick the datesRustNL, leadership-councilComplete
Allocate fundsTeam leadership-councilComplete for event
Allocate fundsRust FoundationComplete for travel
Book the venueRustNLComplete
Catering / snacks / food / drinksRustNLComplete
Register for the Rust All-Hands 2025every project memberMajority already signed up!
Send out conformations/ticketsMara Bos
Send out detailed informationMara Bos
Answer logistical questionsMara Bos
Interface between project and RustNLMara Bos
Make hotel reservationsRustNLIn progress
Book hotelall participantsRustNL will provide suggestions
Book travelall participants
MiscellaneousTeam leadership-councilPrepare one or two plenary sessions
Submit talks for the “Rust Project Track”project membersPossibility to give talks at the conference before the all-hands.
Moderation / safetyRustNL and moderator team
Accessibility and covid safetyRustNL
Come to the Rust All-Hands 2025all participants
Reimburse travel costsRust Foundation

Team swag

TaskOwner(s) or team(s)Notes
MiscellaneousTeam leadership-councilDecide on team swag; suggestions very welcome!
Acquire swagRustNL

Make plans for what to do at the all-hands

TaskOwner(s) or team(s)Notes
Gather input from your teamsteam leads (or delegate)
Provide input for planning teamteam leads (or delegate)
Make an agenda for your team’s roomteam leads (or delegate)
Coordinate the overall processPlanning teamSmall group of 2-3 people. Volunteers welcome!
Make a room plan (after gathering input)Planning team

Organise an optional “pre all-hands day”

TaskOwner(s) or team(s)Notes
OrganisationMara Bos, RustNLAn optional day without an agenda, with space for social activities
Acquire gifts (secret!)Mara BosComplete

Frequently asked questions

I’m so excited about the all hands!

Me too!

How will we schedule meetings?

Jack Huey asked:

The key challenge here is going to be scheduling meetings for teams with overlapping membership. Likely it’ll probably make sense to stagger team meetings such that there are blocks of time with very few overlaps of “official” meetings (with the acknowledgement that maybe that means during those times the parallelism goes down).

Mara Bos answered:

Yeah that’s part of the reason for a “Planning team” to “Coordinate the overall process”. Hopefully we can make the draft agendas public early so teams can work together directly to align their plans a bit. It’s going to be a fun puzzle though. ^^

Who can attend?

Jack Huey asked:

One thing I haven’t seen listed is who other than the Project is/may attend? From what I remember, there is a separate space available - it would be really good to have an actual list for that, which is available to Project members, since people may be interested in chatting/coordinating.

Mara Bos answered:

There will be an unconference at the same venue that will host groups like the embedded working group, Rust for Linux, Bevy maintainers, UI/App developers, and a few other groups. That part is handled by RustNL as a mostly separate event, that just happens to take place in the same location.

RustNL will of course share which groups that will be once they confirm, so we can coordinate potential collaboration with these groups. But from a organisation (and funding) perspective, we treat the all-hands and the unconference as mostly separate events, which is why I didn’t include it in the project goal.

Use annotate-snippets for rustc diagnostic output

Metadata
Point of contactScott Schafer
StatusAccepted
Tracking issuerust-lang/rust-project-goals#123
Zulip channelN/A
Teamscompiler
Task ownersScott Schafer, Esteban Kuber

Summary

Switch to annotate-snippets for rendering rustc’s output, with no loss of functionality or visual regressions.

Motivation

Cargo has been [adding its own linting system][cargo-lints], where it has been using annotate-snippets to try and match Rust’s output. This has led to duplicate code between the two, increasing the overall maintenance load. Having one renderer that produces Rust-like diagnostics will make it so there is a consistent style between Rust and Cargo, as well as any other tools with similar requirements like miri, and should lower the overall maintenance burden by rallying behind a single unified solution.

The status quo

Currently rustc has its own Emitter that encodes the theming properties of compiler diagnostics. It has handle all of the intricacies of terminal support (optional color, terminal width querying and adapting of output), layout (span and label rendering logic), and the presentation of different levels of information. Any tool that wants to approximate rustc’s output for their own purposes, needs to use a third-party tool that diverges from rustc’s output, like annotate-snippets or miette. Any improvements or bugfixes contributed to those libraries are not propagated back to rustc. Because the emitter is part of the rustc codebase, the barrier to entry for new contributors is artificially kept high than it otherwise would be.

annotate-snippets is already part of the rustc codebase, but it is disabled by default, doesn’t have extensive testing and there’s no way of enabling this output through cargo, which limits how many users can actually make use of it.

The next 6 months

  • annotate-snippets rendered output reaches full parity (modulo reasonable non-significant divergences) with rustc’s output
  • A call for testing is made to the community to gather feedback on annotate-snippets

The “shiny future” we are working towards

The outputs of rustc and cargo are fully using annotate-snippets, with no regressions to the rendered output. annotate-snippets grows its feature set, like support for more advanced rendering formats or displaying diagnostics with more than ASCII-art, independently of the compiler development cycle.

Design axioms

  • Match rustc’s output: The output of annotate-snippets should match rustc, modulo reasonable non-significant divergences
  • Works for Cargo (and other tools): annotate-snippets is meant to be used by any project that would like “Rust-style” output, so it should be designed to work with any project, not just rustc. [da]: https://rust-lang.github.io/rust-project-goals/about/design_axioms.html

Ownership and team asks

Owner: Esteban Kuber, Scott Schafer

Reach output parity of rustc/annotate-snippets

TaskOwner(s) or team(s)Notes
add suggestionsScott Schafer
Port a subset of rustc’s UI testsScott Schafer
address divergencesScott Schafer

Initial use of annotate-snippets

TaskOwner(s) or team(s)Notes
update annotate-snippets to latest version
teach cargo to pass annotate-snippets flagEsteban Kuber
add ui test mode comparing new output
switch default nightly rustc output

Production use of annotate-snippets

TaskOwner(s) or team(s)Notes
switch default rustc output
release notes
switch ui tests to only check new output
Dedicated reviewerTeam compilerEsteban Kuber will be the reviewer

Standard reviews

TaskOwner(s) or team(s)Notes
Standard reviewsTeam compiler

Top-level Rust blog post inviting feedback

TaskOwner(s) or team(s)Notes
Top-level Rust blog post inviting feedback
[cargo-lints]: https://github.com/rust-lang/cargo/issues/12235

SVE and SME on AArch64

Metadata
Point of contactDavid Wood
StatusAccepted
FlagshipUnblocking dormant traits
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#270
Teamscompiler, lang, types
Task ownersJamie Cunliffe, David Wood

Arm’s Rust team is David Wood, Adam Gemmell, Jacob Bramley, Jamie Cunliffe and James, as well as @mrkajetanp and @harmou01 as graduates on rotation. This goal will be primarily worked on by David Wood and Jamie Cunliffe.

Summary

Over the next six months, we will aim to merge nightly support for SVE and establish a path towards stabilisation:

  • propose language changes which will enable scalable vector types to be represented in Rust’s type system
  • land an experimental nightly implementation of SVE
  • identify remaining blockers for SVE stabilisation and plan their resolution
  • gain a better understanding of SME’s implications for Rust and identify first steps towards design and implementation

Motivation

AArch64 is an important architecture for Rust, with two tier 1 targets and over thirty targets in lower tiers. It is widely used by some of Rust’s largest stakeholders and as a systems language, it is important that Rust is able to leverage all of the hardware capabilities provided by the architecture, including new SIMD extensions: SVE and SME.

The status quo

SIMD types and instructions are a crucial element of high-performance Rust applications and allow for operating on multiple values in a single instruction. Many processors have SIMD registers of a known fixed length and provide intrinsics which operate on these registers. Arm’s Neon extension is well-supported by Rust and provides 128-bit registers and a wide range of intrinsics.

Instead of releasing more extensions with ever increasing register bit widths, recent versions of AArch64 have a Scalable Vector Extension (SVE), with vector registers whose width depends on the CPU implementation and bit-width-agnostic intrinsics for operating on these registers. By using SVE, code won’t need to be re-written using new architecture extensions with larger registers, new types and intrinsics, but instead will work on newer processors with different vector register lengths and performance characteristics.

SVE has interesting and challenging implications for Rust, introducing value types with sizes that can only be known at compilation time, requiring significant work on the language and compiler. Arm has since introduced Scalable Matrix Extensions (SME), building on SVE to add new capabilities to efficiently process matrices, with even more interesting implications for Rust.

Hardware is generally available with SVE, and key Rust stakeholders want to be able to use these architecture features from Rust. In a recent discussion on SVE, Amanieu, co-lead of the library team, said:

I’ve talked with several people in Google, Huawei and Microsoft, all of whom have expressed a rather urgent desire for the ability to use SVE intrinsics in Rust code, especially now that SVE hardware is generally available.

While SVE is specifically an AArch64 extension, the infrastructure for scalable vectors in Rust should also enable Rust to support for RISC-V’s “V” Vector Extension, and this goal will endeavour to extend Rust in an architecture-agnostic way. SVE is supported in C through Arm’s C Language Extensions (ACLE) but requires a change to the C standard (documented in pages 122-126 of the 2024Q3 ACLE), so Rust has an opportunity to be the first systems programming language with native support for these hardware capabilities.

SVE is currently entirely unsupported by Rust. There is a long-standing RFC for the feature which proposes special-casing SVE types in the type system, and a experimental implementation on this RFC. While these efforts have been very valuable in understanding the challenges involved in implementing SVE in Rust, and providing an experimental forever-unstable implementation, they will not be able to be stabilised as-is.

This goal’s owners have an nearly-complete RFC proposing language changes which will allow scalable vectors to fit into Rust’s type system - this pre-RFC has been informally discussed with members of the language and compiler teams and will be submitted alongside this project goal.

The next 6 months

The primary objective of this initial goal is to land a nightly experiment with SVE and establish a path towards stabilisation:

  • Landing a nightly experiment is nearing completion, having been in progress for some time. Final review comments are being addressed and both RFC and implementation will be updated shortly.
  • A comprehensive RFC proposing extensions to the type system will be opened alongside this goal. It will primarily focus on extending the Sized trait so that SVE types, which are value types with a static size known at runtime, but unknown at compilation time, can implement Copy despite not implementing Sized.

The “shiny future” we are working towards

Adding support for Scalable Matrix Extensions in Rust is the next logical step following SVE support. There are still many unknowns regarding what this will involve and part of this goal or the next goal will be understanding these unknowns better.

Design axioms

  • Avoid overfitting. It’s important that whatever extensions to Rust’s type system are proposed are not narrowly tailored to support for SVE/SME, can be used to support similar extensions from other architectures, and unblocks or enables other desired Rust features wherever possible and practical.
  • Low-level control. Rust should be able to leverage the full capabilities and performance of the underlying hardware features and should strive to avoid inherent limitations in its support.
  • Rusty-ness. Extensions to Rust to support these hardware capabilities should align with Rust’s design axioms and feel like natural extensions of the type system.

Ownership and team asks

Here is a detailed list of the work to be done and who is expected to do it. This table includes the work to be done by owners and the work to be done by Rust teams (subject to approval by the team in an RFC/FCP).

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang, types, compiler

Land nightly experiment for SVE types

TaskOwner(s) or team(s)Notes
Land nightly experiment for SVE typesJamie Cunliffe
Author RFCUpdate rfcs#3268, will still rely on exceptions in the type system
RFC decisionTeam types
ImplementationUpdate rust#118917
Standard reviewsTeam compiler

Upstream SVE types and intrinsics

TaskOwner(s) or team(s)Notes
Upstream SVE types and intrinsicsJamie CunliffeUsing repr(scalable) from previous work, upstream the nightly intrinsics and types

Extending type system to support scalable vectors

TaskOwner(s) or team(s)Notes
Extending type system to support scalable vectorsDavid Wood
Author RFC
RFC decisionTeam types, lang
Implementation
Standard reviewsTeam compiler

Investigate SME support

TaskOwner(s) or team(s)Notes
Investigate SME supportJamie Cunliffe, David Wood
Discussion and moral supportTeam lang, types, compiler
Draft next goalDavid Wood

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Bring the Async Rust experience closer to parity with sync Rust

Metadata
Short titleAsync
Point of contactTyler Mandry
StatusAccepted
FlagshipYes
Tracking issuerust-lang/rust-project-goals#105
Zulip channel[#wg-async][channel]
Teamscompiler, lang, lang-docs, libs-api, types
Task ownersMichael Goulet, Eric Holk, Niko Matsakis, Santiago Pastorino, Tyler Mandry, TBD (Michael Goulet, or Niko Matsakis)
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/187312-wg-async/

Summary

Over the next six months, we will continue bringing Async Rust up to par with “sync Rust” by doing the following:

  • Telling a complete story for the use of async fn in traits, unblocking wide ecosystem adoption,
  • Improving the ergonomics of Pin, which is frequently used in low-level async code, and
  • Preparing to support asynchronous (and synchronous) generators in the language.

Motivation

This goal represents the next step on a multi-year program aiming to raise the experience of authoring “async Rust” to the same level of quality as “sync Rust”. Async Rust is a crucial growth area, with 52% of the respondents in the 2023 Rust survey indicating that they use Rust to build server-side or backend applications.

The status quo

Async Rust is the most common Rust application area according to our 2023 Rust survey. Rust is a great fit for networked systems, especially in the extremes:

  • Rust scales up. Async Rust reduces cost for large dataplanes because a single server can serve high load without significantly increasing tail latency.
  • Rust scales down. Async Rust can be run without requiring a garbage collector or even an operating system, making it a great fit for embedded systems.
  • Rust is reliable. Networked services run 24/7, so Rust’s “if it compiles, it works” mantra means fewer unexpected failures and, in turn, fewer pages in the middle of the night.

Despite async Rust’s popularity, using async I/O makes Rust significantly harder to use. As one Rust user memorably put it, “Async Rust is Rust on hard mode.” Several years back the async working group collected a number of “status quo” stories as part of authoring an async vision doc. These stories reveal a number of characteristic challenges:

The next 6 months

Tell a complete story for async fn in traits

  • Unblock AFIT in public traits by stabilizing RTN and implementable trait aliases (unblock tower 1.0)
  • Ship 1.0 of the dynosaur crate, enabling dynamic dispatch with AFIT
  • Stretch goal: Implement experimental support for async fn in dyn Trait in nightly

Improve ergonomics around Pin

  • Ratify and implement an RFC for auto-reborrowing of pinned references
  • Stretch goal: Discuss and implement a design for safe pin projection

Work toward asynchronous generators

  • Have design meetings and ratify an RFC for a syntax for authoring synchronous iterators (e.g., synchronous generators)
  • Stretch goal: Ratify an RFC for unsafe binders

In H2 we hope to tackle the following:

  • RTN in type position
  • Ratified RFC for syntactic support for asynchronous iteration

The “shiny future” we are working towards

Writing async code in Rust should feel just as expressive, reliable, and productive as writing sync code in Rust. Our eventual goal is to provide Rust users building on async with

  • the same core language capabilities as sync Rust (async traits with dyn dispatch, async closures, async drop, etc);
  • reliable and standardized abstractions for async control flow (streams of data, error recovery, concurrent execution), free of accidental complexity;
  • an easy “getting started” experience that builds on a rich ecosystem;
  • good performance by default, peak performance with tuning;
  • the ability to easily adopt custom runtimes when needed for particular environments, language interop, or specific business needs.

Design axioms

  • Uphold sync Rust’s bar for reliability. Sync Rust famously delivers on the general feeling of “if it compiles, it works” – async Rust should do the same.
  • Lay the foundations for a thriving ecosystem. The role of the Rust org is to develop the rudiments that support an interoperable and thriving async crates.io ecosystem.
  • When in doubt, zero-cost is our compass. Many of Rust’s biggest users are choosing it because they know it can deliver the same performance (or better) than C. If we adopt abstractions that add overhead, we are compromising that core strength. As we build out our designs, we ensure that they don’t introduce an “abstraction tax” for using them.
  • From embedded to GUI to the cloud. Async Rust covers a wide variety of use cases and we aim to make designs that can span those differing constraints with ease.
  • Consistent, incremental progress. People are building async Rust systems today – we need to ship incremental improvements while also steering towards the overall outcome we want.

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The overall owner of the effort is Tyler Mandry. We have identified owners for subitems below; these may change over time.

Overall program management

TaskOwner(s) or team(s)Notes
AFIT story blog postTyler Mandry

Return type notation

TaskOwner(s) or team(s)Notes
Initial implementationMichael GouletComplete
Author RFCNiko MatsakisComplete
RFC decisionTeam langComplete
Finished implementationMichael GouletComplete
Standard reviewsTeam types, compiler
Author stabilization reportMichael Goulet
Author Reference PRTBD (Michael Goulet, Tyler Mandry, or Niko Matsakis)
Review/revise Reference PRTeam lang-docsNiko Matsakis
Stabilization decisionTeam lang, types

Unsafe binders

TaskOwner(s) or team(s)Notes
Initial implementationMichael GouletStretch goal
Author RFCNiko MatsakisStretch goal
RFC decisionTeam lang, typesStretch goal

Implementable trait aliases

TaskOwner(s) or team(s)Notes
Author RFCTyler Mandry
ImplementationMichael Goulet
Standard reviewsTeam types, compiler
RFC decisionTeam lang, types

async fn in dyn Trait

TaskOwner(s) or team(s)Notes
Lang-team experimentNiko Matsakis(Approved)
ImplementationMichael GouletStretch goal

Pin ergonomics

TaskOwner(s) or team(s)Notes
ImplementationEric Holk
Author RFCEric Holk
Lang-team experimentTeam langComplete

Trait for generators (sync)

TaskOwner(s) or team(s)Notes
ImplementationEric Holk
Author RFC
RFC decisionTeam libs-api, lang
Design meetingTeam lang2 meetings expected

Dynosaur 1.0

TaskOwner(s) or team(s)Notes
ImplementationSantiago Pastorino
Standard reviewsTyler Mandry

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Why work on synchronous generators if your goal is to support async?

There are three features we want that all interact quite heavily with each other:

  • Sync generators
  • Async generators
  • Async iteration trait

Of the three, we think we are the closest to ratifying an RFC for synchronous generators. This should help clarify one of the major outstanding questions for the other two items; namely, the relation to pinning. With that out of the way, we should better be able to focus on the iteration trait and how well it works with async generators.

Focusing on pinning first also synergizes well with the efforts to improve the ergonomics of pinning.

build-std

Metadata
Point of contactDavid Wood
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#274
Teamscargo
Task ownersAdam Gemmell

Arm’s Rust team is David Wood, Adam Gemmell, Jacob Bramley, Jamie Cunliffe and James. This goal will be primarily worked on by Adam Gemmell, but David Wood can always be contacted for updates.

Summary

Write an RFC for a minimum viable product (MVP) of build-std which has the potential to be stabilised once implemented (as opposed to the currently implemented MVP which is only suitable for experimentation and testing), and then implement it.

Motivation

build-std is a well-known unstable feature in Cargo which enables Cargo to re-build the standard library, this is useful for a variety of reasons:

  • Building the standard library for targets which do not ship with a pre-compiled standard library.
  • Optimising the standard library for known hardware, such as with non-baseline target features or options which optimise for code size. This is a common use case for embedded developers.
  • Re-building the standard library with different configuration options (e.g. changing the optimisation level, using flags which change the ABI, or which add additional exploit mitigations).
  • Re-building the standard library with different cfgs (e.g. disabling backtrace in std), to the extent that such configurations are supported by the standard library.
  • Stabilisation of various compiler flags which change the ABI, add additional exploit mitigations (such as -Zsanitizers=cfi or -Zbranch-protection), or which otherwise only make sense to use when the entire program is compiled with the flag (including std) is blocked on these being unable to be used properly without being able to rebuild std.

These features are more useful for some subsets of the Rust community, such as embedded developers where optimising for size can be more important and where the targets often don’t ship with a pre-compiled std.

The fifty-thousand foot view of the work involved in this feature is:

  • Having the standard library sources readily available that match the compiler.
  • Being able to build those sources without using a nightly toolchain, which has many possible solutions.
  • Having a blessed way to build at least core without Cargo, which some users like Rust for Linux would like.
    • This would be optional but may be a side-effect of whatever mechanism for build-std the MVP RFC eventually proposes.
  • Being able to tell the compiler to use the resulting prebuilt standard library sources instead of the built-in standard library, in a standard way.
  • Integrating all of the above into Cargo.
  • Making sure all of this works for targets that don’t have a pre-built std.

Rust for Linux and some other projects have a requirement to build core themselves without Cargo (ideally using the same stable compiler they use for the rest of their project), which is a shared requirement with build-std, as whatever mechanism these projects end up using could be re-used by the implementation of build-std and vice-versa.

The status quo

build-std is currently an unstable feature in Cargo which hasn’t seen much development or progress since its initial development in 2019/2020. There are a variety of issues in the wg-cargo-std-aware repository which vary from concrete bugs in the current experimental implementation to vague “investigate and think about this” issues, which make the feature difficult to make progress on.

Some of the work required for this exists in the current perma-unstable -Zbuild-std implementation, which may be re-used if appropriate.

Prior to the submission of this goal, this goal has been discussed with the cargo team and leads of the compiler and library teams, ensuring that this goal’s owners have liaisons from stakeholder teams and the support of the primary teams involved in the design and implementation.

The next 6 months

There are two primary objectives of this goal in its first six months:

  • Firstly, we will write an MVP RFC that will limit the scope of the feature and make it easier to make progress on build-std.

    It is intended that this RFC will summarize all of the previous discussion, use cases and feedback on build-std. In this documenting of the current state of build-std, this RFC will be well-positioned to propose which use cases should and should not be resolved by build-std (for the final feature, not just this MVP). For example, this RFC will decide whether patching or modifying std is a supported use case for build-std.

    For those use cases solved by build-std, the RFC will select a subset for the new MVP of build-std. It is intended that this MVP be sufficiently useful and complete that it could be stabilised. The design of the MVP will be forward-compatible with all of the other use cases that build-std is intended to solve.

    It is hoped that this RFC should demonstrate a thorough understanding of the design space of build-std and give the responsible upstream teams confidence in our ownership of this feature, and enabling those teams to make a fully informed decision on any proposals made.

  • Next, after and conditional on acceptance of this RFC, we will proceed with its implementation.

The “shiny future” we are working towards

After the approval and implementation of the MVP RFC, there will naturally be follow-up use cases which can be designed and implemented to complete the build-std feature.

Design axioms

  • Enabling build-std without changing any compilation options or configuration should produce an equivalent library to that distributed by the project.
  • Avoid precluding future extensions to build-std.
  • build-std should allow std/alloc/core to be treated more like other dependencies than currently.
    • This represents a general move away from treating std/alloc/core as a special case.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo
Author RFCAdam Gemmell
ImplementationAdam Gemmell
Standard reviewsTeam cargo

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Prototype a new set of Cargo “plumbing” commands

Metadata
Point of contactEd Page
StatusAccepted
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#264
Teamscargo
Task ownersHelp wanted, Ed Page

Summary

Create a third-party cargo subcommand that has “plumbing” (programmatic) subcommands for different phases of Cargo operations to experiment with what Cargo should integrate.

Motivation

Cargo is a “porcelain” (UX) focused command and is highly opinionated which can work well for common cases. However, as Cargo scales into larger applications, users need the ability to adapt Cargo to their specific processes and needs.

The status quo

While most Cargo commands can be used programmatically, they still only operate at the porcelain level. Currently, Cargo’s plumbing commands are

  • cargo read-manifest:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • deprecated
  • cargo locate-project:
    • works off of a Cargo.toml file on disk
    • text or json output, undocumented json schema
    • uses a pre-1.0 term for package
  • cargo metadata:
    • works off of Cargo.toml, Cargo.lock files on disk
    • uses a custom json schema
    • can include dependency resolution but excludes feature resolution
    • some users want this faster
    • some users want this to report more information
    • See also open issues
  • cargo pkgid:
    • works off of Cargo.toml, Cargo.lock files on disk
    • text output
  • cargo verify-project:
    • works off of a Cargo.toml file on disk
    • uses a custom json schema
    • uses a pre-1.0 term for package
    • deprecated

There have been experiments for a plumbing for builds

  • --build-plan attempts to report what commands will be run so external build tools can manage them.
    • The actual commands to be run is dynamic, based on the output of build scripts from build graph dependencies
    • Difficulty in supporting build pipelining
  • --unit-graph reports the graph the build operates off of which corresponds to calls to the compiler and build scripts
    • Also provides a way to get the results of feature resolution

The next 6 months

Create a third-party subcommand to experiment with plumbing commands.

A build in Cargo can roughly be split into

  1. Locate project
  2. Read the manifests for a workspace
  3. Read lockfile
  4. Lock dependencies
  5. Write lockfile
  6. Resolve features
  7. Plan a build, including reading manifests for transitive dependencies
  8. Execute a build
  9. Stage final artifacts

These could serve as starting points for experimenting with plumbing commands. Staging of final artifacts may not be worth having a dedicated command for. This is exclusively focused on build while other operations may be of interest to users. We can evaluate those commands in the future as they tend to still build off of these same core primitives.

At minimum, later commands in the process would accept output from earlier commands, allowing the caller to either replace commands (e.g. custom dependency resolver) or customize the output (e.g. remove dev-dependencies from manifests).

Encapsulating stabilized file formats can serve as a starting point for output schemas as we already output those and have to deal with stability guarantees around these.

Between planning a build and executing a build is likely to look like --unit-graph and a plan will need to be put forward for how to work through the open issues. There will likely be similar issues for any other output that can’t leverage existing formats.

Cargo’s APIs may not be able to expose each of these stages and work may need to be done to adapt it to support these divisions.

The performance of piping output between these commands may be sub-par, coming from a combination of at least

  • Cargo’s APIs may require doing more work than is needed for these stages
  • Cargo focuses on json for programmatic output which may prove sub-par (see also zulip)
  • Cargo’s serde structures may not be optimized
  • If customizing only a single step in this process, requiring serializing and deserializing through all of the other stages may be superfluous

Low hanging or egregious bottlenecks may need to be addressed. Otherwise, performance should wait on user feedback.

A schema evolution plan will need to be considered with the design of the schema. How Cargo deals with evolution of existing output could serve as potential starting points:

  • Cargo.toml (generated by cargo package) should still be readable by cargo versions within the specified package.rust-version
    • In the absence of a package.rust-version, Cargo.toml should only represent features the user explicitly used or optional features that were always allowed on stable cargo
  • Cargo.lock (generated by most commands) is strictly versioned: all versions of Cargo should output a lockfile that works in all other versions of Cargo for that given version and changing Cargo versions should not cause the output to change
    • Cargo bumps the default format version after it has been stabilized for a “sufficient period of time”
    • The default is capped by what is supported by the lowest package.rust-version in the workspace
  • cargo metadata --format-version: defaults to “latest” with a warning
    • We attempt to follow the same practice as Cargo.toml
  • --message-format: no versioning currently
    • We attempt to follow the same practice as Cargo.toml

The “shiny future” we are working towards

  • Collect user feedback on these commands and iterate on them for eventual inclusion into Cargo
  • Evaluate refactoring Cargo to better align with these plumbing commands to have better boundaries between subsystems
  • Evaluate splitting the cargo [lib] into crates for each of these plumbing commands as smaller, more approachable, more “blessed” Rust APIs for users to call into

Design axioms

  • The changes to Cargo should not impede the development of Cargo
  • The schemas and planned evolution should not impede the development of Cargo
  • The plumbing commands should be focused on solving expected or known needs, avoiding speculation.

Ownership and team asks

Owner: Identify a specific person or small group of people if possible, else the group that will provide the owner. GitHub user names are commonly used to remove ambiguity.

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo
ImplementationHelp wanted
Optimizing CargoHelp wanted, Ed Page
Inside Rust blog post inviting feedbackEd Page

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Stabilize cargo-script

Metadata
Point of contactEd Page
StatusAccepted
Tracking issuerust-lang/rust-project-goals#119
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)
Teamscargo, compiler, lang, lang-docs
Task ownersEd Page

Summary

Stabilize support for “cargo script”, the ability to have a single file that contains both Rust code and a Cargo.toml.

Motivation

Being able to have a Cargo package in a single file can reduce friction in development and communication, improving bug reports, educational material, prototyping, and development of small utilities.

The status quo

Today, at minimum a Cargo package is at least two files (Cargo.toml and either main.rs or lib.rs). The Cargo.toml has several required fields.

To share this in a bug report, people resort to

  • Creating a repo and sharing it
  • A shell script that cats out to multiple files
  • Manually specifying each file
  • Under-specifying the reproduction case (likely the most common due to being the easiest)

To create a utility, a developer will need to run cargo new, update the Cargo.toml and main.rs, and decide on a strategy to run this (e.g. a shell script in the path that calls cargo run --manifest-path ...).

The next 6 months

The support is already implemented on nightly. The goal is to stabilize support. With RFC #3502 and RFC #3503 approved, the next steps are being tracked in rust-lang/cargo#12207.

At a high-level, this is

  • Add support to the compiler for the frontmatter syntax
  • Add support in Cargo for scripts as a “source”
  • Polish

The “shiny future” we are working towards

Design axioms

  • In the trivial case, there should be no boilerplate. The boilerplate should scale with the application’s complexity.
  • A script with a couple of dependencies should feel pleasant to develop without copy/pasting or scaffolding generators.
  • We don’t need to support everything that exists today because we have multi-file packages.

Ownership and team asks

Tracking issue cargo#12207:

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler
Ensure Cargo implementationEd Page

Implement language feature frontmatter

Tracking issue #136889(https://github.com/rust-lang/rust/issues/136889):

TaskOwner(s) or team(s)Notes
Rustc implementationEd Page
Rust-analyzer implementationEd Page
Standard reviewsTeam compiler
Author call for testing blog postEd Page

Stabilize language feature frontmatter

TaskOwner(s) or team(s)Notes
Author Reference PREd Page
Review/revise Reference PRTeam lang-docsEric Huss
Author stabilization reportEd Page
Author stabilization PREd Page
Stabilization decisionTeam lang

Definitions

For definitions for terms used above, see the About > Team Asks page.

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Continue resolving cargo-semver-checks blockers for merging into cargo

Metadata
Point of contactPredrag Gruevski
StatusAccepted
Tracking issuerust-lang/rust-project-goals#104
Zulip channelN/A
Teamscargo, rustdoc
Task ownersPredrag Gruevski

Summary

Design and implement cargo-semver-checks functionality that lies on the critical path for merging the tool into cargo itself. Continues the work of the 2024h2 goal.

Motivation

Cargo assumes that all packages adhere to semantic versioning (SemVer). However, SemVer adherence is quite hard in practice: research shows that accidental SemVer violations are relatively common (lower-bound: in 3% of releases) and happen to Rustaceans of all skill levels. Given the significant complexity of the Rust SemVer rules, improvements here require better tooling.

cargo-semver-checks is a linter for semantic versioning (SemVer) in Rust. It is broadly adopted by the Rust community, and the cargo team has expressed interest in merging it into cargo itself as part of the existing cargo publish workflow. By default, cargo publish would require SemVer compliance, but offer a flag (analogous to the --allow-dirty flag for uncommitted changes) to override the SemVer check and proceed with publishing anyway.

The cargo team has identified a set of milestones and blockers that must be resolved before cargo-semver-checks can be integrated into the cargo publish workflow. Our goal here is to make steady progress toward resolving them.

The status quo after the 2024h2 goal

As part of the 2024h2 goal work, support for cargo manifest linting was merged into cargo-semver-checks. This lifted one of the blockers blocker for SemVer-checking as part of cargo publish.

Work is still required in two major areas:

  • Checking of cross-crate items
  • SemVer linting of type information

Some work in each of these areas already happened in the 2024h2 goal:

  • The manifest linting work required a significant refactor of the tool’s data-handling infrastructure. As part of that major refactor, we were able to also create “API space” for a future addition of cross-crate information.
  • The compiler team MCP required to expose cross-crate information to rustdoc was merged, and together with T-rustdoc, we now have a plan for exposing that information to cargo-semver-checks.
  • We have implemented a partial schema that makes available a limited subset of type information around generic parameters and trait bounds. It’s sufficient to power a set of new lints, though it isn’t comprehensive yet.

Fully resolving the blockers is likely a 12-24 month undertaking, and beyond the scope of this goal on its own. Instead, this goal proposes to accomplish intermediate steps that create immediate value for users and derisk the overall endeavor, while needing only “moral support” from the cargo team as its only requirement.

Checking of cross-crate items

This section is background information and is unchanged from the 2024h2 goal.

Currently, cargo-semver-checks performs linting by only using the rustdoc JSON of the target package being checked. However, the public API of a package may expose items from other crates. Since rustdoc no longer inlines the definitions of such foreign items into the JSON of the crate whose public API relies on them, cargo-semver-checks cannot see or analyze them.

This causes a massive number of false-positives (“breakage reported incorrectly”) and false-negatives (“lint for issue X fails to spot an instance of issue X”). In excess of 90% of real-world false-positives are traceable back to a cross-crate item, as measured by our SemVer study!

For example, the following change is not breaking but cargo-semver-checks will incorrectly report it as breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example() {}

// in the new release, imagine this function moved to `another_crate`:
pub use another_crate::example;
}

This is because the rustdoc JSON that cargo-semver-checks sees indeed does not contain a function named example. Currently, cargo-semver-checks is incapable of following the cross-crate connection to another_crate, generating its rustdoc JSON, and continuing its analysis there.

Resolving this limitation will require changes to how cargo-semver-checks generates and handles rustdoc JSON, since the set of required rustdoc JSON files will no longer be fully known ahead of time. It will also require CLI changes in the same area as the changes required to support manifest linting.

While there may be other challenges on rustc and rustdoc’s side before this feature could be fully implemented, we consider those out of scope here since there are parallel efforts to resolve them. The goal here is for cargo-semver-checks to have its own story straight and do the best it can.

SemVer linting of type information

This section is background information and is unchanged from the 2024h2 goal.

In general, at the moment cargo-semver-checks lints cannot represent or examine type information. For example, the following change is breaking but cargo-semver-checks will not detect or report it:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: i64) {}
}

Analogous breaking changes to function return values, struct fields, and associated types would also be missed by cargo-semver-checks today.

The main difficulty here lies with the expressiveness of the Rust type system. For example, none of the following changes are breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: impl Into<String>) {}

// subsequent release:
pub fn example<S: Into<String>>(value: S) {}
}

Similar challenges exist with lifetimes, variance, trait solving, async fn versus fn() -> impl Future, etc.

While some promising preliminary work has been done toward resolving this challenge, more in-depth design work is necessary to determine the best path forward.

The next 6 months

  • Prototype cross-crate linting using manual workarounds for the current rustc and rustdoc blockers. This will allow us to roll out a full solution relatively quickly after the rustc and rustdoc blockers are resolved.
  • Expose data on generic types, lifetimes, functions, methods, and bounds in sufficient granularity for linting.
  • Determine how to handle special cases, such as changes to impls or bounds involving 'static, ?Sized, dyn Trait etc.
  • Improve sealed trait analysis to account for #[doc(hidden)] items, resolving many false-positives.

The “shiny future” we are working towards

This section is unchanged from the 2024h2 goal.

Accidentally publishing SemVer violations that break the ecosystem is never fun for anyone involved.

From a user perspective, we want a fearless cargo update: one’s project should never be broken by updating dependences without changing major versions.

From a maintainer perspective, we want a fearless cargo publish: we want to prevent breakage, not to find out about it when a frustrated user opens a GitHub issue. Just like cargo flags uncommitted changes in the publish flow, it should also quickly and accurately flag breaking changes in non-major releases. Then the maintainer may choose to release a major version instead, or acknowledge and explicitly override the check to proceed with publishing as-is.

To accomplish this, cargo-semver-checks needs the ability to express more kinds of lints (including manifest and type-based ones), eliminate false-positives, and stabilize its public interfaces (e.g. the CLI). At that point, we’ll have lifted the main merge-blockers and we can consider making it a first-party component of cargo itself.

Ownership and team asks

Owner: Predrag Gruevski, as maintainer of cargo-semver-checks

I (Predrag Gruevski) will be working on this effort. The only other resource request would be occasional discussions and moral support from the cargo and rustdoc teams, of which I already have the privilege as maintainer of a popular cargo plugin that makes extensive use of rustdoc JSON.

TaskOwner(s) or team(s)Notes
Prototype cross-crate linting using workaroundsPredrag Gruevski
Allow linting generic types, lifetimes, boundsPredrag Gruevski
Handle “special cases” like 'static and ?SizedPredrag Gruevski
Handle #[doc(hidden)] in sealed trait analysisPredrag Gruevski
Discussion and moral supportTeam cargo rustdoc

Frequently asked questions

This section is unchanged from the 2024h2 goal.

Why not use semverver instead?

Semverver is a prior attempt at enforcing SemVer compliance, but has been deprecated and is no longer developed or maintained. It relied on compiler-internal APIs, which are much more unstable than rustdoc JSON and required much more maintenance to “keep the lights on.” This also meant that semverver required users to install a specific nightly versions that were known to be compatible with their version of semverver.

While cargo-semver-checks relies on rustdoc JSON which is also an unstable nightly-only interface, its changes are much less frequent and less severe. By using the Trustfall query engine, cargo-semver-checks can simultaneously support a range of rustdoc JSON formats (and therefore Rust versions) within the same tool. On the maintenance side, cargo-semver-checks lints are written in a declarative manner that is oblivious to the details of the underlying data format, and do not need to be updated when the rustdoc JSON format changes. This makes maintenance much easier: updating to a new rustdoc JSON format usually requires just a few lines of code, instead of “a few lines of code apiece in each of hundreds of lints.”

Making compiletest more maintainable: reworking directive handling

Metadata
Point of contactJieyou Xu
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#259
Teamsbootstrap, compiler, rustdoc
Task ownersJieyou Xu

Summary

Short description of what you will do over the next 6 months.

Rework [compiletest]’s directive handling to make it more maintainable, have better UX for compiler contributors, and fix some long-standing issues.

Motivation

rustc relies on the test infrastructure implemented by the test harness [compiletest] (supported by bootstrap) to run the test suites under tests/ (e.g. ui tests, mir-opt tests, run-make tests, etc.). However, [compiletest] is currently very undertested and undermaintained, which is not ideal because we rely on the test suites to check rustc’s behavior. The current implementation in [compiletest] is also such that it’s very hard and unpleasant to make changes (e.g. adding new directives) to provide up-to-date test infrastructure support for the needs of compiler (and rustdoc) contributors. The UX is not great either because of poor error handling and error reporting.

The status quo

The current status quo is that [compiletest] imposes significant friction for compiler (and rustdoc) contributors who want to run tests and diagnose test failures. [compiletest] error messages are opaque, terse and hard to read. We had to include a separate allow-list of known directives to detect unknown directives. We still sometimes let malformed directives through and silently do nothing. Argument splitting is naive and inconsistent. The implementation is very convoluted. Also there’s still insufficient documentation.

See the tracking issue of various directive handling related bugs.

The next 6 months

The key changes I want to achieve:

  1. Directive handling is testable (at all) and in addition have strong test coverage.
  2. Directives have stricter syntax to reduce ambiguity and enable invalid directive detection or make invalid directive detection easier.
  3. Directives are well-documented. Move directive documentation close to directives themselves and make it possible to be generated alongside tool docs for compiletest, so it’s less likely to become outdated and to enable documentation coverage enforcement.
    • Also, make sure that we have robust self documentation so it’s not only one or two contributors who understands how things work inside compiletest
  4. Generally improve directive handling robustness. Examples: fixing argument splitting in compile-flags, fix paths related to aux-build, etc.
  5. Test writers and reviewers can receive better diagnostics, for things like a directive is not accepted in a given test suite or why something in compiletest failed.

The “shiny future” we are working towards

My long-term goal for [compiletest] is that I want it to make it significantly easier to maintain. Concretely, this means significantly better test coverage, easier to extend, better documentation. Hopefully, by being more maintainable, we are able to attract more active maintainers from both bootstrap and compiler teams and make the code base significantly more pleasant to work on.

For directive handling specifically, it should mean that:

  • It’s relatively straightforward and low friction to implement new directives, including test coverage and documentation. It should be easy to do the right thing.
  • [compiletest] should produce error messages that are easy to read and understand, possibly even making suggestions.
  • Directives should be documented (and enforced to be documented) via rustdoc which are made available on nightly-rustc docs so we can back-link from dev-guide and not have to maintain two sets of docs that are mutually inconsistent.

Ownership and team asks

Owner: [Jieyou Xu]

Note that [compiletest] is (in theory) currently co-maintained by both t-bootstrap and t-compiler, but AFAIK is (in practice) currently not really actively maintained by anyone else. The following team asks are probably mostly compiler for feedback on their use cases (as a test infra consumer) and bootstrap for implementation review.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam bootstrap, compiler, rustdocincluding consultations for desired test behaviors and testing infra consumers
Experimental prototype implementation1Jieyou Xuto see how approaches look like and gain experience/feedback
[compiletest] changes w/ experience from prototypeJieyou Xu
Standard reviewsTeam bootstrap, compilerProbably mostly bootstrap or whoever is more interested in reviewing [compiletest] changes
Inside Rust blog post for project outcomeJieyou Xu

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

TODO: pending during project discussions

[Jieyou Xu]: https://github.com/jieyouxu [compiletest]: https://github.com/rust-lang/rust/tree/master/src/tools/compiletest


  1. I want to start with an out-of-tree experimental prototype to see how the pieces are fit together to make it easier to rapidly iterate and receive feedback without having to mess with the “live” [compiletest] that does not have sufficient test coverage.

Prepare const traits for stabilization

Metadata
Point of contactOliver Scherer
StatusAccepted
Tracking issuerust-lang/rust-project-goals#106
Zulip channelN/A
Teamscompiler, lang, types
Task ownersMichael Goulet, Deadbeef, Niko Matsakis, Oliver Scherer, tiif, rust-lang/project-const-traits

Summary

Prepare const Trait bounds for stabilization.

Motivation

const fn on stable are unable to invoke trait methods, limiting their usefulness. After years of experimentation, the compiler now has a promising implementation of const traits and key parts of the stdlib have been updated to use it. However, the feature is still firmly in experimental territory: there has never been an RFC describing its syntax.

The goal for the next 6 months is to author an RFC proposing an end-user syntax for const bounds and a specific semantics. Our believe is that the core implementation work is done and that it should be possible to merge the RFC, implement the syntactic choices, issue a public call for experimentation, and otherwise pave the ground for stabilization (stabilization itself is a stretch goal and seems likely to occur in 2025H2).

The status quo

People write a lot of code that will be run in compile time. They include procedural macros, build scripts (42.8k hits on GitHub for build.rs), and const functions/consts (108k hits on GitHub for const fn). Not being able to write const functions with generic behavior is often cited as a pain point of Rust’s compile time capabilities. Because of the limited expressiveness of const fn, people may decide to move some compile time logic to a build script, which could increase build times, or simply choose not to do it in compile time (even though it would have helped runtime performance).

There are also language features that require the use of traits, such as iterating with for and handling errors with ?. Because the Iterator and Try traits currently cannot be used in constant contexts, people are unable to use ? to handle results, nor use iterators e.g. for x in 0..5.

The next 6 months

The primary goal is to do “Everything but” stabilization of this feature over the next 6 months

  • Author an RFC for const traits and get it accepted by the language design team
  • Implement the syntax and user experience described in the RFC
  • Issue a call for experimentation and resolve any issues found
  • Author a stabilization report

As a secondary goal, we will use this as an experiment to drive forward a-mir-formality, with Niko Matsakis and Oliver Scherer mentoring tiif to extend a-mir-formality with support for const traits.

The “shiny future” we are working towards

We’re working towards enabling developers to do more things in general within a const context. Const traits is a blocker for many future possibilities (see also the const eval feature skill tree) including heap operations in const contexts.

Design axioms

None.

Ownership and team asks

Steps towards the primary goal of doing everything towards stabilization apart from approving stabilization itself:

TaskOwner(s) or team(s)Notes
Lang-team experimentTeam langComplete
Experimental implementationDeadbeef, Michael GouletComplete
Author RFCOliver SchererComplete
Adjust implementation to match RFCrust-lang/project-const-traits
Call for testingOliver Scherer
Standard reviewsTeam compiler
Design meetingTeam langfirst meeting scheduled for Jan; second meeting may be required
RFC decisionTeam lang(stretch goal)
RFC secondary reviewTeam typesTypes team needs to validate the approach
Author specification 1st draftOliver Scherer

Formalize const-traits in a-mir-formality

Steps towards formalization of the approach in a-mir-formality:

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam typesDuring types team office hours, we’ll share information about our progress.
Implementationtiif
Mentoring and kibbitzingNiko Matsakis, Oliver Scherer

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Will we be stabilizing the syntax found on libstd today?

Most likely not. The current syntax includes some controversial notation, such as T: ~Trait. The point of the RFC is to determine what syntax will be used. What we hope will not change is the semantics.

Externally Implementable Items

Metadata
Point of contactMara Bos
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#254
Teamscompiler, lang
Task ownersJana and Mara, Jana, compiler, lang

Summary

We intend to implement Externally Implementable Items in the compiler. The plan is to do so in a way that allows us to change the way #[panic_handler] and similar attributes are handled, making these library features instead of compiler built-ins. We intend to eventually support both statics and functions, but the priority is at functions right now.

Motivation

(as per the rfcs1 2 3 on this):

We have several items in the standard library that are overridable/definable by the user crate. For example, the (no_std) panic_handler, the global allocator for alloc, and so on.

Each of those is a special lang item with its own special handling. Having a general mechanism simplifies the language and makes this functionality available for other crates, and potentially for more use cases in core/alloc/std.

In general, having externally implementable items be feature of the language instead of magic lang items and linker hacks gives more flexibility. It creates a standard interface to expose points where libraries can be customized.

Additionally, making externally implementable items a language feature makes it easier to document these points of customization. They can become part of the public api of a crate.

The status quo

Today, “externally implementable items” exist in various forms that each have their own implementation. Examples are the #[panic_handler], the global allocator, the global logger of the log crate, and so on. Some of these are magical lang items, whereas others need to be set at runtime or are done (unsafely) through a global (#[no_mangle]) linker symbol.

After [RFC 3632], which proposes a new syntax for externally implementable functions, several alternative ideas were proposed in rapid succession that focus on statics, traits, and impl blocks rather than function definitions. Each of these having roughly equivalent power, but using a different part of Rust to achieve it.

The lang team agreed that this is a problem worth solving, and accepted it as a lang experiment.4

While working on implementing possible solutions, we concluded that it’d be better to make use of attributes rather than new syntax, at least for now.5

Because this requires support for name resolution in attributes, this led to a big detour: refactoring how attributes are implemented and handled in rustc.6 The main part of that is now merged7, allowing us to finally continue on implementing the externally implementable items experiment itself.

The next 6 months

The goal for the next six months is to finish the implementation of externally implementable items (as an experimental feature).

It is not unthinkable that we run into more obstacles that requires some changes in the compiler, but we estimate that six months is enough to make the feature available for experimentation.

The “shiny future” we are working towards

This feature should be able to replace the magic behind the panic handler, global allocator, oom handler, and so on. At that point, an attribute like #[panic_handler] would simply be a regular (externally implementable) item exported by core, for example.

After stabilization, other crates in the ecosystem, such as the log crate, should be able to make use of this as well. E.g., they could have a #[log::global_logger] item that can be used to provide the global logger.

In the longer term, this could enable more fine grained customization of parts of core, alloc and std, such as panic handling. For example, right now, all kind of panics, including overflows and out-of-bounds panics, can all only be handled through the #[panic_handler], which will only get a panic message containing an (english) description of the problem. Instead, one could imagine having a #[panic_oob_handler] that gets the index and size as arguments, allowing one to customize the default behavior.

Design axioms

The experimental feature we implement should:

  • be able to replace how #[panic_handler] and global allocator features are implemented.
    • This means the feature should not have a higher (memory, performance, etc.) cost than how those features are currently implemented.
    • This also puts some requirements on the supported functionality, to support everything that those features currently support. (E.g., being able to provide a default implementation that can be overridden later.)
  • be ergonomic.
    • This means that mistakes should not result in confusing linker errors, but in reasonable diagnostics.
  • allow for semver-compatible upgrade paths.
    • E.g. if a crate wants to change the signature or kind of an externally implementable item, it should be possible to have some backwards-compatible path forward.
  • be as close to zero-cost as possible.
    • E.g. adding the option for more fine grained panic handlers to core should not result in a loss of performance.

Ownership and team asks

Owner: Jana Dönszelmann and Mara Bos

TaskOwner(s) or team(s)Notes
Discussion and moral supportcompiler, lang
Lang-team experimentTeam langComplete
Design experiment (syntax, etc.)Jana and MaraDone
Refactor attributes in rustcJanaIn progress, refactor merged
Implement experimentJana and Mara
Standard reviewsTeam compiler
Blog post inviting feedbackJana and Mara
Update RFC with new findingsJana and Mara

Frequently asked questions

  • None yet.

  1. https://github.com/rust-lang/rfcs/pull/3632

  2. https://github.com/rust-lang/rfcs/pull/3635

  3. https://github.com/rust-lang/rfcs/pull/3645

  4. https://github.com/rust-lang/rfcs/pull/3632#issuecomment-2125488373

  5. https://github.com/rust-lang/rust/issues/125418#issuecomment-2360542039

  6. https://github.com/rust-lang/rust/issues/131229

  7. https://github.com/rust-lang/rust/pull/131808

Experiment with ergonomic ref-counting

Metadata
Point of contactSantiago Pastorino
StatusAccepted
Tracking issuerust-lang/rust-project-goals#107
Zulip channelN/A
Teamslang
Task ownersJosh Triplett, Niko Matsakis, Santiago Pastorino

Summary

  • Deliver a nightly implementation of the experimental use syntax for ergonomic ref-counting.
  • RFC decision on the above

Motivation

For 2025H1 we propose to continue pursuing the use syntax that makes it more ergonomic to work with “cheaply cloneable” data particularly the use || closures. The specific goals are to land an experimental nightly implementation and an accepted RFC so that we can collect feedback from Rust Nightly users.

Like many ergonomic issues, these impact all users, but the impact is particularly severe for newer Rust users, who have not yet learned the workarounds, or those doing higher-level development, where the ergonomics of Rust are being compared against garbage-collected languages like Python, TypeScript, or Swift.

The status quo

Many Rust applications—particularly those in higher-level domains—use reference-counted values to pass around core bits of context that are widely used throughout the program. Reference-counted values have the convenient property that they can be cloned in O(1) time and that these clones are indistinguishable from one another (for example, two handles to a Arc<AtomicInteger> both refer to the same counter). There are also a number of data structures found in the stdlib and ecosystem, such as the persistent collections found in the im crate or the Sender type from std::sync::mpsc and tokio::sync::mpsc, that share this same property.

Rust’s current rules mean that passing around values of these types must be done explicitly, with a call to clone. Transforming common assignments like x = y to x = y.clone() can be tedious but is relatively easy. However, this becomes a much bigger burden with closures, especially move closures (which are common when spawning threads or async tasks). For example, the following closure will consume the state handle, disallowing it from being used in later closures:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);
tokio::spawn(async move { /* code using `state` */ });
}

This scenario can be quite confusing for new users (see e.g. this 2014 talk at StrangeLoop where an experienced developer describes how confusing they found this to be). Many users settle on a workaround where they first clone the variable into a fresh local with a new name, such as:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);

let _state = state.clone();
tokio::spawn(async move { /*code using `_state` */ });

let _state = state.clone();
tokio::spawn(async move { /*code using `_state` */ });
}

Others adopt a slightly different pattern leveraging local variable shadowing:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);

tokio::spawn({
    let state = state.clone();
    async move { /*code using `state`*/ }
});
}

Whichever pattern users adopt, explicit clones of reference counted values leads to significant accidental complexity for many applications. As noted, cloning these values is both cheap at runtime and has zero semantic importance, since each clone is as good as the other.

Impact on new users and high-level domains

The impact of this kind of friction can be severe. While experienced users have learned the workaround and consider this to be a papercut, new users can find this kind of change bewildering and a total blocker. The impact is also particularly severe on projects attempting to use Rust in domains traditionally considered “high-level” (e.g., app/game/web development, data science, scientific computing). Rust’s strengths have made it a popular choice for building underlying frameworks and libraries that perform reliably and with high performance. However, thanks in large part to these kind of smaller, papercut issues, it is not a great choice for consumption of these libraries

Users in higher-level domains are accustomed to the ergonomics of Python or TypeScript, and hence ergonomic friction can make Rust a non-starter. Those users that stick with Rust long enough to learn the workarounds, however, often find significant value in its emphasis on reliability and long-term maintenance (not to mention performance). Small changes like avoiding explicit clones for reference-counted data can both help to make Rust more appealing in these domains and help Rust in other domains where it is already widespead.

The next 6 months

In 2024H2 we began work on an experimental implementation (not yet landed) and authored a corresponding RFC, which has received substantial feedback. In 2025H1 we will focus on driving the experimental branch to completion.

The “shiny future” we are working towards

This goal is scoped around reducing (or eliminating entirely) the need for explicit clones for reference-counted data. See the FAQ for other potential future work that we are not asking the teams to agree upon now.

Design axioms

We don’t have consensus around a full set of “design axioms” for this design, but we do have alignment around the following basic points:

  • Explicit ref-counting is a major ergonomic pain point impacting both high- and low-level, performance oriented code.
  • The worst ergonomic pain arises around closures that need to clone their upvars.
  • Some code will want the ability to precisely track reference count increments.
  • The design should allow user-defined types to “opt-in” to the lightweight cloning behavior.

Ownership and team asks

TaskOwner(s) or team(s)Notes
ImplementationSantiago Pastorino
ReviewsNiko Matsakis
Discussion and moral supportTeam lang
Author RFCJosh TriplettComplete

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None.

Model coherence in a-mir-formality

Metadata
Point of contactNiko Matsakis
StatusAccepted
Tracking issuerust-lang/rust-project-goals#122
Zulip channel[#t-types/formality][channel]
Teamstypes
Task ownersHelp wanted, Niko Matsakis
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/402470-t-types.2Fformality

Summary

We will model coherence (including negative impls) in a-mir-formality and compare its behavior against rustc. This will require extending a-mir-formality with the ability to run Rust tests.

Motivation

Over the next six months we will test a-mir-formality’s model of coherence against the new trait solver. To do this, we will extend it with the ability to run (small, simple) Rust files as tests and then build a tool to compare its behavior against rustc. This is working towards our ultimate goal for a-mir-formality being an “executable spec and playground” for the Rust type system. There are a number of things that need to happen for that goal to be truly realized in practice but the biggest of them is to be able to compare behavior against rustc.

The status quo

a-mir-formality has a sketch of a model of the Rust type system but tests must be written in a “Rust-like” dialect. This dialect is great for precisely controlling the input but makes it impossible to compare mir-formality’s behavior to rustc in any systematic way.

The next 6 months

Our goal for the next 6 months is to use a-mir-formality to document and explore Rust’s coherence system. Towards this end we will do two major initiatives:

  • Preparing an explainer that documents a-mir-formality’s rules and reading it with the types team;
    • this will also involve changing and improving those rules
  • Extending a-mir-formality with the ability to run (small, simple) unmodified Rust tests.

We will use the ability to run tests to compare the behavior of a-mir-formality against rustc, looking for discrepancies between the model and rustc’s actual behavior.

The “shiny future” we are working towards

We are working towards a future where

  • a-mir-formality is regularly tested against a subset of the compiler’s test suite;
  • new features that impact the type system are modeled in a-mir-formality prior to stabilization (and perhaps prior to RFC);
  • a-mir-formality is widely maintained by all members of the types team.

Design axioms

The primary “axiom” in choosing this goal is that there’s nothing like the magic of running code – in other words, the best way to make the shiny future come true is going to be making it easy to write tests and play with a-mir-formality. Right now the barrier to entry is still too high.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam types

Modeling and documenting coherence rules

TaskOwner(s) or team(s)Notes
Author explainer for coherence modelNiko Matsakis

Running Rust tests in a-mir-formality

TaskOwner(s) or team(s)Notes
MentorshipNiko Matsakis
ImplementationHelp wanted

Stretch goal: modeling Rust borrow checker

As a stretch goal, we can extend a-mir-formality to model the bodies of functions and try to model the Rust borrow checker.

TaskOwner(s) or team(s)Notes
MentorshipNiko Matsakis
ImplementationHelp wanted

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Improve state machine codegen

Metadata
Point of contactFolkert de Vries
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#258
Teamscompiler, lang
Task ownersbjorn3, Folkert de Vries

Summary

We want to improve rustc codegen, based on this initialive by the Trifecta Tech Foundation. The work focuses on improving state machine code generation, and finding (and hopefully fixing) cases where clang produces better code than rustc for roughly equivalent input.

Motivation

Matching C performance is crucial for rust adoption in performance-sensitive domains. Rust is doing well overall, but not good enough.

In compression, video decoding and other high-performance areas, nobody will use rust if it is even a couple percent slower: latency, power (i.e. battery) consumption and other factors are just more important than whatever advantages rust can bring. In particular, we’ve observed that C code translated to rust code, whether manually or mechanically, often performs a couple percent worse than the original C.

Given that we clang and rustc both use LLVM for code generation, there is no fundamental reason that rust should be slower.

The status quo

Our target audience is users of rust in performance-sensitive domains, where the rustc codegen hinders adoption of rust. Concretely we have most experience with, and knowledge of the bottlenecks in these projects:

In the compression libraries, we spotted a specific pattern (in rust terms, a loop containing a match) where rust is not able to generate good code today. We wrote RFC 3720 to tackle this problem.

In the case of rav1d, the performance is several percent worse than its C equivalent dav1d. The rav1d project used c2rust to translate the dav1d C source to rust. Hence the two code bases are basically equivalent, and we’d expect basically identical performance.

The rav1d developers were unable to track down the reason that rav1d performs worse than dav1d: their impression (that we have confirmed with various rustc developers) is that rustc+llvm is just slightly worse at generating code than clang+llvm, because llvm overfits to what clang gives it.

The next 6 months

Improve state machine codegen

The problem, and a range of possible solutions, is described in RFC 3720.

  • recognize the problematic pattern in zlib-rs in HIR, based on a fragile heuristic
  • ensure it is eventually turned into a goto to the actual target in MIR
  • evaluate how effective that is for other projects (e.g. rustc itself)
  • depending on how RFC 3720 evolves, implement the specific proposal (syntax, lints, error messages)

Finding performance bottlenecks

We want to build a tool that uses creduce and c2rust to find small examples where clang+llvm produces meaningfully better code than rust+llvm.

The output will be either issues with small rust snippets that have suboptimal codegen (compared to clang) or PRs fixing these problems.

The “shiny future” we are working towards

The shiny future is to improve rust codegen to encourage wider adoption of rust in performance-sensitive domains.

Ownership and team asks

Owner: Identify a specific person or small group of people if possible, else the group that will provide the owner. GitHub user names are commonly used to remove ambiguity.

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler
Lang-team experimentTeam lang
Refine RFC 3720Folkert de Vries
ImplementationFolkert de Vries, bjorn3
Standard reviewsTeam compiler

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet

Finish the libtest json output experiment

Metadata
Point of contactEd Page
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#255
Teamscargo, libs-api, testing-devex
Task ownersEd Page

Summary

Finish the libtest json experiment.

Motivation

libtest is the test harness used by default for tests in cargo projects. It provides the CLI that cargo calls into and enumerates and runs the tests discovered in that binary. It ships with rustup and has the same compatibility guarantees as the standard library.

Before 1.70, anyone could pass --format json despite it being unstable. When this was fixed to require nightly, this helped show how much people have come to rely on programmatic output.

Cargo could also benefit from programmatic test output to improve user interactions, including

Most of that involves shifting responsibilities from the test harness to the test runner which has the side effects of:

  • Allowing more powerful experiments with custom test runners (e.g. cargo nextest) as they’ll have more information to operate on
  • Lowering the barrier for custom test harnesses (like libtest-mimic) as UI responsibilities are shifted to the test runner (cargo test)

The status quo

The next 6 months

  1. Experiment with potential test harness features
  2. Experiment with test reporting moving to Cargo
  3. Putting forward a proposal for approval

The “shiny future” we are working towards

  • Reporting shifts from test harnesses to Cargo
  • We run test harnesses in parallel

Design axioms

  • Low complexity for third-party test harnesses so its feasible to implement them
  • Low compile-time overhead for third-party test harnesses so users are willing to take the compile-time hit to use them
  • Format can meet expected future needs
    • Expected is determined by looking at what other test harnesses can do (e.g. fixture, paramertized tests)
  • Format can evolve with unexpected needs
  • Cargo perform all reporting for tests and benches

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam testing-devex, cargo, libs-api
Prototype harnessEd Page
Prototype Cargo reporting supportEd Page
Write stabilization reportEd Page

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Declarative (macro_rules!) macro improvements

Metadata
Point of contactJosh Triplett
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#252
Teamslang, wg-macros
Task ownersEric Holk, Josh Triplett, Vincenzo Palazzo

Summary

In this project goal, I’ll propose and shepherd Rust language RFCs to make macro_rules! macros just as capable as proc macros, and to make such macros easier to write. I’ll also start prototyping extensions to the declarative macro system to make macros easier to write, with the aim of discussing and reaching consensus on those additional proposals during RustWeek (May 2025) at the latest. Finally, I’ll write a series of Inside Rust blog posts on these features, to encourage crate authors to try them and provide feedback, and to plan transitions within the ecosystem.

The scope of this goal is an arc of many related RFCs that tell a complete story, as well as the implementation of the first few steps.

Motivation

This project goal will make it possible, and straightforward, to write any type of macro using the declarative macro_rules! system. This will make many Rust projects build substantially faster, make macros simpler to write and understand, and reduce the dependency supply chain of most crates.

The status quo

There are currently several capabilities that you can only get with a proc macro: defining an attribute macro that you can invoke with #[mymacro], or defining a derive macro that you can invoke with #[derive(MyTrait)]. In addition, even without the requirement to do so (e.g. using workarounds such as the macro_rules_attribute crate), macro authors often reach for proc macros anyway, in order to write simpler procedural code rather than refactoring it into a declarative form.

Proc macros are complex to build, have to be built as a separate crate that needs to be kept in sync with your main crate, add a heavy dependency chain (syn/quote/proc-macro2) to projects using them, add to build time, and lack some features of declarative (macro_rules!) macros such as $crate.

As a result, proc macros contribute to the perceptions that Rust is complex, has large dependency supply chains, and takes a long time to build. Crate authors sometimes push back on (or feature-gate) capabilities that require proc macros if their crate doesn’t yet have a dependency on any, to avoid increasing their dependencies.

The next 6 months

Over the next 6 months, I’ll propose RFCs to improve the current state of declarative (macro_rules!) macros, and work with Eric Holk and Vincenzo Palazzo to get those RFCs implemented. Those RFCs together will enable:

  • Using macro_rules! to define attribute macros (#[attr])
  • Using macro_rules! to define derive macros (#[derive(Trait)])
  • Using macro_rules! to define unsafe attributes and unsafe derive macros.

I also have an RFC in progress (“macro fragment fields”) to allow macro_rules! macros to better leverage the Rust parser for complex constructs. Over the next 6 months, I’ll shepherd and refine that RFC, and design extensions of it to help parse additional constructs. (I expect this RFC to potentially require an additional design discussion before acceptance.) The goal will be to have enough capabilities to simplify many common cases of attribute macros and derive macros.

I’ll propose initial prototypes of additional macro metavariable expressions to make macro_rules! easier to write, such as by handling multiple cases or iterating without having to recurse. This provides one of the key simplification benefits of proc macros, with minimal added complexity in the language. I expect these to reach pre-RFC form and be suitable for discussion at RustWeek in May 2025, and hopefully reach consensus, but I do not expect them to be fully accepted or shipped in the next 6 months.

In addition, as part of this goal, I intend to work with Eric Holk and Vincenzo Palazzo to revitalize the wg-macros team, and evaluate potential policies and delegations from lang, in a similar spirit to wg-const-eval, t-types, and t-opsem.

Much as with the const eval system, I expect this to be a long incremental road, with regular improvements to capabilities and simplicity. Crate authors can adopt new features as they arise, and transition from proc macros to declarative macros once they observe sufficient parity to support such a switch.

The “shiny future” we are working towards

In the shiny future of Rust, the vast majority of crates don’t need to use proc macros. They can easily implement attributes, derives, and complex macros using exclusively the declarative macro_rules! system.

Furthermore, crate authors will not feel compelled to use proc macros for simplicity, and will not have to contort their procedural logic in order to express it as a declarative macro macro. Crate authors will be able to write macros using macro_rules! in either a recursive or semi-procedural style. For instance, this could include constructs like for and match.

I expect that all of these will be available to macros written in any edition, though I also anticipate the possibility of syntax improvements unlocked by future editions or within future macro constructs. For instance, currently Rust macros do not reserve syntax like $keyword (e.g. $for). Existing editions could require the ${...} macro metavariable syntax to introduce new constructs. Rust 2027 could reserve $keyword, and new syntax like macro could reserve such syntax in all editions.

Design axioms

  • Incremental improvements are often preferable to a ground-up rewrite. The ecosystem can adopt incremental improvements incrementally, and give feedback that inspires further incremental improvements.
  • There should never be a capability that requires using a proc macro.
  • The most obvious and simplest way to write a macro should handle all cases a user might expect to be able to write. Where possible, macros should automatically support new syntax variations of existing constructs, without requiring an update.
  • Macros should not have to recreate the Rust parser (or depend on crates that do so). Macros should be able to reuse the compiler’s parser. Macros shouldn’t have to parse an entire construct in order to extract one component of it.
  • Transforming iteration or matching into recursion is generally possible, but can sometimes obfuscate logic.

Ownership and team asks

Owner / Responsible Reporting Party: Josh Triplett

TaskOwner(s) or team(s)Notes
Propose discussion session at RustWeekJosh Triplett
Policy decisionTeam lang wg-macrosDiscussed with Eric Holk and Vincenzo Palazzo; lang would decide whether to delegate specific matters to wg-macros

macro_rules! attributes

TaskOwner(s) or team(s)Notes
Author/revise/iterate RFCsJosh Triplett
RFC decisionTeam lang
Implementation of RFCEric Holk, Vincenzo Palazzo
Iterate on design as neededJosh Triplett
Inside Rust blog post on attribute macrosJosh Triplett
Process feedback from crate authorsJosh Triplett

macro_rules! derives

TaskOwner(s) or team(s)Notes
Author/revise/iterate RFCsJosh Triplett
RFC decisionTeam lang
Implementation of RFCEric Holk, Vincenzo Palazzo
Iterate on design as neededJosh Triplett
Inside Rust blog post on derive macrosJosh Triplett
Process feedback from crate authorsJosh Triplett

Design and iteration for macro fragment fields

TaskOwner(s) or team(s)Notes
Author initial RFCJosh Triplett
Design meetingTeam lang
RFC decisionTeam lang
Implementation of RFCEric Holk, Vincenzo Palazzo
Iterate on design as neededJosh Triplett
Inside Rust blog post on additional capabilitiesJosh Triplett
Process feedback from crate authorsJosh Triplett
Support lang experiments for fragment fieldsJosh Triplett
Author small RFCs for further fragment fieldsJosh Triplett

Design for macro metavariable constructs

TaskOwner(s) or team(s)Notes
Design research and discussionsJosh Triplett
Discussion and moral supportTeam lang, wg-macros
Author initial RFCJosh Triplett

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What about “macros 2.0”

Whenever anyone proposes a non-trivial extension to macros, the question always arises of how it interacts with “macros 2.0”, or whether it should wait for “macros 2.0”.

“Macros 2.0” has come to refer to a few different things, ambiguously:

  • Potential future extensions to declarative macros to improve hygiene/namespace handling.
  • An experimental marco system using the keyword macro that partially implements hygiene improvements and experimental alternate syntax, which doesn’t have a champion or a path to stabilization, and hasn’t seen active development in a long time.
  • A catch-all for hypothetical future macro improvements, with unbounded potential for scope creep.

As a result, the possibility of “macros 2.0” has contributed substantially to “stop energy” around improvements to macros.

This project goal takes the position that “macros 2.0” is sufficiently nebulous and unfinished that it should not block making improvements to the macro system. Improvements to macro hygiene should occur incrementally, and should not block other improvements.

Could we support proc macros without a separate crate, instead?

According to reports from compiler experts, this would be theoretically possible but incredibly difficult, and is unlikely to happen any time soon. We shouldn’t block on it.

In addition, this would not solve the problem of requiring proc macros to recreate the Rust parser (or depend on such a reimplementation).

What about a “comptime” system?

This would likewise be possible in the future, but we shouldn’t block on it. And as above, this would not solve the problem of requiring such a system to recreate the Rust parser. We would still need a design for allowing such comptime functions to walk the Rust AST in a forward-compatible way.

Metrics Initiative

Metadata
Point of contactJane Lusby
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#260
Teamscompiler, infra
Task ownersHelp Wanted, Esteban Kuber, Jane Lusby

Summary

Build out the support for metrics within the rust compiler and starting with a Proof of concept dashboard for viewing unstable feature usage statistics over time.

Motivation

We’re envisioning three use cases for the Metrics Initiative:

  1. Supporting feature development, e.g. answering specific questions such as when the old and new trait solvers diverge, showing unstable feature usage trends, or helping identify and resolve bugs.
  2. Guiding improvements to User Experience, e.g. knowing which compiler errors are causing the most confusion or are hit the most frequently, focusing on improving those first, and verifying that the improvements help.
  3. Improving perf feedback loops and insight, e.g. helping identify pathological edge cases, similar to work Nicholas Nethercote has done manually in the past

We’re focusing initially on the first use case since we see that as the most likely to have a significant impact.

The status quo

Currently the Rust compiler has the capability to store to disk a backtrace and additional runtime information whenever an ICE occurs. This is only enabled on nightly due to concerns around where this file is stored, and how the output includes the fully qualified path of the file, which normally includes the username for the user that executed rustc.

Additionally, our users can use Cargo’s --timings flag and rustc’s -Z self-profile to generate reports on where compile times are going, but these are explicit opt-in actions, that produce output meant for direct human consumption, not for tool analysis.

For the uses of the perf dashboard, internal compiler aggregates can be collected, but lack granularity for complex analysis. These are currently only used to detect changes in behavior between two rustc builds.

All together these tools give us the ability to gather information about the inner workings of the compiler on a case by case basis, but any attempt to piece together trends within this information is often left as a manual process if not left undone entirely. This often leaves teams to guess at how people are using the language or to rely on proxies for that information.

The next 6 months

Sketch out the specific things you are trying to achieve in this goal period. This should be short and high-level – we don’t want to see the design!

  • Initial prototypes and proof of concept impls
    • initial metrics dumping in compiler e.g. unstable feature usage info
    • backend to store metrics
    • enable metrics dumping on existing project infra for open source crates (e.g. docs.rs or crater) and send metrics to backend
    • proof of concept dashboard for viewing metrics

The “shiny future” we are working towards

We’d like to get to the point where lang and libs can pull up a simple dashboard to see exactly what features exist, what their status is, and what their usage over time looks like. Beyond that, we want to get to the point where other contributors and teams can leverage the metrics to answer their own questions while we continue to build up the supporting infrastructure. The metrics should make it possible to track how often certain ICEs are encountered or if certain code paths are hit or any other question about real world usage of the compiler that our contributors and maintainers may have.

Design axioms

  • Trust: Do not violate the trust of our users
    • NO TELEMETRY, NO NETWORK CONNECTIONS
    • Emit metrics locally
    • User information should never leave their machine in an automated manner; sharing their metrics should always be opt-in, clear, and manual.
    • All of this information would only be stored on disk, with some minimal retention policy to avoid wasteful use of users’ hard drives
  • Feedback: improving feedback loops to assist with iterative improvement within the project
    • answer questions from real production environments in a privacy-preserving way
    • improve legibility of rare or intermittent issues
    • earlier warnings for ICEs and other major issues on nightly, improving the likelihood that we’d catch them before they hit stable.
      • https://blog.rust-lang.org/2021/05/10/Rust-1.52.1.html
  • Performance impact
    • leave no trace (minimize performance impact, particularly for default-enabled metrics)
  • Extensible:
    • it should be easy to add new metrics as needed
    • Only add metrics as a way to answer a specific question in mind, with an explicitly documented rationale
    • machine readable, it should be easy to leverage metrics for analysis with other tools
  • User experience:
    • improving user experience of reporting issues to the project
    • improving the user experience of using the compiler, measuring the impact of changes to user experience

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler, infra
ImplementationJane Lusby
backend for storing metricsEsteban Kuber
integration with docs.rs or crates.io to gather metrics from open source rust projectsJane Lusby
proof of concept dashboard visualizing unstable feature usage dataHelp Wanted
Standard reviewsTeam compiler

Frequently asked questions

“Stabilizable” prototype for expanded const generics

Metadata
Point of contactBoxy
StatusAccepted
Tracking issuerust-lang/rust-project-goals#100
Zulip channel[#project-const-generics][channel]
Teamslang, types
Task ownersBoxy, Noah Lev Michael Goulet, Michael Goulet
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/260443-project-const-generics/

Summary

Experiment with a new min_generic_const_args implementation to address challenges found with the existing approach to supporting generic parameters in const generic arguments.

Motivation

min_const_generics was stabilized with the restriction that const-generic arguments may not use generic parameters other than a bare const parameter, e.g. Foo<N> is legal but not Foo<{ T::ASSOC }>. This restriction is lifted under feature(generic_const_exprs) however its design is fundamentally flawed and introduces significant complexity to the compiler. A ground up rewrite of the feature with a significantly limited scope (e.g. min_generic_const_args) would give a viable path to stabilization and result in large cleanups to the compiler.

The status quo

A large amount of rust users run into the min_const_generics limitation that it is not legal to use generic parameters with const generics. It is generally a bad user experience to hit a wall where a feature is unfinished, and this limitation also prevents patterns that are highly desirable. We have always intended to lift this restriction since stabilizing min_const_generics but we did not know how.

It is possible to use generic parameters with const generics by using feature(generic_const_exprs). Unfortunately this feature has a number of fundamental issues that are hard to solve and as a result is very broken. It being so broken results in two main issues:

  • When users hit a wall with min_const_generics they cannot reach for the generic_const_exprs feature because it is either broken or has no path to stabilization.
  • In the compiler, to work around the fundamental issues with generic_const_exprs, we have a number of hacks which negatively affect the quality of the codebase and the general experience of contributing to the type system.

The next six months

We have a design for min_generic_const_args in mind but would like to validate it through implementation as const generics has a history of unforeseen issues showing up during implementation. Therefore we will pursue a prototype implementation in 2025. As a stretch goal, we will attempt to review the design with the lang team in the form of a design meeting or RFC.

In the past 6 months preliminary refactors were made to allow actually implementing the core of the design, this took significantly longer than expected which highlights the importance of actually implementing the design to see if it works.

The “shiny future” we are working towards

The larger plan with const generics (but not this project-goal) is to bring feature-parity with type generics for const generics:

  • Arbitrary types can be used in const generics instead of just: integers, floats, bool and char.
    • implemented under feature(adt_const_params) and is relatively close to stabilization
  • Generic parameters are allowed to be used in const generic arguments (e.g. Foo<{ <T as Trait>::ASSOC_CONST }>).
  • Users can specify _ as the argument to a const generic, allowing inferring the value just like with types.
    • implemented under feature(generic_arg_infer) and is relatively close to stabilization
  • Associated const items can introduce generic parameters to bring feature parity with type aliases
    • implemented under feature(generic_const_items), needs a bit of work to finish it. Becomes significantly more important after implementing min_generic_const_args
  • Introduce associated const equality bounds, e.g. T: Trait<ASSOC = N> to bring feature parity with associated types
    • implemented under feature(associated_const_equality), blocked on allowing generic parameters in const generic arguments

Allowing generic parameters to be used in const generic arguments is the only part of const generics that requires significant amounts of work while also having significant benefit. Everything else is already relatively close to the point of stabilization. I chose to specify this goal to be for implementing min_generic_const_args over “stabilize the easy stuff” as I would like to know whether the implementation of min_generic_const_args will surface constraints on the other features that may not be possible to easily fix in a backwards compatible manner. Regardless I expect these features will still progress while min_generic_const_args is being implemented.

Design axioms

  • Do not block future extensions to const generics
  • It should not feel worse to write type system logic with const generics compared to type generics
  • Avoid post-monomorphization errors
  • The “minimal” subset should not feel arbitrary

Ownership and team asks

Owner: Boxy, project-const-generics lead, T-types member

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams.

  • Subgoal:
    • Describe the work to be done and use to mark “subitems”.
  • Owner(s) or team(s):
    • List the owner for this item (who will do the work) or Help wanted if an owner is needed.
    • If the item is a “team ask” (i.e., approve an RFC), put Team and the team name(s).
  • Status:
    • List Help wanted if there is an owner but they need support, for example funding.
    • Other needs (e.g., complete, in FCP, etc) are also fine.
TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang, types
Implementation and mentoringBoxy
ImplementationNoah Lev Michael Goulet
ReviewerMichael Goulet

Outputs and milestones

Outputs

  • A sound, fully implemented feature(min_generic_const_args) available on nightly
  • All issues with generic_const_exprs’s design have been comprehensively documented (stretch goal)
  • RFC for min_generic_const_args’s design (stretch goal)

Milestones

  • Prerequisite refactorings for min_generic_const_args have taken place
  • Initial implementation of min_generic_const_args lands and is useable on nightly
  • All known issues are resolved with min_generic_const_args
  • Document detailing generic_const_exprs issues
  • RFC is written and filed for min_generic_const_args

Frequently asked questions

Do you expect min_generic_const_args to be stabilized by the end?

No. The feature should be fully implemented such that it does not need any more work to make it ready for stabilization, however I do not intend to actually set the goal of stabilizing it as it may wind up blocked on the new trait solver being stable first.

Next-generation trait solver

Metadata
Point of contactlcnr
StatusAccepted
Tracking issuerust-lang/rust-project-goals#113
Zulip channel[#t-types/trait-system-refactor][channel]
Teamstypes
Task ownersMichael Goulet, lcnr
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/364551-t-types.2Ftrait-system-refactor

Summary

Continue work towards the stabilization of -Znext-solver=globally, collecting and resolving remaining blockers. Extend its use in lints and rustdoc.

Motivation

The next-generation trait solver is intended to fully replace the existing type system components responsible for proving trait bounds, normalizing associated types, and much more. This should fix many long-standing (soundness) bugs, enable future type system improvements, and improve compile-times. It’s tracking issue is #107374(https://github.com/rust-lang/rust/issues/107374).

The status quo

There are multiple type system unsoundnesses blocked on the next-generation trait solver: project board. Desirable features such as coinductive trait semantics and perfect derive, where-bounds on binders, and better handling of higher-ranked bounds and types are also stalled due to shortcomings of the existing implementation.

Fixing these issues in the existing implementation is prohibitively difficult as the required changes are interconnected and require major changes to the underlying structure of the trait solver. The Types Team therefore decided to rewrite the trait solver in-tree, and has been working on it since EOY 2022.

The next six months

  • resolve remaining issues affecting our compile-time benchmarks
    • fix the failing tests by ‘properly’ resolving the underlying issues
      • wg-grammar
      • projection-caching
      • nalgebra-0.33.0
    • improve performance
      • avoid exponential performance hits in all benchmarks
      • get most benchmarks to be neutral or improvements
  • go through the most popular crates on crates.io and fix any encountered issues
  • move additional lints and rustdoc to use the new solver by default
  • publicly ask for testing of -Znext-solver=globally once that’s useful

The “shiny future” we are working towards

  • we are able to remove the existing trait solver implementation and significantly cleanup the type system in general, e.g. removing most normalize in the caller by handling unnormalized types in the trait system
  • all remaining type system unsoundnesses are fixed
  • many future type system improvements are unblocked and get implemented
  • the type system is more performant, resulting in better compile times

Design axioms

In order of importance, the next-generation trait solver should be:

  • sound: the new trait solver is sound and its design enables us to fix all known type system unsoundnesses
  • backwards-compatible: the breakage caused by the switch to the new solver should be minimal
  • maintainable: the implementation is maintainable, extensible, and approachable to new contributors
  • performant: the implementation is efficient, improving compile-times

Ownership and team asks

Owner: lcnr

Add’l implementation work: Michael Goulet

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam types
Implementationlcnr, Michael Goulet
Standard reviewsTeam types
FCP decision(s)Team typesfor necessary refactorings

Support needed from the project

  • Types team
    • review design decisions
    • provide technical feedback and suggestion

Outputs and milestones

See next few steps :3

Outputs

Milestones

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Null and enum-discriminant runtime checks in debug builds

Metadata
Point of contactBastian Kersting
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#262
Teamscompiler, lang, opsem
Task ownersBastian Kersting, @vabr-g

Summary

Add runtime checks to rustc that check for null pointers on pointer access and invalid enum discriminants. Similar to integer overflow and pointer alignment checks, this will only be enabled in debug builds.

Motivation

While safe Rust prevents access to null references, unsafe Rust allows you to access null pointers and create null references. It hands over responsibility to the programmer to assure validity of the underlying memory. Especially when interacting with values that cross the language boundary (FFI, e.g. passing a C++ created pointer to Rust), the reasoning about such values is not always straightforward.

At the same time, undefined behavior (UB) is triggered quickly when interacting with invalid pointers. E.g. just the existence of a null reference is UB, it doesn’t even have to be dereferenced.

Similar goes for enums. An enum must have a valid discriminant, and all fields of the variant indicated by that discriminant must be valid at their respective type (source). Again, FFI could potentially pass an invalid enum value to Rust and thus cause undefined behavior.

In general, for unsafe code, the responsibility of ensuring the various invariants of the Rust compiler are with the programmer. They have to make sure the value is not accidentally null, misaligned, violates Rust’s pointer aliasing rules or any other invariant. The access happens inside an unsafe block.

The status quo

While Miri exists and does a great job at catching various types of UB in unsafe Rust code, it has the downside of only working on pure Rust code. Extern functions can not be called and a mixed language binary is unable to be executed in Miri.

Kani, which verifies unsafe Rust via model checking has similar limitations.

The next 6 months

Within the next half a year, the plan is to start with null and enum discriminant checks to verify the code is upholding these invariants. Since these checks obviously pose a runtime overhead, we only insert them (optionally?) in debug builds. This is similar to the integer overflow and alignment checks that trigger a panic when observing an overflow and terminate the program.

The “shiny future” we are working towards

Similar to how UBSan exists in Clang, we would like to see an option to detect undefined behavior at runtime. As mentioned above, this is critical for cross-language interoperability and can help to catch UB before it reaches production.

The extension of these checks can be done step-by-step, keeping in mind the runtime overhead. Eventually we would like to check (sanitize) most items listed as UB in Rust.

Particularly as next steps we would like to check for UB when:

  • Calling a function with the wrong call ABI or unwinding from a function with the wrong unwind ABI.
  • Performing a place projection that violates the requirements of in-bounds pointer arithmetic.
  • Eventually check the Rust pointer aliasing model (stacked borrows check).

Ownership and team asks

Owner: Bastian Kersting

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam, lang, opsem
ImplementationBastian Kersting, @vabr-g
Standard reviewsTeam compiler, opsemBen Kimock

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Implement Open API Namespace Support

Metadata
Point of contactEd Page
StatusAccepted
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#256
Teamscargo, compiler
Task ownersb-naber, Ed Page

Summary

Navigate the cross-team design work to get RFC 3243 implemented.

Motivation

RFC 3243 proposed opening up namespaces in Rust to extension, managed by the package name with crates-io putting access control on who can publish to a crate’s API namespace. This covers multiple teams and needs a lot of coordination to balance the needs of each team as shown on the rustc tracking issue.

The status quo

Cargo support is partially implemented. No compiler support. There is a crates-io prototype for a previous iteration of RFC 3243 but that code base has likely diverged a lot since then.

The next 6 months

Implement at least Cargo and compiler support for this to be experimented with and allow crates-io work.

The “shiny future” we are working towards

Design axioms

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler
Compiler implementationb-naber
Work through lingering cargo issuesEd Page, b-naber

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Optimizing Clippy & linting

(a.k.a The Clippy Performance Project)

Metadata
Point of contactAlejandra González
StatusAccepted
Tracking issuerust-lang/rust-project-goals#114
Zulip channelN/A
Teamsclippy
Task ownersAlex Macleod, Alejandra González

Summary

This is the formalization and documentation of the Clippy Performance Project, a project first talked about on Zulip, July 2023. As the project consists of several points and is ever-changing, this document also has a dynamic structure and the team can add points.

In short, this is an effort to optimize Clippy, and Rust’s linting infrastructure with a point of view of making Clippy faster (both on CI/CD pipelines, and on devs’ machines)

Motivation

Clippy can take up to 2.5 times the time that a normal cargo check takes, and it doesn’t need to be! Taking so long is expensive both in development time, and in real money.

The status quo

Based on some [informal][poll-urlo] [feedback][poll-reddit] [polls][poll-mastodon], it’s clear that Clippy is used in lots of different contexts. Both in developer’s IDEs and outside them.

The usage for IDEs is not as smooth as one may desire or expect when comparing to prior art like [Prettier][prettier], [Ruff][ruff], or other tools in the Rust ecosystem rustfmt and Rust-analyzer.

The other big use-case is as a test before committing or on CI. Optimizing Clippy for performance would fold the cost of these tests.

On GitHub Actions, this excessive time can equal the cost of running cargo check on a Linux x64 32-cores machine, instead of a Linux x64 2-cores machine. A 3.3x cost increase.

The next 6 months

In order to achieve a better performance we want to:

  • Have benchmarking software ready to run on the server.
  • Optimize the collection of Minimum Safe Rust Version (MSRVs)
  • Migrate applicable lints to use incremental compilation

Apart from these 3 clear goals, any open issue, open PR or merged PRs with the label performance-project are a great benefit.

The “shiny future” we are working towards

The possible outcome would be a system that can be run on-save without being a hassle to the developer, and that has the minimum possible overhead over cargo check (which, would also be optimized as a side of a lot of a subset of the optimizations).

A developer shouldn’t have to get a high-end machine to run a compiler swiftly; and a server should not spend more valuable seconds on linting than strictly necessary.

Ownership and team asks

Owner: Alejandra González

TaskOwner(s) or team(s)Notes
ImplementationAlejandra González, Alex Macleod
Standard reviewsTeam clippy
[pr125116]: https://github.com/rust-lang/rust/pull/125116
[poll-urlo]: https://users.rust-lang.org/t/feedback-poll-where-and-how-do-you-use-clippy/114047?u=blyxyas
[poll-reddit]: https://www.reddit.com/r/rust/comments/1dxu43p/feedback_poll_where_how_do_you_use_clippy/
[poll-mastodon]: https://tech.lgbt/Alejandra González/112747808297589676
[prettier]: https://github.com/prettier/prettier
[ruff]: https://github.com/astral-sh/ruff

Promoting Parallel Front End

Metadata
Point of contactSparrow Li
StatusAccepted
Tracking issuerust-lang/rust-project-goals#121
Zulip channel[#t-compiler/wg-parallel-rustc][channel]
Teamscompiler
Task ownersSparrow Li
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/187679-t-compiler.2Fwg-parallel-rustc/

Summary

Continue to parallelize front-end stabilization and performance improvements, continuing from the 2024h2 goal.

Motivation

There are still some occasional deadlock issues, and in environments with high thread counts (>16) performance may be reduced due to data races.

The status quo

Many current issues reflect ICE or deadlock problems that occur during the use of parallel front end. We need to resolve these issues to enhance its robustness. We also need theoretical algorithms to detect potential deadlocks in query systems.

The current parallel front end still has room for further improvement in compilation performance, such as parallelization of HIR lowering and macro expansion, and reduction of data contention under more threads (>= 16).

We can use parallel front end in bootstrap to alleviate the problem of slow build of the whole project.

Cargo does not provide an option to enable the use of parallel front end, so it can only be enabled by passing rustc options manually.

The next 6 months

  • Solve reproducible deadlock issues via tests.
  • Enable parallel frontends in bootstrap.
  • Continue to improve parallel compilation performance, with the average speed increase from 20% to 25% under 8 cores and 8 threads.
  • Communicate with Cargo team on the solution and plan to support parallel front end.

The “shiny future” we are working towards

We need a detection algorithm to theoretically prove that the current query system and query execution process do not bring potential deadlock problems.

The existing rayon library implementation is difficult to fundamentally eliminate the deadlock problem, so we may need a better scheduling design to eliminate deadlock without affecting performance.

The current compilation process with GlobalContext as the core of data storage is not very friendly to parallel front end. Maybe try to reduce the granularity (such as modules) to reduce data competition under more threads and improve performance.

Design axioms

The parallel front end should be:

  • safe: Ensure the safe and correct execution of the compilation process
  • consistent: The compilation result should be consistent with that in single thread
  • maintainable: The implementation should be easy to maintain and extend, and not cause confusion to developers who are not familiar with it.

Ownership and team asks

Owner: Sparrow Li and Parallel Rustc WG own this goal

TaskOwner(s) or team(s)Notes
ImplementationSparrow Li
Author testsSparrow Li
Discussion and moral supportTeam compiler

Frequently asked questions

rustc-perf improvements

Metadata
Point of contactDavid Wood
StatusAccepted
Zulip channel#project-goals/2025h1/rustc-perf-improvements
Tracking issuerust-lang/rust-project-goals#275
Teamscompiler, infra
Task ownersJames, Jakub Beránek, David Wood

Arm’s Rust team is David Wood, Adam Gemmell, Jacob Bramley, Jamie Cunliffe and James. This goal will be primarily worked on by James, but David Wood can always be contacted for updates.

Summary

Add support to rustc-perf for distributed benchmarking across multiple platforms and configuration.

Motivation

Improving the performance of the Rust compiler is a long-standing objective of the Rust project and compiler team, which has led to the development of the project’s performance tracking infrastructure. While the performance tracking infrastructure has seen many improvements in recent years, it cannot scale to support multiple benchmarking machines simultaneously.

There are increasingly demands on the performance infrastructure which require a more scalable benchmarking infrastructure - benchmarking the parallel compiler with different thread counts, different codegen backends, or different architectures.

The status quo

rustc-perf does not currently support scheduling and accepting benchmarks from multiple machines, requiring a non-trivial rearchitecting to do so. None of our policies around performance triage and handling regressions currently consider what to do in case of conflicting benchmarking results.

The next 6 months

rustc-perf’s maintainers have written a rough draft of the work required to support multiple collectors which will form the basis of the work completed during this goal. After aligning on a implementation plan with the upstream maintainers of rustc-perf and ensuring that the implementation can proceed while placing as little burden on the infra team as possible, the work will largely consist of:

  1. Establish a parallel testing infrastructure to avoid any disruption to the live rustc-perf service
  2. Plan and implement necessary refactorings to the rustc-perf infrastructure enabling distributed benchmarking
  3. Writing tests for the new distributed rustc-perf infrastructure, enabling future development to avoid breakage
  4. Make changes to the database schema to support receiving results from multiple collectors (both being able to distinguish between results from each configuration and be have multiple writes simultaneously)
  5. Update queries and statistics used in summarising collected performance data and identifying outliers
  6. Update perf.rust-lang.org to be able to display performance data from multiple collectors and make appropriate comparisons (within a configuration, not between configurations)

As this work nears completion, this goal’s owners will collaborate with the compiler team and its performance working group to extend and update the compiler team’s triage and regression handling policies. It is important that there are clear guidelines and procedures for circumstances where a benchmark improves on one platform and regresses on another, or how to weigh benchmark results from unstable features or configurations (e.g. -Zthreads=2) vs the primary benchmarking platforms and configurations.

The “shiny future” we are working towards

Following the completion of this goal, it is anticipated that new platforms and configurations will be added to rustc-perf, but this is unlikely to warrant further goals.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam infra
Improve rustc-perf implementation workJames, Jakub Beránek
Standard reviewsTeam infra
Deploy to productionTeam infrarustc-perf improvements, testing infrastructure
Draft performance regression policyDavid Wood
Policy decisionTeam compilerUpdate performance regression policy
Inside Rust blog post announcing improvementsDavid Wood

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None yet.

Stabilize public/private dependencies

Metadata
Point of contactEd Page
StatusAccepted
Contingent onContributor
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#272
Teamscargo, compiler
Task ownersHelp wanted, Ed Page

Summary

Find a MVP for stabilization and move it forward.

Motivation

This will allow users to tell Rustc and Cargo what dependencies are private

  • Help users catch ways they unexpectedly expose their implementation details
  • Help tooling better identify what all constitutes an API

The status quo

RFC #1977(https://github.com/rust-lang/rfcs/pull/1977) has been superseded by RFC #3516(https://github.com/rust-lang/rfcs/pull/3516) to reduce complexity on the Cargo side to help get this over the line. However, there is still a lot of complexity on the compiler side to get this right ( rust#3516, rust#119428, ), keeping this feature in limbo

The next 6 months

Work with compiler to identify a minimal subset of functionality for what the lint can do and close out the remaining stabilization tasks.

The “shiny future” we are working towards

Design axioms

  • False negatives are likely better than false positives

Ownership and team asks

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo, compiler
Work through #3516, #119428Help wanted
Finish any remaining tasksHelp wanted
MentoringEd Page
Stabilization reportHelp wanted

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Extend pubgrub to match cargo’s dependency resolution

Metadata
Point of contactJacob Finkelman
StatusAccepted
Tracking issuerust-lang/rust-project-goals#110
Zulip channelN/A
Teamscargo
Task ownerseh2046

Summary

Implement a standalone library based on pubgrub that model’s cargo dependency resolution and bring it to a quality of code so that it can be maintained by the cargo team. This lays the groundwork for improved cargo error messages, extensions for hotly requested features (e.g., better MSRV support, CVE-aware resolution, etc), and support for a richer ecosystem of cargo extensions.

Motivation

Cargo’s dependency resolver is brittle and under-tested. Disentangling implementation details, performance optimizations, and user-facing functionality will require a rewrite. Making the resolver a standalone modular library will make it easier to test and maintain.

The status quo

Big changes are required in cargo’s resolver: there is lots of new functionality that will require changes to the resolver and the existing resolver’s error messages are terrible. Cargo’s dependency resolver solves the NP-Hard problem of taking a list of direct dependencies and an index of all available crates and returning an exact list of versions that should be built. This functionality is exposed in cargo’s CLI interface as generating/updating a lock file. Nonetheless, any change to the current resolver in situ is extremely treacherous. Because the problem is NP-Hard it is not easy to tell what code changes break load-bearing performance or correctness guarantees. It is difficult to abstract and separate the existing resolver from the code base, because the current resolver relies on concrete datatypes from other modules in cargo to determine if a set of versions have any of the many ways two crate versions can be incompatible.

The next six months

Develop a standalone library for doing dependency resolution with all the functionality already supported by cargo’s resolver. Prepare for experimental use of this library inside cargo.

The “shiny future” we are working towards

Eventually we should replace the existing entangled resolver in cargo with one based on separately maintained libraries. These libraries would provide simpler and isolated testing environments to ensure that correctness is maintained. Cargo plugins that want to control or understand what lock file cargo uses can interact with these libraries directly without interacting with the rest of cargo’s internals.

Design axioms

  • Correct: The new resolver must perform dependency resolution correctly, which generally means matching the behavior of the existing resolver, and switching to it must not break Rust projects.
  • Complete output: The output from the new resolver should be demonstrably correct. There should be enough information associated with the output to determine that it made the right decision.
  • Modular: There should be a stack of abstractions, each one of which can be understood, tested, and improved on its own without requiring complete knowledge of the entire stack from the smallest implementation details to the largest overall use cases.
  • Fast: The resolver can be a slow part of people’s workflow. Overall performance must be a high priority and a focus.

Ownership and team asks

Owner: Jacob Finkelman will own and lead the effort.

I (Jacob Finkelman) will be working full time on this effort. I am a member of the Cargo Team and a maintainer of pubgrub-rs.

Integrating the new resolver into Cargo and reaching the shiny future will require extensive collaboration and review from the Cargo Team. The next milestones involve independent work polishing various projects for publication. Review support from the cargo team, identifying what about the code needs to be documented and improved will be invaluable. However, there is plenty of work clearly available to do. If team members are not available progress will continue.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam cargo
Implementation work on pubgrub libraryeh2046

Outputs

Standalone crates for independent components of cargo’s resolver. We have already developed https://github.com/pubgrub-rs/pubgrub for solving the core of dependency resolution and https://github.com/pubgrub-rs/semver-pubgrub for doing mathematical set operations on Semver requirements. The shiny future will involve several more crates, although their exact borders have not yet been determined. Eventually we will also be delivering a -Z pubgrub for testing the new resolver in cargo itself.

Milestones

For all crate versions on crates.io the performance is acceptable.

There are some crates where pubgrub takes a long time to do resolution, and more where pubgrub takes longer than cargo’s existing resolver. Investigate each of these cases and figure out if performance can be improved either by improvements to the underlying pubgrub algorithm or the way the problem is presented to pubgrub.

Make a new release of pubgrub with the features developed for the prototype.

The prototype testing tool has relied on pubgrub as a git dependency. This has allowed rapid feedback on proposed changes. Before cargo can depend on PubGrub these changes need to be polished and documented to a quality appropriate for publication on crates.io.

Determine what portion of the prototype can be maintained as a standalone library.

One of the goals of this effort is to have large portions of resolution be maintained as separate packages, allowing for their use and testing without depending on all of cargo. Figure out which parts of the prototype can be separate packages and which parts should be part of cargo.

Get cargo team review of code developed in the prototype.

Much of the prototypes code has only ever been understood by me. Before it becomes a critical dependency of cargo or part of cargo, it needs to be polished and documented so that other members the cargo team would be comfortable maintaining it.

Frequently asked questions

If the existing resolver defines correct behavior then how does a rewrite help?

Unless we find critical bugs with the existing resolver, the new resolver and cargo’s resolver should be 100% compatible. This means that any observable behavior from the existing resolver will need to be matched in the new resolver. The benefits of this work will come not from changes in behavior, but from a more flexible, reusable, testable, and maintainable code base. For example: the base pubgrub crate solves a simpler version of the dependency resolution problem. This allows for a more structured internal algorithm which enables complete error messages. It’s also general enough not only to be used in cargo but also in other package managers. We already have contributions from the maintainers of uv who are using the library in production.

Implement restrictions, prepare for stabilization

Metadata
Point of contactJacob Pratt
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#257
Teamscompiler, lang, lang-docs
Task ownersJacob Pratt

Summary

RFC 3323 will be implemented and feature-complete, with all syntax questions resolved. The features will be prepared for stabilization.

Motivation

The RFC for restrictions was accepted over two years ago, but the pull request implementing it has been stalled for a long time for a variety of reasons. Implementing the feature will permit testing, feedback, and stabilization.

The status quo

Sealed traits are a common pattern in Rust, but are not currently supported by the language itself. Instead, they are implemented using a combination of visibility modifiers and nested modules. Fields with restricted mutability are currently only possible with getters and setters, setting aside (ab)using Deref implementations.

More details are available in the RFC.

The next 6 months

The accepted restrictions RFC represents the end goal of this project goal. All unresolved questions should be discussed and resolved, with the two features (impl_restrictions and mut_restrictions) being ready for stabilization. Future possibilities are likely considered at a high level, but are not the focus of this project goal.

Ownership and team asks

Owner: Jacob Pratt

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
ImplementationJacob Prattold PR is plausibly workable
Standard reviewsTeam compiler
Author stabilization reportJacob Pratt
Author Reference PRJacob Pratt
Review/revise Reference PRTeam lang-docsJoel Marcey
Stabilization decisionTeam lang
Inside Rust blog post inviting feedbackJacob Prattfeedback on syntax if no team consensus

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Isn’t the syntax already decided?

While the RFC was accepted without this being an unresolved question (aside from a simpler syntax for common cases), I believe that an attribute-based syntax such as #[restrict(impl(crate))] may be, but is not necessarily, favorable to the syntax in the RFC. This is because it is backwards-compatible with all existing macros and prevents nontrivial additions to the width of code.

Stabilize tooling needed by Rust for Linux

Metadata
Short titleRust-for-Linux
Point of contactNiko Matsakis
StatusAccepted
FlagshipYes
Tracking issuerust-lang/rust-project-goals#116
Zulip channel[#rust-for-linux][channel]
Teamscargo, clippy, compiler, rustdoc
Task ownersHelp Wanted, Alice Ryhl, Niko Matsakis
[channel]: https://rust-lang.zulipchat.com/#narrow/channel/425075-rust-for-linux/

Summary

Continue working towards Rust for Linux on stable, turning focus to compiler and tooling.

Motivation

This goal continues our push to support the Linux kernel building on stable Rust. The focus in 2025H1 is shifting from language features, which were largely completed in 2024H2, towards compiler flags and tooling support. The Linux Kernel makes use of a number of unstable options in the compiler for target specific optimizations, code hardening, and sanitizer integration. It also requires a custom build of the standard library and has hacky integration with rustdoc to enable the use of doctests. We are looking to put all of these items onto a stable foundation.

The status quo

The Rust for Linux (RFL) project has been accepted into the Linux kernel in experimental status. The project’s goal, as described in the Kernel RFC introducing it, is to add support for authoring kernel components (modules, subsystems) using Rust. Rust would join C as the only two languages permitted in the Linux kernel. This is a very exciting milestone for Rust, but it’s also a big challenge.

Integrating Rust into the Linux kernel means that Rust must be able to interoperate with the kernel’s low-level C primitives for things like locking, linked lists, allocation, and so forth. This interop requires Rust to expose low-level capabilities that don’t currently have stable interfaces.

The Rust side of the kernel needs to support a range of compiler versions, just like the C side does. For instance, distributions wish to be able to build a range of kernel sources with the same compiler, rather than having to select a particular toolchain for a particular kernel version. Thus RFL is already declaring an MSRV. Because unstable features have no kind of reliability guarantee, this in turn means that it is a priority to remove the dependency on unstable features so that Linux can be built with future Rust compilers without major changes on the kernel side.

Longer term, having Rust in the Linux kernel is an opportunity to expose more C developers to the benefits of using Rust. But that exposure can go both ways. If Rust is constantly causing pain related to toolchain instability, or if Rust isn’t able to interact gracefully with the kernel’s data structures, kernel developers may have a bad first impression that causes them to write off Rust altogether. We wish to avoid that outcome. And besides, the Linux kernel is exactly the sort of low-level systems application we want Rust to be great for!

For deeper background, please refer to these materials:

What we have done so far

We began the push towards stable support for RFL in 2024H2 with a project goal focused on language features. Over the course of those six months we:

  • Stabilized the CoercePointee derive, supporting the kernel’s use of smart pointers to model intrusive linked lists.
  • Stabilized basic usage of asm_goto. Based on a survey of the kernel’s usage, we modified the existing design and also proposed two extensions.
  • Stabilized offset_of syntax applied to structs.
  • Added Rust-for-Linux to the Rust CI to avoid accidental breakage.
  • Stabilized support for pointers to static in constants.

The one feature which was not stabilized yet is arbitrary self types v2, which reached “feature complete” status in its implementation. Stabilization is expected in early 2025.

We also began work on tooling stabilization with an RFC proposing an approach to stabilizing ABI-modifying compiler flags.

The next six months

Over the next six months our goal is to stabilize the major bits of tooling used by the Rust for Linux project. Some of these work items are complex enough to be tracked independently as their own project goals, in which case they are linked.

  • implementing RFC #3716 to allow stabilizing ABI-modifying compiler flags to control code generation, sanitizer integration, and so forth
  • the ability to extract dependency info and to configure no-std without requiring it in the source file:
    • currently using -Zbinary_dep_depinfo=y and -Zcrate-attr
  • stable rustdoc features allowing the RFL project to extract and customize rustdoc tests (--extract-doctests);
  • clippy configuration (possibly .clippy.toml and CLIPPY_CONF_DIR);
  • a blessed way to rebuild std: RFL needs a way to rebuild the standard library using stable calls to rustc. Currently building the standard library with rustc is not supported. This is a precursor to what is commonly called -Zbuild-std; it is also a blocker to making full use of API-modifying compiler flags and similar features, since they can’t be used effectively unless the kernel is rebuilt.

In addition, as follow-up from 2024H2, we wish to complete arbitrary self types v2 stabilization.

The “shiny future” we are working towards

The ultimate target for this line of work is that Rust code in the Linux kernel builds on stable Rust with a Minimum Supported Rust Version (MSRV) tied to some external benchmark, such as Debian stable. This is the minimum requirement for Rust integration to proceed from an “experiment” so something that could become a permanent part of Linux.

Looking past the bare minimum, the next target would be making “quality of life” improvements that make it more ergonomic to write Rust code in the kernel (and similar codebases). One such example is the proposed experiment for field projections.

Design axioms

  • First, do no harm. If we want to make a good first impression on kernel developers, the minimum we can do is fit comfortably within their existing workflows so that people not using Rust don’t have to do extra work to support it. So long as Linux relies on unstable features, users will have to ensure they have the correct version of Rust installed, which means imposing labor on all Kernel developers.
  • Don’t let perfect be the enemy of good. The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of functionality that meets the kernel developers’ needs while leaving other aspects unstable.

Ownership and team asks

Here is a detailed list of the work to be done and who is expected to do it. This table includes the work to be done by owners and the work to be done by Rust teams (subject to approval by the team in an RFC/FCP).

  • The Team badge indicates a requirement where Team support is needed.
TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler rustdoc cargo
Overall program managementNiko Matsakis

ABI-modifying compiler flags

Goal: stabilizing various ABI-modifying flags such as -Zbranch-protection and friends.

TaskOwner(s) or team(s)Notes
Author RFCAlice Ryhl![Completed][]
RFC decisionTeam compilerRFC #3716, currently in PFCP
ImplementationHelp WantedFor each flag, need to move flags from -Z to -C etc
Standard reviewsTeam compiler
Stabilization decisionTeam compilerFor each of the relevant compiler flags

Extract dependency information, configure no-std externally

Goal: support extraction of dependency information (similar to -Zbinary_dep_depinfo=y today) and ability to write crates without explicit, per-crate ![no_std] (achieved via -Zcrate-attr today).

Right now there is no plan for how to approach this. This task needs an owner to pick it up, make a plan, and execute.

TaskOwner(s) or team(s)Notes
Author a planHelp Wanted
ImplementationHelp Wanted
Standard reviewsTeam compiler
Stabilization decisionTeam compiler

Rustdoc features to extract doc tests

Goal: stable rustdoc features sufficient to extract doc tests without hacky regular expressions

TaskOwner(s) or team(s)Notes
Author RFCHelp Wanted
RFC decisionTeam rustdoc
ImplementationHelp Wanted
Standard reviewsTeam rustdoc
Stabilization decisionTeam rustdoc

Clippy configuration

Goal: stabilized approach to customizing clippy (like .clippy.toml and CLIPPY_CONF_DIR today).

As discussed on Zulip, the relevant policy is already correct, but documentation is needed.

TaskOwner(s) or team(s)Notes
Author documentationHelp Wanted
Stabilization decisionTeam clippy

Blessed way to rebuild std

See build-std goal.

Frequently asked questions

What kind of compiler flags will Rust-for-Linux need?

Implementing RFC #3716, coupled with a blessed way to build std, will allow the full use of flags that modify the ABI. We will need to ultimately stabilize the full set of flags used by RFL, which include at least the following:

  • arm64: -Zbranch-protection, -Zfixed-x18, -Zuse-sync-unwind.
  • x86: -Zcf-protection, -Zfunction-return, -Zno-jump-tables, -Zpatchable-function-entry, retpoline (+retpoline-external-thunk,+retpoline-indirect-branches,+retpoline-indirect-calls), SLS (+harden-sls-ijmp,+harden-sls-ret).
  • x86 32-bit: -Zregparm=3, -Zreg-struct-return.
  • LoongArch: -Zdirect-access-external-data.
  • production sanitizer flags: -Zsanitizer=shadow-call-stack, -Zsanitizer=kcfi, -Zsanitizer-cfi-normalize-integer.

Stabilization decisions for each flag will be made independently. We will likely take a future goal to drive some percentage of them to stabilization once RFC #3716 is implemented.

Rust Vision Document

Metadata
Point of contactNiko Matsakis
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#269
Teamsleadership-council
Task ownersNiko Matsakis, vision team

Summary

Present a first draft of a “Rust Vision Doc” at the Rust All Hands in May.

The Rust Vision Doc will summarize the state of Rust adoption – where is Rust adding value? what works well? what doesn’t? – based on conversations with individual Rust users from different communities, major Rust projects, and companies large and small that are adopting Rust. It will use that raw data to make recommendations on what problems Rust should be attacking and what constraints we should be trying to meet. The document will not include specific features or recommendations, which ought to be legislated through RFCs.

Motivation

The goal is to author a longer term “vision doc” that identifies key opportunities for Rust over the next 3-5 years. The document will help us focus our energies and attack problems that move the needle for Rust.

Rust’s planning processes have a 6 month time window

Rust’s official planning processes are currently scoped at the 6 month horizon (project goals). Of course a number of longer term initiatives are in play, some quite long indeed, such as the long drive towards a better async experience or towards parallel compilation. This planning primarily lives in the heads of the maintainers doing the work. There is no coordinated effort to collect the experiences of Rust users in a larger way.

It’s time for us to think beyond “adoption”

Rust’s goal since the beginning has been to empower everyone to build reliable and efficient software. We wanted Rust to be a language that would enable more people to build more things more quickly than was possible before. And not just any things, but things that worked well, saved resources, and lasted a long time. This is why Rust prizes performance, reliability, productivity, and long-term maintenance.

Once the basic design of Rust had come into focus, it was clear that our primary goal was focusing on adoption. But now that Rust has established a foothold in the industry, adoption on its own is not clearly the right goal for us. Rust, like most any general purpose language, can be used for all kinds of things. What are the kinds of applications where Rust is already a great fit, and how could it get even better? And what are the kinds of applications where Rust could be a great fit, if we overcame some obstacles?

To know where to go, you have to know where you are

The biggest effort towards central planning was the authoring of the Async Vision Doc, which took place in 2021. The Async Vision Doc effort began by collecting status quo stories described the experiences of using async in a number of scenarios based on a cast of four characters1: Alan, Grace, Niklaus, and Barbara. These stories were “crowd sourced” over several months, during which time we held video chats and interviews.

Writing the “status quo” stories helped us to compensate for the curse of knowledge: the folks working on Async Rust tended to be experts in Async Rust, familiar with the the little tips and tricks that can get you out of a jam. The stories helped us to see the impact from little paper cuts that we had long since overlooked, while also identifying deeper challenges and blockers.

Gathering stories from both individuals and groups

Gathering stories from individuals can be done with the same techniques we used with the Async Vision Doc, like online meetings and soliciting PRs. We may also be able to coordinate with Rust conferences.

For the broader Rust vision doc, we would also like to proactively seek input from groups that we think would have useful context:

  • Rust trainers and consultants;
  • groups driving adoption at companies;
  • groups like the Rust Foundation.

Focus on opportunities and requirements instead of a specific “shiny future”

After the Status Quo story gathering, the Async Vision Doc attempted to author a shiny future. The intent was to align the community around a single vision but (in the opinion of the author, myself) it was not especially successful. There are several reasons for this. For one, the document was never RFC’d, which meant it did not truly represent a consensus. Second, it attempted to paint a more precise picture than was truly possible. The design of new features in complex domains like async is subject to a “fog of war effect”2: the immediate next steps can be relatively clear, and perhaps the end point is even somewhat understood, but the path between will have to figured out as you go. Trying to author a shiny future is inherently challenging.

For the Rust Vision Doc, we plan to take a different approach. Rather than authoring a shiny future, we will identify specific opportunities– places where we believe Rust could have a huge impact on the state of software development. For each of those, we’ll make recommendations about the kinds of problems that need to be solve for Rust to be truly successful in those domains. We will back up those recommendations with references to status quo stories and other data.

The next 6 months

Our goal for the next 6 months is to present a first draft of the vision doc at the Rust All Hands, planned for May 2025. We will use this opportunity to get feedback on the doc structure and recommendations and to begin work on the actual RFC, excepted to be accepted in 2025H2.

Here is the overall plan for 2025H1:

TaskNovDecJanFebMarAprMayJun
Form a team██████
Gather status quo stories██████░░░
Coalesce stories and personae░░░██████
Develop recommendations and goals░░░███
Review RFC Draft 1 at Rust All Hands██████
Publish a blog post with summarized feedback███

The plan actually begins now, in the goal construction phase. One of the tasks to be done is building up a small support team of researchers who will help with doing the interviews and authoring status quo stories and other parts of the document. As goal point of contact, nikomatsakis will select initial members. With the Async Vision Doc, our experience was that most Rust users are eager to share their experiences, but that authoring and upleveling that into a status quo story is challenging. It’s better to centralize that authorship into a small group of motivated people.

The plan to finalize the document is as follows:

  • We will be gathering and summarizing data for the first 3 months.
  • In early April we will begin authoring the first draft.
  • We will present the first draft for review at the Rust All hands and associated Rust Week conference.
  • We will publish a blog post with collected feedback.

Approval of the RFC indicates general alignment with the framing and prioritizes it describes. It will not commit any Rust team to any particular action.

The “shiny future” we are working towards

Assuming this vision doc is successful, we believe it should be refreshed on a regular basis. This would be a good completement to the Rust Project Goal system. Project Goals describe the next few steps. The Vision Doc helps to outline the destination.

We also expect that the Vision Doc template may be useful in other more narrow contexts, such as a revised version of the Async Vision Doc,a vision doc for Rust in UI, machine learning, etc.

Design axioms

  • Shared understanding of the status quo is key. The experience of the async vision doc was that documenting the status quo had huge value.
  • Describe the problem and requirements, not the solution. Attempting to design 3-5 years of features in 6 months is clearly impossible. We will focus on identifying areas where Rust can have a big impact and describing the kinds of things that are holding it back.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Select support team membersNiko Matsakis
MiscellaneousTeam leadership-councilCreate supporting subteam + Zulip stream
Gathering of status quo storiesvision team
Prepare draft of RFC to be presented at Rust all handsvision team

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Why are you creating a support team? Should it be a working group?

Oh geez I don’t know what to call anything anymore. I think this is a time-limited team created for the purpose of authoring this RFC and then disbanded. We can call that a working group, project group, whatever.

I do think that if this doc is successful there might be a role for a longer-term maintenance team, perhaps one that also helps to run the project goals effort. That’s a topic for another day.


  1. Any resemblance between these names and famous programming language pioneers is purely coincidental.

  2. Hat tip to Tyler Mandry for this name.

Research: How to achieve safety when linking separately compiled code

Metadata
Point of contactMara Bos
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#267
Teamscompiler, lang
Task ownersJana Dönszelmann, Mara Bos, Hexcat (= Mara Bos + Jana Dönszelmann), MSc student, Msc student, Research team (MSc student, etc.), professor

Summary

Research what “safety” and “unsafety” means when dealing with separately compiled code, like when loading dynamically linked libraries. Specifically, figure out how it’d be possible to provide any kind of safety when linking external code (such as loading a dynamic library or linking a separately compiled static library).

Motivation

Rust has a very clear definition of “safe” and “unsafe” and (usually) makes it easy to stay in the “safe” world. unsafe blocks usually only have to encapsulate very small blocks of which one can (and should) prove soundness manually.

When using #[no_mangle] and/or extern { … } to connect separately compiled code, however, any concept of safety pretty much disappears.

While it might be reasonable to make some assumptions about (standardized) symbols like strlen, the unsafe assumption that a symbol with the same name will refer to something of the expected signature is not something that one can prove at compile time, but is rather an (hopeful, perhaps reasonable) expectation of the contents of dynamic libraries available at runtime.

The end result is that for use cases like plugins, we have no option than just unsafely hoping for the best, accepting that we cannot perfectly guarantee that undefined behavior is impossible linking/loading a library/a plugin/some external code.

The status quo

Today, combining separately compiled code (from different Rust projects or different languages) is done through a combination of extern "…" fn, #[repr(…)], #[no_mangle], and extern {…}.

Specifically:

  1. extern "…" fn (which has a bit of a confusing name) is used to specify the calling convention or ABI of a function.

    The default one is the "Rust" ABI, which (purposely) has no stability guarantees. The "C" ABI is often used for its stability guarantees, but places restrictions on the possible signatures.

  2. #[repr(…)] is used to control memory layout.

    The default one is the Rust layout, which (purposely) has no stability guarantees. The C layout is often used for its stability guarantees, but places restrictions on the types.

  3. #[no_mangle] and extern {…} are used to control the symbols used for linking.

    #[no_mangle] is used for exporting an item under a known symbol, and extern { … } is used for importing an item with a known symbol.

There have often been requests for a “stable Rust abi” which usually refers to a calling convention and memory layout that is as unrestrictive as extern "Rust" fn and #[repr(Rust)], but as stable as extern "C" fn and #[repr(C)].

It seems unlikely that extern "Rust" fn and #[repr(Rust)] would ever come with stability guarantees, as allowing for changes when stability is not necessary has its benefits. It seems most likely that a “stable Rust ABI” will arrive in the form of a new ABI, by adding some kind of extern "Rust-stable-v1" (and repr) or similar (such as extern "crabi" fn and #[repr(crabi)] proposed here), or by slowly extending extern "C" fn and #[repr(C)] to support more types (like tuples and slices, etc.).

Such developments would lift restrictions on which types one can use in FFI, but just a stable calling convention and memory layout will do almost nothing for safety, as linking/loading a symbol (possibly at runtime) with a different signature (or ABI) than expected will still immediately lead to undefined behavior.

Research question and scope

This research project focuses entirely on point 3 above: symbols and linking.

The main research question is:

What is necessary for an alternative for #[no_mangle] and extern { … } to be safe, with a reasonable and usable definition of “safe”?

We believe this question can be answered independently of the specifics of a stable calling convention (point 1) and memory layout (point 2).

RFC3435 “#[export]” for dynamically linked crates proposes one possible way to provide safety in dynamic linking. The goal of the research is to explore the entire solution space and understand the requirements and limitations that would apply to any possible solution/alternative.

The next 6 months

  • Assemble a small research team (e.g. an MSc student, a professor, and a researcher/mentor).
  • Acquire funding.
  • Run this as an academic research project.
  • Publish intermediate results as a blog post.
  • (After ~9 months) Publish a thesis and possibly a paper that answers the research question.

The “shiny future” we are working towards

The future we’re working towards is one where (dynamically) linking separately compiled code (e.g. plugins, libraries, etc.) will feel like a first class Rust feature that is both safe and ergonomic.

Depending on the outcomes of the research, this can provide input and design requirements for future (stable) ABIs, and potentially pave the way for safe cross-language linking.

Design axioms

  • Any design is either fully safe, or makes it possible to encapsulate the unsafety in a way that allows one to prove soundness (to reasonable extend).
  • Any design allows for combining code compiled with different versions of the Rust compiler.
  • Any design is usable for statically linking separately (pre) compiled static libraries, dynamically linking/loading libraries, and dynamically loading plugins.
  • Designs require as little assumptions about the calling convention and memory layout. Ideally, the only requirement is that they are stable, which means that the design can be used with the existing extern "C" fn and #[repr(C)].

Ownership and team asks

Owner: Mara Bos and/or Jana Dönszelmann

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Coordination with universityJana DönszelmannDelft University of Technology
Acquire fundingHexcat (= Mara Bos + Jana Dönszelmann)
ResearchResearch team (MSc student, professor, etc.)
Mentoring and interfacing with Rust projectMara Bos, Jana Dönszelmann
Blog post (author, review)MSc student, Jana Dönszelmann, Mara Bos
Experimental implementationMsc student
Lang-team experimentTeam langNiko Matsakis
Standard reviewsTeam compiler
Thesis / PaperResearch team (MSc student, professor, etc.)

Frequently asked questions

Is there a university and professor interested in this?

Yes! We’ve discussed this with a professor at the Delft University at Technology, who is excited and already looking for interested students.

Evaluate approaches for seamless interop between C++ and Rust

Metadata
Point of contactTyler Mandry
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#253
Teamscompiler, lang, libs-api
Task ownersHelp wanted, Tyler Mandry

Summary

Seriously consider what it will take to enable Rust adoption in projects that must make use of large, rich C++ APIs. Map out the space of long-term solutions we are interested in. These solutions should enable interop between Rust and other languages in the future.

Motivation

Rust has seen broad and growing adoption across the software industry. This has repeatedly demonstrated the value of its commitment to safety and reliability. Memory safety, in particular, has caught the notice of governmental bodies in the European Union and the United States, among others.

We should aim to spread the benefits of Rust and its underlying ideas as far as possible across our industry and its users. While the current uptake of Rust is encouraging, it is limited today to areas where Rust adoption is relatively easy. There exists a large portion of production code in use today that cannot feasibly adopt Rust, and it is time we looked seriously at what it would take to change that.

The status quo

Costs of memory unsafety

Memory safety vulnerabilities are the most costly kinds of vulnerabilities, both for product owners and their users. These vulnerabilities and their costs have persisted despite the deployment of many mitigation measures in memory unsafe languages which often impose costs of their own.1 2

Experience has shown that regardless of the size of an existing codebase, incrementally adopting a memory safe language like Rust in new code brings roughly linear benefits in terms of new memory safety vulnerabilities. This is because most vulnerabilities come from new code, not old code.3 This means Rust adoption has value even if only adopted in new code.

Given the growing recognition of this problem from within various technical communities, major technology companies, and major governmental bodies, there is increasing pressure to adopt memory safe languages across the board for all new code. As this proposal explains, this presents both a significant opportunity and a significant challenge for Rust.

Obstacles to memory safety

Roughly speaking, there are three axes to adoption of memory safety: Social, Technical, and Economic. Making progress along one axis can overcome blockers in the others.

For example, safety has become more socially desirable in many technical communities over the years, which has led to the development of mitigation measures and the adoption of languages like Rust. This has come partly as a result of the recognition of the economic costs of memory safety vulnerabilities.

For C/C++ this has led to an improvement along the technical front in terms of automated checking, in both static and dynamic tooling. However, this protracted effort has also revealed the limits of such an approach without language changes. While there have been calls for C++ to adopt memory safety features,4 they have not gained traction within the C++ standards body for a combination of technical, social, and economic reasons.5

Obstacles to Rust adoption

Changing languages at a large scale is fearfully expensive.6

Rust itself is a major technical breakthrough that enables safety from all kinds of undefined behavior, including spatial safety, temporal safety, and data race safety, with very high confidence. This makes it appealing for those looking to introduce safety to their codebase. Rust adoption is feasible in the following situations:

Feasible: New codebases with Rust-only dependencies

This includes completely new projects as well as complete rewrites of existing projects, when such rewrites are socially and economically viable.

Feasible: Interprocess boundaries

Projects with a natural interprocess boundary between components are more easily migrated to Rust. Because of the loose coupling enforced by the boundary, the project can be incrementally migrated one component at a time. Microservice architectures with their RPC/HTTP boundaries are one example of this.

Feasible: Small, simple intraprocess API surface

Projects with a small, simple API surface that can be manually expressed in terms of the C ABI. This boundary, expressed and invoked in unsafe code, is prone to human error. It can be maintainable when the surface is small enough, but this also means that Rust adoption can decrease safety at the language boundary.

Feasible: Larger intraprocess API surface, but with limited vocabulary

Projects with a limited API vocabulary are able to use one of the existing interop tools like bindgen, cbindgen, or cxx.

Infeasible: Everything else

The fact that all of these options exist and undergo active development is a testament to the value developers see in Rust adoption. However, they leave out a large portion of production use cases today: Projects that make rich use of an API in a language like C++ where comparatively limited interop support exists for Rust, and that link in enough code to make rewriting infeasible.

Furthermore, the limitations of current interop tooling are not simply a matter of adding features. Many of them stem from a mismatch in the expressiveness of the two languages along various axes. As one example, C++ and Java both support overloading while Rust does not. In some cases this mismatch is broadly accepted as a missing feature in Rust that will be added in time. In others, Rust’s lack of expressiveness may be considered a feature in itself.

These mismatches point to the limitations of such approaches. If we attempt to solve them one at a time, we may never reach the “shiny future” we are working towards.

The next 6 months

We do not propose any specific deliverables over the next six months. We only propose a discussion with the Language, Compiler, and Libs-API teams that takes a serious look at the problem space and what it would take to solve it. This discussion should incorporate lessons from existing projects and lay the foundation for future explorations and engagements.

Possible discussion topics include:

  • Coverage of rich C++ APIs, including those that make use of language features like templates, (partial) specialization, and argument-dependent lookup. (Lang + Compiler)
  • Seamless use of “vocabulary types” like strings, vectors, and hashmaps, including the various kinds of conversions in source and at the ABI level. (Lang + Libs-API)
  • A standard IDL for describing a Rust API/ABI that can be produced by the Rust compiler. (Lang + Compiler)

The “shiny future” we are working towards

It is essential that our industry adopts memory safety broadly. To realize this, Rust should be feasible to adopt in any application, particularly those which prioritize performance and reliability in addition to safety.

This includes making Rust feasible to adopt in both new and existing applications that make rich use of APIs in memory unsafe languages like C++. To the extent possible, incremental Rust adoption should only increase safety, never decrease it.

Given that this is a highly ambitious, multi-year project, we should begin with presenting the problem space as accurately as possible to the Rust language team as a way to receive guidance and build alignment on overall direction.

Design axioms

This goal adheres to the general design axioms in the interop initiative’s problem statement:

  • Build the foundations for a better future while actively improving the present
  • Pursue high-quality interoperation from both sides
  • Pursue general-purpose interoperability (not tied to a specific toolchain/IR)
  • Avoid changes to Rust itself that would undermine its core values
  • Only change the language or standard library where external library solutions are insufficient

In addition, it proposes the following axioms:

  • Seek solutions that make 100% coverage possible. This means 100% of functions and methods defined in one language are callable in the other language. This may require some APIs to be unergonomic and/or unsafe to call.
  • Minimize the potential for human error. Interop should leverage trusted, automated tooling wherever possible.
  • Extend contracts between languages where possible. For example, a strongly typed interface in one language should be equally strongly typed in the other language, subject to the constraints imposed by that language.
  • Introduce zero overhead when calling between languages.
  • Prefer solutions that are general enough to apply to languages beyond C++.

Ownership and team asks

Owner: Jon Bauman and Tyler Mandry

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang, compiler, libs-api
Design meetingTeam lang, compiler, libs-api2-3 meetings expected; all involve lang
Author design docTyler Mandry
Author design docHelp wanted
Author design docHelp wanted

Frequently asked questions

None yet.


  1. https://alexgaynor.net/2020/may/27/science-on-memory-unsafety-and-security/

  2. https://security.googleblog.com/2021/04/rust-in-android-platform.html

  3. See https://security.googleblog.com/2024/09/eliminating-memory-safety-vulnerabilities-Android.html and https://security.googleblog.com/2022/12/memory-safe-languages-in-android-13.html.

  4. https://safecpp.org/draft.html

  5. https://cor3ntin.github.io/posts/profiles

  6. https://downloads.regulations.gov/ONCD-2023-0002-0020/attachment_1.pdf

Nightly support for ergonomic SIMD multiversioning

Metadata
Point of contactLuca Versari
StatusAccepted
Zulip channel#project-portable-simd
Tracking issuerust-lang/rust-project-goals#261
Teamslang
Task ownersLuca Versari

Summary

Figure out the best way for Rust to support generating code for multiple SIMD targets in a safe and ergonomic way.

Motivation

Even within the same architecture, CPUs vary significantly in which SIMD ISA extensions they implement1. Most libraries that are shipped to users in binary form thus tend to contain code for different SIMD targets and use runtime dispatch. Having compiler support for this pattern, i.e. by having the compiler generate multiple versions of code written only once, would significantly help drive Rust’s adoption in the world of codecs, where some of the most subtle memory vulnerabilities are found, as well as other domains where squeezing out the last bits of performance is fundamental.

The status quo

Currently, generating efficient code for a specific SIMD ISAs requires annotating the function with appropriate attributes. This is incompatible with generating multiple versions through i.e. generics.

This limitation can be worked around in different ways, all of which with some significant downsides:

  • Intermediate functions can be annotated as #[inline(always)] and inline in a top-level caller, with downsides for code size.
  • Calls between “multiversioned” functions do target selection again, which inhibits inlining and has performance implications.
  • Programmers explicitly define no-inline boundaries and call functions across such boundaries in a different way; this requires significant boilerplate and has bad ergonomics.
  • Macros can create multiple copies of the relevant functions and figure out how to call between those; this is bad for compilation times and not particularly rust-y.

There are currently multiple proposals for ways to resolve the above issues. In brief:

  • allow ADTs to carry feature information and pass it on to functions that take them as argument
  • have functions automatically inherit the target features of their callers
  • let features depend on const generic arguments to functions

The trade-offs between the different approaches are complex, and there is no consensus on the best path forward. More details on the proposals can be found in this document.

The next 6 months

  • A design meeting is scheduled to discuss the best approach forward on this topic.
  • A lang team experiment is approved, enabling exploration in the compiler of the proposed approach.
  • A RFC is posted, based on the results of the exploration, and reviewed.
  • The implementation is updated to reflect changes from the RFC, and becomes broadly available in the nightly compiler.

The “shiny future” we are working towards

Once the proposed design is stabilized, Rust will offer one of the most compelling stories for achieving very high performance on multiple targets, with minimal friction for developers.

This significantly increases the adoption of Rust in performance-critical, safety-sensitive low level libraries.

Design axioms

  • The common case should be simple and ergonomic.
  • Additional flexibility to unlock the maximum possible performance should be possible and sufficiently ergonomic.
  • The vast majority of SIMD usage should be doable in safe Rust.

Ownership and team asks

Owner: Identify a specific person or small group of people if possible, else the group that will provide the owner. GitHub user names are commonly used to remove ambiguity.

TaskOwner(s) or team(s)Notes
Design meetingTeam lang
Lang-team experimentTeam lang
Experimental implementationLuca Versari
Author RFCLuca Versari
RFC decisionTeam lang

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.


  1. For example, x86 CPUs currently have about 12 (!) different possible configurations with respect to AVX-512 support alone.

Publish first rust-lang-owned release of “FLS”

Metadata
Point of contactJoel Marcey
StatusAccepted
Zulip channel#t-spec
Tracking issuerust-lang/rust-project-goals#265
Teamsbootstrap, spec
Task ownersJoel Marcey, Ferrous Systems

Summary

Ferrous Systems will be transferring the Ferrocene Language Specification (FLS) to the Rust Project, under the ownership of the Specification Team, or t-spec. In the first half of 2025, the Specification team will integrate the FLS, under an appropriate name, into both its design and development processes, and the project as a whole.

Motivation

The Specification Team has been working for the past year on preparing a specification of Rust. Over this time, the Team has made and began executing several distinct plans to achieve this: creating a new document; modifying the reference; and most recently, agreeing with Ferrous Systems to take ownership of the FLS to support its specification delivery efforts. The current plan is to do the latter two processes in parallel, and in order to do that effectively the Ferrocene Language Specification needs to be adopted and integrated into the project processes and tooling.

The status quo

RFC 3355 describes the goals of the specification as “[Serving] the needs of Rust users, such as authors of unsafe Rust code, those working on safety critical Rust software, language designers, maintainers of Rust tooling, and so on,” and “Incorporating it in their process for language evolution. For example, the language team could require a new language feature to be included in the specification as a requirement for stabilization.”

Presently, the working draft Specification of Rust consists of a modified version of the reference, achieved by adding paragraph identifiers (almost finished), and slowly modifying the content to more normatively describe the language. This may help achieve one of the presented goals for the specification, namely incorporation into the language evolution process. However, Ferrous Systems has, over the past 2 years, developed the Ferrocene Language Specification, which has seen adoption in the Safety Critical Space, and a sharp change in the specification would create substantial financial burdens on those early adopters.

Based on more recent discussions and agreements with Ferrous Systems, the Specification Team will be incorporating the Ferrocene Language Specification as-is into its processes. This will leave us with two documents to maintain, with decisions to make on how they will fit into the Specification delivery process overall.

The next 6 months

The goal is to merge the Ferrocene Language Specification (FLS) into the rust-lang infrastructure and publish at least one version in some form under some (TBD) name. The expectation is that it will be integrated into our release process in a similar fashion as other rust-lang maintained books (the reference, rust book, etc) but because the FLS uses distinct tooling that may or may not be possible.

The “shiny future” we are working towards

The goal is designed to move forward the Rust Specification, in a way that is satisfying to both internal and external consumers, and that makes progress on the overall goals set out in RFC 3355. It is also designed to put us in a position for a 2025h2 goal of producing a first useful version of the specification that satisfies those goals, as well as any ancillary work that needs to be done along side the specification itself.

Design axioms

The following design axioms apply:

  • Making Decisions Effectively, but Efficiently: When the goal asks the Team to make a decision, the Team should be prepared in advance with the necessary background, and come to consensus based on as much information as is possible, but at the same time, acting with efficiency and alacrity, not spending more time than is necessary on a decision. In particular, the team should not delay discussing a decision more than is necessary.
    • Elaborating on the last part, decisions the team are well aware of needing to make should not be deferred once all of the requisite information is available, unless a higher priority decision needs to supplant it.
  • Iterative changes are better: When it comes to making modifications, particularly to the FLS, slow and gradual ones should be preferred to sharp, major ones.

Ownership and team asks

Owner: Joel Marcey, in his capacity of t-spec team member and Rust Foundation representative, will lead this project goal.

Some subgoals list an expected due/completion date. If one is omitted, completion by the end of 2025h1 is implied.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam spec
Copyright cleanup and assignmentJoel MarceyEnd of February 2025
Adjust tooling, as neededJoel MarceyJoel to find appropriate person
Standard reviewsTeam bootstrapFor any tooling integration
Continued updates for new releasesFerrous Systems

Frequently asked questions

Run the 2025H1 project goal program

Metadata
Point of contactNiko Matsakis
StatusAccepted
Zulip channel#project-goals
Tracking issuerust-lang/rust-project-goals#268
Teamsleadership-council
Task ownersleads of each team, Niko Matsakis, goals team

Summary

  • Create a goals team for running the project-goals-program
  • Run the second round of the Rust project goal program experiment

Motivation

Over 2024H2 we ran the first round of an experimental new Rust Project Goal program to reasonable success. Based on feedback received, we will make some minor adjustments to the plan and try a second round. We will also create a team so that the program is being run in a more sustainable way. Assuming that this second result continues to be positive, then in 2025h2 we would be looking to author an RFC describing the structure of the project goal program and making it a recurring part of project life.

The status quo

The Rust Project Goal program aims to resolve a number of challenges that the project faces for which having an established roadmap, along with a clarified ownership for particular tasks, would be useful:

  • Focusing effort and avoiding burnout:
    • One common contributor to burnout is a sense of lack of agency. People have things they would like to get done, but they feel stymied by debate with no clear resolution; feel it is unclear who is empowered to “make the call”; and feel unclear whether their work is a priority.
    • Having a defined set of goals, each with clear ownership, will address that uncertainty.
  • Helping direct incoming contribution:
    • Many would-be contributors are interested in helping, but don’t know what help is wanted/needed. Many others may wish to know how to join in on a particular project.
    • Identifying the goals that are being worked on, along with owners for them, will help both groups get clarity.
  • Helping the Foundation and Project to communicate
    • One challenge for the Rust Foundation has been the lack of clarity around project goals. Programs like fellowships, project grants, etc. have struggled to identify what kind of work would be useful in advancing project direction.
    • Declaring goals, and especially goals that are desired but lack owners to drive them, can be very helpful here.
  • Helping people to get paid for working on Rust
    • A challenge for people who are looking to work on Rust as part of their job – whether that be full-time work, part-time work, or contracting – is that the employer would like to have some confidence that the work will make progress. Too often, people find that they open RFCs or PRs which do not receive review, or which are misaligned with project priorities. A secondary problem is that there can be a perceived conflict-of-interest because people’s job performance will be judged on their ability to finish a task, such as stabilizing a language feature, which can lead them to pressure project teams to make progress.
    • Having the project agree before-hand that it is a priority to make progress in an area and in particular to aim for achieving particular goals by particular dates will align the incentives and make it easier for people to make commitments to would-be employers.

For more details, see

The next 6 months

  • Create a team to run the goal program in a more sustainable way
  • Publish monthly status updates on the goals selected for 2025h1

The “shiny future” we are working towards

We envision the Rust Project Goal program as a permanent and ongoing part of Rust development. People looking to learn more about what Rust is doing will be able to visit the Rust Project Goal website and get an overview; individual tracking issues will give them a detailed rundown of what’s been happening.

Rust Project Goals also serve as a “front door” to Rust, giving would-be contributors (particularly more prolific contributors, contractors, or companies) a clear way to bring ideas to Rust and get them approved and tracked.

Running the Rust Project Goals program will be a relatively scalable task that can be executed by a single individual.

Design axioms

  • Goals are a contract. Goals are meant to be a contract between the owner and project teams. The owner commits to doing the work. The project commits to supporting that work.
  • Goals aren’t everything, but they are our priorities. Goals are not meant to cover all the work the project will do. But goals do get prioritized over other work to ensure the project meets its commitments.
  • Goals cover a problem, not a solution. As much as possible, the goal should describe the problem to be solved, not the precise solution. This also implies that accepting a goal means the project is committing that the problem is a priority: we are not committing to accept any particular solution.
  • Nothing good happens without an owner. Rust endeavors to run an open, participatory process, but ultimately achieving any concrete goal requires someone (or a small set of people) to take ownership of that goal. Owners are entrusted to listen, take broad input, and steer a well-reasoned course in the tradeoffs they make towards implementing the goal. But this power is not unlimited: owners make proposals, but teams are ultimately the ones that decide whether to accept them.
  • To everything, there is a season. While there will be room for accepting new goals that come up during the year, we primarily want to pick goals during a fixed time period and use the rest of the year to execute.

Ownership and team asks

Owner: Niko Matsakis

  • Niko Matsakis can commit 20% time (avg of 1 days per week) to pursue this task, which he estimates to be sufficient.
TaskOwner(s) or team(s)Notes
Begin soliciting goals in Nov 2024Niko Matsakis
Approve goal slate for 2025h1leads of each team
Top-level Rust blog post for 2025h1 goalsNiko Matsakis
Propose team membershipNiko Matsakis
Org decisionTeam leadership-councilapprove creation of new team
January goal updategoals team
February goal updategoals team
Author RFCgoals team
March goal updategoals team
Begin soliciting goals for 2025h2goals team
April goal updategoals team
May goal updategoals team
June goal updategoals team

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

None.

Publish first version of StableMIR on crates.io

Metadata
Point of contactCelina G. Val
StatusAccepted
Zulip channel#project-stable-mir
Tracking issuerust-lang/rust-project-goals#266
Teamscompiler, project-stable-mir
Task ownersCelina G. Val, Help needed

Summary

Publish StableMIR crate(s) to crates.io to allow tool developers to create applications on the top of the Rust compiler, and extract code information from a compiled Rust crate and their dependencies without using compiler internal APIs.

Motivation

In the past couple of years we have introduced a more stable API, named StableMIR, to the Rust compiler to enable tool developers to analyze and extract information from compiled Rust crates without directly depending on compiler internals. By publishing StableMIR crate(s) to crates.io, we can provide a reliable interface that enables developers to build analysis tools, development environments, and other applications that work with Rust code while being insulated from internal compiler changes.

Publishing these crates through crates.io will make them easily accessible to the broader Rust community and establish a foundation for building a robust ecosystem of development tools. This will benefit the entire Rust ecosystem by enabling developers to create sophisticated tooling such as static analyzers, linters, and development environments that can work reliably across different Rust compiler versions. Besides stability, users will be able to rely on semantic versioning to track and adapt to changes, reducing the existing maintenance burden for these developers.

The status quo

In the past couple of years we have introduced a more stable API, named StableMIR, to the Rust compiler. This API provides tool developers more stability and predictability, reducing the maintenance cost, as well as providing a smaller surface API to reduce the ramp-up time for new developers.

However, StableMIR consumption model is still similar to any other internal compiler crate. It doesn’t have any explicit version, and it must be imported using an extern crate statement.

The next 6 months

The first task is to restructure the relationship between stable-mir and rustc_smir crates, eliminating existing dependencies on the stable-mir crate.

This will be followed by forking the stable-mir crate into its own repository, where we’ll implement CI jobs designed to detect any breaking changes that might occur due to compiler updates.

Once the structural changes are complete, we’ll shift our attention to documentation and publication. This includes creating comprehensive developer documentation that covers maintenance procedures for both crates, ensuring future maintainers have clear guidelines for updates and compatibility management.

The final step will be publishing the newly refactored and documented version of stable-mir to crates.io, making it readily available for tool developers in the Rust ecosystem.

The “shiny future” we are working towards

By establishing a stable and well-documented interface, we would like to empower developers to build a rich tooling ecosystem for Rust that can be maintained in parallel with the Rust compiler’s development.

This parallel development model ensures that tools can evolve alongside Rust itself, fostering innovation and reducing bottlenecks.

Design axioms

  • Enable tool developers to implement sophisticated analysis with low maintenance cost.
  • Do not compromise the development and innovation speed of the rust compiler.
  • Crates should follow semantic versioning.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam compiler
ImplementationCelina G. Val
Standard reviewsTeam project-stable-mir
Fork configurationHelp needed
DocumentationHelp needed
Publish crateCelina G. Val

Definitions

Definitions for terms used above:

  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.

Frequently asked questions

Instrument the Rust standard library with safety contracts

Metadata
Point of contactCelina G. Val
StatusAccepted
Tracking issuerust-lang/rust-project-goals#126
Zulip channelN/A
Teamscompiler, libs
Task ownersHelp wanted, Celina G. Val, Michael Tautschnig

Summary

Finish the implementation of the contract attributes proposed in the compiler MCP-759, and port safety contracts from the verify-rust-std fork to the Rust standard library.

Motivation

Safety contracts serve as formal specifications that define the preconditions, postconditions, and invariants, that must be maintained for functions and data structures to operate correctly and safely. Currently, the Rust standard library already contains safety pre- and postconditions specified in the unsafe functions’ documentation.

Contract attributes will enable developers to define safety requirements and behavioral specifications through programmatic contracts, which can be automatically converted into runtime checks when needed. These contracts can also express conditions that are verifiable through static analysis tools, and also provide foundation for formal verification of the standard library implementation, and other Rust code.

The status quo

Safety conditions are already well documented, and the Rust standard library is also instrumented using check_library_ub and check_language_ub in many different places for conditions that are checkable at runtime.

The compiler team has also accepted Felix Klock’s proposal MCP-759 to add experimental contracts attributes, and the initial implementation is currently under review.

Finally, we have annotated and verified around 200 functions in the verify-rust-std fork with safety contracts using contract attributes similar to the ones proposed in MCP-759.

The next 6 months

First, we will keep working with the compiler team to finish the implementation of contract attributes. We’ll add support to #[contracts::requires] and #[contracts::ensures] attributes as described in MCP-759, as well type invariant specification.

This will allow users to convert contracts into runtime checks, as well as, provide compiler interface for external tools, such as verification tools, to retrieve the annotated contracts.

Once that has been merged to the compiler, we will work with the library to annotate functions of the standard library with their safety contracts.

The “shiny future” we are working towards

All unsafe functions in Rust should have their safety conditions specified using contracts, and verified that those conditions are enough to guarantee absence of undefined behavior.

Rust users should be able to check that their code do not violate the safety contracts of unsafe functions, which would rule out the possibility that their applications could have a safety bug.

Design axioms

  • No runtime penalty: Instrumentation must not affect the standard library runtime behavior, including performance, unless users opt-in for contract runtime checks.
  • Formal Verification: Enable the verification of the standard library implementation.
  • Contract as code: Keeping the contract language and specification as close as possible to Rust syntax and semantics will lower the barrier for users to understand and be able to write their own contracts.

Ownership and team asks

Owner: Celina G. Val and Michael Tautschnig

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam libs

Experimental Contract attributes

TaskOwner(s) or team(s)Notes
Author MCPComplete Done already by Felix Klock
ImplementationCelina G. ValIn progress.
Standard reviewsTeam compiler
Design meetingTeam compiler

Standard Library Contracts

TaskOwner(s) or team(s)Notes
Standard Library ContractsCelina G. Val, Michael Tautschnig
Writing new contractsHelp wanted
Standard reviewsTeam libs

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author MCP and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.

Frequently asked questions

Unsafe Fields

Metadata
Point of contactJack Wrenn
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#273
Teamscompiler, lang
Task ownersJacob Pratt, Luca Versari

Summary

Design and implement a mechanism for denoting when fields carry library safety invariants.

Motivation

The absence of a mechanism for denoting the presence of library safety invariants increases both the risk of working with unsafe code and the difficulty of evaluating its soundness.

The status quo

Presently, Rust lacks mechanisms for denoting when fields carry library safety invariants, and for enforcing extra care around their use. Consequently, to evaluate the soundness of unsafe code (i.e., code which relies on safety invariants being upheld), it is not enough to check the contents of unsafe blocks — one must check all places (including safe contexts) in which safety invariants might be violated. (See The Scope of Unsafe)

For example, consider this idealized Vec:

#![allow(unused)]
fn main() {
pub struct Vec<T> {
    data: Box<[MaybeUninit<T>]>,
    len: usize,
}
}

Although len is bound by a safety invariant, it is trivial to violate its invariant in entirely safe code:

#![allow(unused)]
fn main() {
impl Vec<T> {
    pub fn evil(&mut self) {
        self.len += 2;
    }
}
}

Rust cannot enforce that modifications of len require unsafe, because the language does not provide the programmer a way of communicating to the compiler that len carries safety invariants.

The “shiny future” we are working towards

Rust programmers will use the unsafe keyword to denote fields that carry library safety invariants; e.g.:

#![allow(unused)]
fn main() {
struct Vec<T> {
    // SAFETY: The elements `data[i]` for
    // `i < len` are in a valid state.
    unsafe data: Box<[MaybeUninit<T>]>,
    unsafe len: usize,
}
}

Rust will require that usages of unsafe fields which could violate their safety invariants must only occur within unsafe contexts.

The next 6 months

In the next six months, we will iterate on the design and implementation of unsafe fields. An RFC for unsafe fields will be accepted, and a candidate implementation will — at the very least — be ready to enter the stabilization process.

Design axioms

The design of unsafe fields is guided by three axioms:

  1. Unsafe Fields Denote Safety Invariants A field should be marked unsafe if it carries arbitrary library safety invariants with respect to its enclosing type.
  2. Unsafe Usage is Always Unsafe Uses of unsafe fields which could violate their invariants must occur in the scope of an unsafe block.
  3. Safe Usage is Usually Safe Uses of unsafe fields which cannot violate their invariants should not require an unsafe block.

Ownership and team asks

Owner: Jack Wrenn

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang
Author RFCJacob PrattRFC3458, Living Design Doc
ImplementationLuca Versari
Standard reviewsTeam compiler
Design meetingTeam lang
RFC decisionTeam lang

Ongoing discussion on Zulip.

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

TBD

Secure quorum-based cryptographic verification and mirroring for crates.io

Metadata
Short titleCrates.io mirroring
Point of contactwalterhpearce
StatusAccepted
Zulip channelN/A
Tracking issuerust-lang/rust-project-goals#271
Teamscargo, crates-io, infra, leadership-council, release
Task ownersJosh Triplett, walterhpearce

Summary

Within 6 months, we will work towards consensus with Rust teams on an RFC for cryptographic verification and mirroring of releases and crates.io, and provide experimental infrastructure demonstrating the ability to mirror crates.io and verify downloads from a mirror. This will include a proof of concept for a secure chain-of-trust to the Rust Project, via a quorum-based mechanism, and methods to verify singular Rust crates, their singular index entries, as well as the index and the artifacts as a whole.

This consensus will include a clear policy for the threat models we should protect against, and a clear demonstration that the proposed infrastructure secures against those threats.

Motivation

Rustaceans need to be able to download crates and know that they’re getting the crate files that were published to crates.io without modification. Rustaceans everywhere should be able to use local mirrors of crates.io, such as geographically distributed mirrors or mirrors within infrastructure (e.g. CI) that they’re using.

The status quo

Currently rustup, cargo and crates.io provide no cryptographic security for the index, crates or our releases. The only verification which occurs is via HTTPS validation of the URLs and tamperable hashes within the index. This provides assurance that the server being communicated with is owned by the project & crates.io, but does not allow for the possibility of secure mirroring nor protects against compromise or tampering with the index or files (either at rest or in transit).

There are places where Rust is difficult to use right now. Using Cargo with crates.io works well for Rustaceans with unfirewalled access to high speed Internet, but not all are so lucky. Some are behind restrictive firewalls which they are required to use. Some don’t have reliable access to the Internet. In cases like these, we want to support mirrors of crates.io in a secure way that provides cryptographic guarantees that they are getting the same packages as are provided by the Rust Project, without any risk of tampering.

Another reason for wanting to be able to better support mirrors is to address cost pressures on Rust. Approximately half of Rust release and crate traffic is from CI providers. Being able to securely distribute Rust releases & crates from within CI infrastructure would be mutually beneficial, since it would allow the Rust Foundation to reallocate budget or donated resources to other uses, and would make Rust CI actions faster and more reliable on CI platforms that have mirrors.

Finally, supply chain security is a growing concern, particularly among corporate and government users of Rust. The Log4j vulnerability brought much greater attention to the problems that can occur when a single dependency nested arbitrarily deep in a dependency graph has a critical vulnerability. Many of these users are putting significant resources into better understanding their dependencies, which includes being able to attest that their dependencies verifiably came from specific sources like crates.io.

The next 6 months

We would like to have a experimental out-of-band version of a signing pipeline for the project for releases and crates.io. We expect this 6 month goal to consist of standing up experimental versions of the infrastructure and systems required for utilizing TUF on releases and crates with external commands and forks of the appropriate tools. This experimental version shall be a in-kind implementation of the RFC which is discussed in this goal. As a part of this process, we wish to take appropriate team time for discussion of the RFC for mirroring and signing to come to a consensus. The RFC shall be a transforming description (“living documentation”) of the MVP implementation in order to drive discussion and show proof-of-concept to the appropriate teams.

This goal shall include a series of educational materials (ex: blog posts, broken-down RFC components, or other materials) which discuss the history of artifact signing, current crate and release security, and the driving goals behind requiring cryptographic verification of Rust Project artifacts and why we have come to this solution. We hope to provide this material to interested parties across the project, with project-team-specific materials, to help drive consensus to this solution. These materials will not assume background knowledge of TUF or the TUF specification, and will provide motivation for the selection of TUF over other possibilities. These materials shall be crafted by the project team (walterhpearce & Josh Triplett)

We are requesting the following activities from Rust Project teams:

  • Leadership Council:
    • Review of threat models, policy decision on whether those are the correct threat models to target, general approval about the use of a quorum to address those threat models.
  • Cargo Team:
    • Review and approval of design for index changes and crate verification
    • Review and approval of incremental bandwidth usage for updates using novel index update mechanism (to be created by walterhpearce)
  • Crates.io Team:
    • Review and approval of design for index changes
    • Review and approval of rotation & revocation strategy
  • Infra Team:
    • Review and approval of design for key management & ceremony process
    • Review and approval of proposed repository structure
    • Review and approval of secure storage & usage for automated keys
  • Release Team:
    • Review of secure storage & usage for automated keys
    • Review and approval of rotation & revocation strategy
  • Rustup Team: None

The project goal team will also make themselves consistently available to the community and involved teams for additional one-on-one discussions or broader group discussions (async or sync) to discuss any items involving TUF and signing, as desired by any member of the above teams with additional questions or concerns.

We will structure these discussions so that these decisions can largely be made independently. In particular, we will endeavor to provide discussion venues for asynchronous discussion of individual issues with the RFC, such that each team member need only participate in (and get notifications for) the discussions they’re interested in. (For instance, this may consist of a GitHub repository with separate issues for each topic/decision, and/or associated Zulip streams)

We also wish to implement technical items for this goal.

  • There will be a sample process for selecting a trusted root quorum for the project (endorsed by the leadership council), and that quorum will have completed a proof-of-concept signing ceremony. This may not be the final iteration of the quorum process, quorum, or root of trust; it will be a demonstration of feasibility for the purposes of this experiment, and a test that the process and systems in place all function.

  • We will have deployed a TUF repository for Rust releases for utilizing as validation against Rust releases downloaded by Rustup.

  • We will have implemented TUF validation in a fork of Rustup in a condition which can be a PR to Rustup project as an optional feature

  • We will have integrated signing into a TUF repository for crates published to crates.io; this may be accomplished in collaboration with crates.io or out-of-band via the new updates RSS feed.

  • Finally, we’ll provide some method for end users to verify these signatures as an external cargo subcommand & rustup fork for proof-of-concept

The “shiny future” we are working towards

After this next six months, we will continue working to bring the experimental infrastructure into production.

We intend to provide production mirroring capabilities, and some mechanism for automatic mirror discovery. Cargo should be able to automatically discover and use mirrors provided within CI infrastructure, within companies, or within geographic regions, and cryptographically verify those that mirrors are providing unmodified crates and indexes from crates.io.

We’ll provide cryptographic verification of our GitHub source repositories, and some demonstration of how to verify mirrors of those repositories.

We hope to have follow-up RFCs which will enable authors to generate their own quorums for author and organization level signing and validation of the crates they own.

We’ll add support for similar cryptographic security for third-party crate repositories.

The project choosing to adopt this strategy and infrastructure will require ongoing commitment of people and effort to maintain sufficient working knowledge of operating the infrastructure and addressing the threat models. We will need to affirm that this is sustainable long-term, that there will be a critical mass of people who will continue to care about this going forward. In part, this will include paid staff and ongoing financial commitment from the Foundation whose job is to maintain it, which the Foundation has already stated that they’re willing to commit.

Ownership and team asks

TaskOwner(s) or team(s)Notes
Inside Rust blog post about proof-of-conceptwalterhpearce
Series of documents (RFC components or Inside Rust blog posts)walterhpearce, Josh Triplett
Policy decisionTeam leadership-council1 hour synchronously discussing the threat models, policy, and quorum mechanism. Note: The ask from the Leadership Council is not a detailed exploration of how we address these threat models; rather, this will be a presentation of the threat models and a policy decision that the project cares about those threat models, along with the specific explanation of why a quorum is desirable to address those threat models.
Design meetingTeam cargo1 hour Overall Design and threat model
Design meetingTeam cargo1 hour General design/implementation for index verification
Dedicated reviewerTeam cargo1 hour Design for novel incremental download mechanism for bandwidth conservation
Design meetingTeam crates-io1 hour Overall Design, threat model, and discussion of key management and quorums
Design meetingTeam crates-io1 hour General design/implementation for automated index signing
Design meetingTeam infra3 hours of design and threat model discussion. Specific production infrastructure setup will come at a later time after the initial proof of concept.
Discussion and moral supportTeam releaseAsynchronous discussion of the release team’s role in the chain of trust, and preliminary approval of an experimental proof of concept. Approximately ~1 hour of total time across the 6-month period.

Quorum-based cryptographic infrastructure (RFC 3724)

TaskOwner(s) or team(s)Notes
Further revisions to RFCwalterhpearce, Josh Triplett
Implementation and proof-of-concept deploymentwalterhpearce

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.

Not accepted

This section contains goals that were proposed but ultimately not accepted, either for want of resources or consensus. In many cases, narrower versions of these goals were proposed instead.

GoalPoint of contactTask Owners and Champions
Field Projections@y86-devHelp wanted
Rust Specification TestingConnor Horman

Rust project goals for 2024H2

Status: Accepted RFC #3672 has been accepted, establishing 26 total Rust project goals for 2024H2.

Want to learn more?

Goals

This page lists the 26 project goals accepted for 2024h2.

Flagship goals

Flagship goals represent the goals expected to have the broadest overall impact.

Other goals

This is the full list of goals (including flagship).

Invited goals. Some goals here are marked with the Help wanted badge for their point of contact. These goals are called “invited goals”. Teams have reserved some capacity to pursue these goals but until an appropriate owner is found they are only considered provisionally accepted. If you are interested in serving as the owner for one of these invited goals, reach out to the point of contact listed in the goal description.

Associated type position impl trait

Metadata
Point of contactOliver Scherer
StatusAccepted
Tracking issuerust-lang/rust-project-goals#103
Zulip channelN/A
Teamslang, types
Task ownersOliver Scherer

Summary

Stable support for impl Trait in the values of associated types (aka “associated type position impl trait” or ATPIT)

Motivation

Rust has been on a long-term quest to support impl Trait in more and more locations (“impl Trait everywhere”). The next step in that journey is supporting impl Trait in the values of associated types (aka “associated type position impl trait” or ATPIT), which allows impls to provide more complex types as the value of an associated type, particularly anonymous types like closures and futures. It also allows impls to hide the precise type they are using for an associated type, leaving room for future changes. This is the latest step towards the overall vision of support impl Trait notation in various parts of the Rust language.

The status quo

Impls today must provide a precise and explicit value for each associated type. For some associated types, this can be tedious, but for others it is impossible, as the proper type involves a closure or other aspect which cannot be named. Once a type is specified, impls are also unable to change that type without potentially breaking clients that may have hardcoded it.

Rust’s answer to these sorts of problems is impl Trait notation, which is used in a number of places within Rust to indicate “some type that implements Trait”:

  • Argument position impl Trait (“APIT”), in inherent/item/trait functions, in which impl Trait desugars to an anonymous method type parameter (sometimes called “universal” impl Trait);
  • Return type position in inherent/item functions (“RPIT”) and in trait (“RPITIT”) functions, in which impl Trait desugars to a fresh opaque type whose value is inferred by the compiler.

ATPIT follows the second pattern, creating a new opaque type.

The next six months

The plan for 2024 is to stabilize Associated Type Position Impl Trait (ATPIT). The design has been finalized from the lang team perspective for some time, but the types team is still working out final details. In particular, the types team is trying to ensure that whatever programs are accepted will also be accepted by the next generation trait solver, which handles opaque types in a new and simplified way.

The “shiny future” we are working towards

This goal is part of the “impl Trait everywhere” effort, which aims to support impl Trait in any position where it makes sense. With the completion of this goal we will support impl Trait in

  • the type of a function argument (“APIT”) in inherent/item/trait functions;
  • return types in functions, both inherent/item functions (“RPIT”) and trait functions (“RPITIT”);
  • the value of an associated type in an impl (ATPIT).

Planned extensions for the future include:

  • allowing impl Trait in type aliases (“TAIT”), like type I = impl Iterator<Item = u32>;
  • allowing impl Trait in let bindings (“LIT”), like let x: impl Future = foo();
  • dyn safety for traits that make use of RTPIT and async functions.

Other possible future extensions are:

  • allowing impl Trait in where-clauses (“WCIT”), like where T: Foo<impl Bar>;
  • allowing impl Trait in struct fields, like struct Foo { x: impl Display };

See also: the explainer here for a “user’s guide” style introduction, though it’s not been recently updated and may be wrong in the details (especially around TAIT).

Design axioms

None.

Ownership and team asks

Owner: oli-obk owns this goal.

TaskOwner(s) or team(s)Notes
ImplementationOliver Scherer
FCP decision(s)Team types
Stabilization decisionTeam types lang

Frequently asked questions

None yet.

Patterns of empty types

Metadata
Point of contact@Nadrieril
StatusAccepted
Tracking issuerust-lang/rust-project-goals#115
Zulip channelN/A
Teamscompiler, lang
Task owners@Nadrieril, Goal owner

Summary

Introduce an RFC for never patterns or other solutions for patterns involving uninhabited types.

Motivation

The story about pattern-matching is incomplete with regards to empty types: users sometimes have to write unreachable!() for cases they know to be impossible. This is a papercut that we can solve, and would make for a more consistent pattern-matching story.

This is particularly salient as the never type ! is planned to be stabilized in edition 2024.

The status quo

Empty types are used commonly to indicate cases that can’t happen, e.g. in error-generic interfaces:

#![allow(unused)]
fn main() {
impl TryFrom<X> for Y {
    type Error = Infallible;
    ...
}
// or
impl SomeAST {
    pub fn map_nodes<E>(self, f: impl FnMut(Node) -> Result<Node, E>) -> Result<Self, E> { ... }
}
// used in the infallible case like:
let Ok(new_ast) = ast.map_nodes::<!>(|node| node) else { unreachable!() };
// or:
let new_ast = match ast.map_nodes::<!>(|node| node) {
    Ok(new_ast) => new_ast,
    Err(never) => match never {},
}
}

and conditional compilation:

#![allow(unused)]
fn main() {
pub struct PoisonError<T> {
    guard: T,
    #[cfg(not(panic = "unwind"))]
    _never: !,
}
pub enum TryLockError<T> {
    Poisoned(PoisonError<T>),
    WouldBlock,
}
}

For the most part, pattern-matching today treats empty types as if they were non-empty. E.g. in the above example, both the else { unreachable!() } above and the Err branch are required.

The unstable exhaustive_patterns allows all patterns of empty type to be omitted. It has never been stabilized because it goes against design axiom n.1 “Pattern semantics are predictable” when interacting to possibly-uninitialized data.

The next six months

The first step is already about to complete: the min_exhaustive_patterns feature is in FCP and about to be stabilized. This covers a large number of use-cases.

After min_exhaustive_patterns, there remains the case of empty types behind references, pointers and union fields. The current proposal for these is never_patterns; next steps are to submit the RFC and then finish the implementation according to the RFC outcome.

The “shiny future” we are working towards

The ideal endpoint is that users never have code to handle a pattern of empty type.

Design axioms

  • Pattern semantics are predictable: users should be able to tell what data a pattern touches by looking at it. This is crucial when matching on partially-initialized data.
  • Impossible cases can be omitted: users shouldn’t have to write code for cases that are statically impossible.

Ownership and team asks

Owner: @Nadrieril

I (@Nadrieril) am putting forward my own contribution for driving this forward, both on the RFC and implementation sides. I am an experienced compiler contributor and have been driving this forward already for several months.

  • I expect to be authoring one RFC, on never patterns (unless it gets rejected and we need a different approach).
    • The feature may require one design meeting.
  • Implementation work is 80% done, which leaves about 80% more to do. This will require reviews from the compiler team, but not more than the ordinary. | Task | Owner(s) or team(s) | Notes | | –––––––––––––– | –––––––––– | —– | | Author RFC | @Nadrieril | | | Implementation | @Nadrieril | | | Standard reviews | Team compiler | | | Discussion and moral support | Team lang | | | Author stabilization report | Goal owner | |

Note:

  • RFC decisions, Design Meetings, and Stabilizaton decisions were intentionally not included in the above list of asks. The lang team is not sure it can commit to completing those reviews on a reasonable timeline.

Frequently asked questions

Scalable Polonius support on nightly

Metadata
Point of contactRémy Rakic
StatusAccepted
Tracking issuerust-lang/rust-project-goals#118
Zulip channel#t-types/polonius
Teamstypes
Task ownersAmanda Stjerna, Rémy Rakic, Niko Matsakis

Summary

Implement a native rustc version of the Polonius next generation borrow checking algorithm, that would scale better than the previous datalog implementation.

Motivation

Polonius is an improved version of the borrow checker that resolves common limitations of the borrow checker and which is needed to support future patterns such as “lending iterators” (see #92985). Its model also prepares us for further improvements in the future.

Some support exists on nightly, but this older prototype has no path to stabilization due to scalability issues. We need an improved architecture and implementation to fix these issues.

The status quo

The next six months

  • Land polonius on nightly

The “shiny future” we are working towards

Stable support for Polonius.

Design axioms

N/A

Ownership and team asks

Owner: lqd

Other support provided by Amanda Stjerna as part of her PhD.

TaskOwner(s) or team(s)Notes
Design reviewNiko Matsakis
ImplementationRémy Rakic, Amanda Stjerna
Standard reviewsTeam typesMatthew Jasper

Support needed from the project

We expect most support to be needed from the types team, for design, reviews, interactions with the trait solver, and so on. We expect Niko Matsakis, leading the polonius working group and design, to provide guidance and design time, and Michael Goulet and Matthew Jasper to help with reviews.

Outputs and milestones

Outputs

Nightly implementation of polonius that passes NLL problem case #3 and accepts lending iterators (#92985).

Performance should be reasonable enough that we can run the full test suite, do crater runs, and test it on CI, without significant slowdowns. We do not expect to be production-ready yet by then, and therefore the implementation would still be gated under a nightly -Z feature flag.

As our model is a superset of NLLs, we expect little to no diagnostics regressions, but improvements would probably still be needed for the new errors.

Milestones

MilestoneExpected date
Factoring out higher-ranked concerns from the main pathTBD
Replace parts of the borrow checker with location-insensitive PoloniusTBD
Location-sensitive prototype on nightlyTBD
Verify full test suite/crater pass with location-sensitive PoloniusTBD
Location-sensitive pass on nightly, tested on CITBD

Frequently asked questions

None yet.

Assemble project goal slate

Metadata
Point of contactNiko Matsakis
StatusAccepted
Tracking issuerust-lang/rust-project-goals#102
Zulip channel#project-goals
Teamsleadership-council
Task owners(none)

Extracted from RFC 3614

Summary

Run an experimental goal program during the second half of 2024

Motivation

This RFC proposes to run an experimental goal program during the second half of 2024 with Niko Matsakis as owner/organizer. This program is a first step towards an ongoing Rust roadmap. The proposed outcomes for 2024 are (1) select an initial slate of goals using an experimental process; (2) track progress over the year; (3) drawing on the lessons from that, prepare a second slate of goals for 2025 H1. This second slate is expected to include a goal for authoring an RFC proposing a permanent process.

The status quo

The Rust project last published an annual roadmap in 2021. Even before that, maintaining and running the roadmap process had proved logistically challenging. And yet there are a number of challenges that the project faces for which having an established roadmap, along with a clarified ownership for particular tasks, would be useful:

  • Focusing effort and avoiding burnout:
    • One common contributor to burnout is a sense of lack of agency. People have things they would like to get done, but they feel stymied by debate with no clear resolution; feel it is unclear who is empowered to “make the call”; and feel unclear whether their work is a priority.
    • Having a defined set of goals, each with clear ownership, will address that uncertainty.
  • Helping direct incoming contribution:
    • Many would-be contributors are interested in helping, but don’t know what help is wanted/needed. Many others may wish to know how to join in on a particular project.
    • Identifying the goals that are being worked on, along with owners for them, will help both groups get clarity.
  • Helping the Foundation and Project to communicate
    • One challenge for the Rust Foundation has been the lack of clarity around project goals. Programs like fellowships, project grants, etc. have struggled to identify what kind of work would be useful in advancing project direction.
    • Declaring goals, and especially goals that are desired but lack owners to drive them, can be very helpful here.
  • Helping people to get paid for working on Rust
    • A challenge for people who are looking to work on Rust as part of their job – whether that be full-time work, part-time work, or contracting – is that the employer would like to have some confidence that the work will make progress. Too often, people find that they open RFCs or PRs which do not receive review, or which are misaligned with project priorities. A secondary problem is that there can be a perceived conflict-of-interest because people’s job performance will be judged on their ability to finish a task, such as stabilizing a language feature, which can lead them to pressure project teams to make progress.
    • Having the project agree before-hand that it is a priority to make progress in an area and in particular to aim for achieving particular goals by particular dates will align the incentives and make it easier for people to make commitments to would-be employers.

For more details, see

The plan for 2024

The plan is to do a “dry run” of the process in the remainder of 2024. The 2024 process will be driven by Niko Matsakis; one of the outputs will be an RFC that proposes a more permanent process for use going forward. The short version of the plan is that we will

  • ASAP (April): Have a ~2 month period for selecting the initial slate of goals. Goals will be sourced from Rust teams and the broader community. They will cover the highest priority work to be completed in the second half of 2024.
  • June: Teams will approve the final slate of goals, making them ‘official’.
  • Remainder of the year: Regular updates on goal progress will be posted
  • October: Presuming all goes well, the process for 2025 H1 begins. Note that the planning for 2025 H1 and finishing up of goals from 2024 H2 overlap.

The “shiny future” we are working towards

We wish to get to a point where

  • it is clear to onlookers and Rust maintainers alike what the top priorities are for the project and whether progress is being made on those priorities
  • for each priority, there is a clear owner who
    • feels empowered to make decisions regarding the final design (subject to approval from the relevant teams)
  • teams cooperate with one another to prioritize work that is blocking a project goal
  • external groups who would like to sponsor or drive priorities within the Rust project know how to bring proposals and get feedback

More concretely, assuming this goal program is successful, we would like to begin another goal sourcing round in late 2024 (likely Oct 15 - Dec 15). We see this as fitting into a running process where the project evaluates its program and re-establishes goals every six months.

Design axioms

  • Goals are a contract. Goals are meant to be a contract between the owner and project teams. The owner commits to doing the work. The project commits to supporting that work.
  • Goals aren’t everything, but they are our priorities. Goals are not meant to cover all the work the project will do. But goals do get prioritized over other work to ensure the project meets its commitments.
  • Goals cover a problem, not a solution. As much as possible, the goal should describe the problem to be solved, not the precise solution. This also implies that accepting a goal means the project is committing that the problem is a priority: we are not committing to accept any particular solution.
  • Nothing good happens without an owner. Rust endeavors to run an open, participatory process, but ultimately achieving any concrete goal requires someone (or a small set of people) to take ownership of that goal. Owners are entrusted to listen, take broad input, and steer a well-reasoned course in the tradeoffs they make towards implementing the goal. But this power is not unlimited: owners make proposals, but teams are ultimately the ones that decide whether to accept them.
  • To everything, there is a season. While there will be room for accepting new goals that come up during the year, we primarily want to pick goals during a fixed time period and use the rest of the year to execute.

Ownership and team asks

Owner: Niko Matsakis

  • Niko Matsakis can commit 20% time (avg of 1 days per week) to pursue this task, which he estimates to be sufficient.
TaskOwner(s) or team(s)Notes
RFC decisionTeam leadership-councilComplete
Inside Rust blog post inviting feedbackPosted
Top-level Rust blog post announcing result

Support needed from the project

  • Project website resources to do things like
    • post blog posts on both Inside Rust and the main Rust blog;
    • create a tracking page (e.g., https://rust-lang.org/goals);
    • create repositories, etc.
  • For teams opting to participate in this experimental run:
    • they need to meet with the goal committee to review proposed goals, discuss priorities;
    • they need to decide in a timely fashion whether they can commit the proposed resources

Outputs and milestones

Outputs

There are three specific outputs from this process:

  • A goal slate for the second half (H2) of 2024, which will include
    • a set of goals, each with an owner and with approval from their associated teams
    • a high-level write-up of why this particular set of goals was chosen and what impact we expect for Rust
    • plan is to start with a smallish set of goals, though we don’t have a precise number in mind
  • Regular reporting on the progress towards these goals over the course of the year
    • monthly updates on Inside Rust (likely) generated by scraping tracking issues established for each goal
    • larger, hand authored updates on the main Rust blog, one in October and a final retrospective in December
  • A goal slate for the first half (H1) of 2025, which will include
    • a set of goals, each with an owner and with approval from their associated teams
    • a high-level write-up of why this particular set of goals was chosen and what impact we expect for Rust
    • (probably) a goal to author an RFC with a finalized process that we can use going forward

Milestones

Key milestones along the way (with the most impactful highlighted in bold):

Date2024 H2 Milestone2025 H1 Milestones
Apr 26Kick off the goal collection process
May 24Publish draft goal slate, take feedback from teams
June 14Approval process for goal slate begins
June 28Publish final goal slate
JulyPublish monthly update on Inside Rust
AugustPublish monthly update on Inside Rust
SeptemberPublish monthly update on Inside Rust
Oct 1Publish intermediate goal progress update on main Rust blogBegin next round of goal process, expected to cover first half of 2025
NovemberPublish monthly update on Inside RustNov 15: Approval process for 2025 H1 goal slate begins
DecemberPublish retrospective on 2024 H2Announce 2025 H1 goal slate

Process to be followed

The owner plans to author up a proposed process but rough plans are as follows:

  • Create a repository rust-lang/project-goals that will be used to track proposed goals.
  • Initial blog post and emails soliciting goal proposals, authored using the same format as this goal.
  • Owner will consult proposals along with discussions with Rust team members to assemble a draft set of goals
  • Owner will publish a draft set of goals from those that were proposed
  • Owner will read this set with relevant teams to get feedback and ensure consensus
  • Final slate will be approved by each team involved:
    • Likely mechanism is a “check box” from the leads of all teams that represents the team consensus

It is not yet clear how much work it will be to drive this process. If needed, the owner will assemble a “goals committee” to assist in reading over goals, proposing improvements, and generally making progress towards a coherent final slate. This committee is not intended to be a decision making body.

Frequently asked questions

Is there a template for project goals?

This RFC does not specify details, so the following should not be considered normative. However, you can see a preview of what the project goal process would look like at the nikomatsakis/rust-project-goals repository; it contains a goal template. This RFC is in fact a “repackaged” version of 2024’s proposed Project Goal #1.

Why is the goal completion date targeting end of year?

In this case, the idea is to run a ~6-month trial, so having goals that are far outside that scope would defeat the purpose. In the future we may want to permit longer goal periods, but in general we want to keep goals narrowly scoped, and 6 months seems ~right. We don’t expect 6 months to be enough to complete most projects, but the idea is to mark a milestone that will demonstrate important progress, and then to create a follow-up goal in the next goal season.

How does the goal completion date interact with the Rust 2024 edition?

Certainly I expect some of the goals to be items that will help us to ship a Rust 2024 edition – and likely a goal for the edition itself (presuming we don’t delay it to Rust 2025).

Do we really need a “goal slate” and a “goal season”?

Some early drafts of project goals were framing in a purely bottom-up fashion, with teams approving goals on a rolling basis. That approach though has the downside that the project will always be in planning mode which will be a continuing time sink and morale drain. Deliberating on goals one at a time also makes it hard to weigh competing goals and decide which should have priority.

There is another downside to the “rolling basis” as well – it’s hard to decide on next steps if you don’t know where you are going. Having the concept of a “goal slate” allows us to package up the goals along with longer term framing and vision and make sure that they are a coherent set of items that work well together. Otherwise it can be very easy for one team to be solving half of a problem while other teams neglect the other half.

Do we really need an owner?

Nothing good happens without an owner. The owner plays a few important roles:

  • Publicizing and organizing the process, authoring blog posts on update, and the like.
  • Working with individual goal proposals to sharpen them, improve the language, identify milestones.
  • Meeting with teams to discuss relative priorities.
  • Ensuring a coherent slate of goals.
    • For example, if the cargo team is working to improve build times in CI, but the compiler team is focused on build times on individual laptops, that should be surfaced. It may be that its worth doing both, but there may be an opportunity to do more by focusing our efforts on the same target use cases.

Isn’t the owner basically a BDFL?

Simply put, no. The owner will review the goals and ensure a quality slate, but it is up to the teams to approve that slate and commit to the goals.

Why the six months horizon?

Per the previous points, it is helpful to have a “season” for goals, but having e.g. an annual process prevents us from reacting to new ideas in a nimble fashion. At the same time, doing quarterly planning, as some companies do, is quite regular overhead. Six months seemed like a nice compromise, and it leaves room for a hefty discussion period of about 2 months, which seems like a good fit for an open-source project.

Rust 2024 Edition

Metadata
Point of contactTC
StatusAccepted
FlagshipYes
Tracking issuerust-lang/rust-project-goals#117
Zulip channel#edition
Teamslang, leadership-council, types
Task owners(none)

Summary

Feature complete status for Rust 2024, with final release to occur in early 2025.

Motivation

RFC #3501 confirmed the desire to ship a Rust edition in 2024, continuing the pattern of shipping a new Rust edition every 3 years. Our goal for 2024 H2 is to stabilize a new edition on nightly by the end of 2024.

The status quo

Editions are a powerful tool for Rust but organizing them continues to be a “fire drill” each time. We have a preliminary set of 2024 features assembled but work needs to be done to marshal and drive (some subset of…) them to completion.

The next six months

The major goal this year is to release the edition on nightly. Top priority items are as follows:

ItemTrackingRFCMore to do?
Reserve gen keywordhttps://github.com/rust-lang/rust/issues/123904https://github.com/rust-lang/rust/pull/116447No.
Lifetime Capture Rules 2024https://github.com/rust-lang/rust/issues/117587https://github.com/rust-lang/rfcs/pull/3498Yes.
Precise capturing (dependency)https://github.com/rust-lang/rust/issues/123432https://github.com/rust-lang/rfcs/pull/3617Yes.
Change fallback to !https://github.com/rust-lang/rust/issues/123748N/AYes.

The full list of tracked items can be found using the A-edition-2024 label..

The “shiny future” we are working towards

The Edition will be better integrated into our release train. Nightly users will be able to “preview” the next edition just like they would preview any other unstable feature. New features that require new syntax or edition-related changes will land throughout the edition period. Organizing the new edition will be rel

Design axioms

The “Edition Axioms” were laid out in RFC #3085:

  • Editions do not split the ecosystem. The most important rule for editions is that crates in one edition can interoperate seamlessly with crates compiled in other editions.
  • Edition migration is easy and largely automated. Whenever we release a new edition, we also release tooling to automate the migration. The tooling is not necessarily perfect: it may not cover all corner cases, and manual changes may still be required.
  • Users control when they adopt the new edition. We recognize that many users, particularly production users, will need to schedule time to manage an Edition upgrade as part of their overall development cycle.
  • Rust should feel like “one language”. We generally prefer uniform behavior across all editions of Rust, so long as it can be achieved without compromising other design goals.
  • Editions are meant to be adopted. We don’t force the edition on our users, but we do feel free to encourage adoption of the edition through other means.

Ownership and team asks

Owner: TC

TaskOwner(s) or team(s)Notes
RFC decisionTeam leadership-councilComplete (RFC #3501)
Stabilization decisionTeam lang types
Top-level Rust blog post

Outputs and milestones

  • Owner: TC

Outputs

  • Edition release complete with
    • announcement blog post
    • edition migration guide

Milestones

DateVersionEdition stage
2024-10-11Branch v1.83Go / no go on all items
2024-10-17Release v1.82Rust 2024 nightly beta
2025-01-03Branch v1.85Cut Rust 2024 to beta
2025-02-20Release v1.85Release Rust 2024

Frequently asked questions

None yet.

Expose experimental LLVM features for automatic differentiation and GPU offloading

Metadata
Point of contactManuel Drehwald
StatusAccepted
Tracking issuerust-lang/rust-project-goals#109
Other tracking issuesrust-lang/rust#124509, rust-lang/rust#124509
Zulip channelN/A
Teamscompiler, lang
Task ownersManuel Drehwald

Summary

Expose experimental LLVM features for automatic differentiation and GPU offloading.

Motivation

Scientific computing, high performance computing (HPC), and machine learning (ML) all share the interesting challenge in that they each, to different degrees, care about highly efficient library and algorithm implementations, but that these libraries and algorithms are not always used by people with deep experience in computer science. Rust is in a unique position because ownership, lifetimes, and the strong type system can prevent many bugs. At the same time strong alias information allows compelling performance optimizations in these fields, with performance gains well beyond that otherwise seen when comparing C++ with Rust. This is due to how automatic differentiation and GPU offloading strongly benefit from aliasing information.

The status quo

Thanks to PyO3, Rust has excellent interoperability with Python. Conversely, C++ has a relatively weak interop story. This can lead Python libraries to using slowed C libraries as a backend instead, just to ease bundling and integration. Fortran is mostly used in legacy places and hardly used for new projects.

As a solution, many researchers try to limit themself to features which are offered by compilers and libraries built on top of Python, like JAX, PyTorch, or, more recently, Mojo. Rust has a lot of features which make it more suitable to develop a fast and reliable backend for performance critical software than those languages. However, it lacks two major features which developers now expect. One is high performance autodifferentiation. The other is easy use of GPU resources.

Almost every language has some way of calling hand-written CUDA/ROCm/Sycl kernels, but the interesting feature of languages like Julia, or of libraries like JAX, is that they offer users the ability to write kernels in the language the users already know, or a subset of it, without having to learn anything new. Minor performance penalties are not that critical in such cases, if the alternative are a CPU-only solution. Otherwise worthwhile projects such as Rust-CUDA end up going unmaintained due to being too much effort to maintain outside of LLVM or the Rust project.

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

The next six months

We are requesting support from the Rust project for continued experimentation:

  1. Merge the #[autodiff] fork.
  2. Expose the experimental batching feature of Enzyme, preferably by a new contributor.
  3. Merge an MVP #[offloading] fork which is able to run simple functions using rayon parallelism on a GPU or TPU, showing a speed-up.

The “shiny future” we are working towards

The purpose of this goal is to enable continued experimentation with the underlying LLVM functionality. The eventual goal of this experimentation is that all three proposed features (batching, autodiff, offloading) can be combined and work nicely together. The hope is that we will have state-of-the-art libraries like faer to cover linear algebra, and that we will start to see more and more libraries in other languages using Rust with these features as their backend. Cases which don’t require interactive exploration will also become more popular in pure Rust.

Caveats to this future

There is not yet consensus amongst the relevant Rust teams as to how and/or whether this functionality should be exposed on stable. Some concerns that continued experimentation will hopefully help to resolve:

  • How effective and general purpose is this functionality?
  • How complex is this functionality to support, and how does that trade off with the value it provides? What is the right point on the spectrum of tradeoffs?
  • Can code using these Rust features still compile and run on backends other than LLVM, and on all supported targets? If not, how should we manage the backend-specific nature of it?
  • Can we avoid tying Rust features too closely to the specific properties of any backend or target, such that we’re confident these features can remain stable over decades of future landscape changes?
  • Can we fully implement every feature of the provided functionality (as more than a no-op) on fully open systems, despite the heavily proprietary nature of parts of the GPU and accelerator landscape?

Design axioms

Offloading

  • We try to provide a safe, simple and opaque offloading interface.
  • The “unit” of offloading is a function.
  • We try to not expose explicit data movement if Rust’s ownership model gives us enough information.
  • Users can offload functions which contains parallel CPU code, but do not have final control over how the parallelism will be translated to co-processors.
  • We accept that hand-written CUDA/ROCm/etc. kernels might be faster, but actively try to reduce differences.
  • We accept that we might need to provide additional control to the user to guide parallelism, if performance differences remain unacceptably large.
  • Offloaded code might not return the exact same values as code executed on the CPU. We will work with t-opsem to develop clear rules.

Autodiff

  • We try to provide a fast autodiff interface which supports most autodiff features relevant for scientific computing.
  • The “unit” of autodiff is a function.
  • We acknowledge our responsibility since user-implemented autodiff without compiler knowledge might struggle to cover gaps in our features.
  • We have a fast, low level, solution with further optimization opportunities, but need to improve safety and usability (i.e. provide better high level interfaces).
  • We need to teach users more about autodiff “pitfalls” and provide guides on how to handle them. See, e.g. https://arxiv.org/abs/2305.07546.
  • We do not support differentiating inline assembly. Users are expected to write custom derivatives in such cases.
  • We might refuse to expose certain features if they are too hard to use correctly and provide little gains (e.g. derivatives with respect to global vars).

Add your design axioms here. Design axioms clarify the constraints and tradeoffs you will use as you do your design work. These are most important for project goals where the route to the solution has significant ambiguity (e.g., designing a language feature or an API), as they communicate to your reader how you plan to approach the problem. If this goal is more aimed at implementation, then design axioms are less important. Read more about design axioms.

Ownership and team asks

Owner: Manuel Drehwald

Manuel S. Drehwald is working 5 days per week on this, sponsored by LLNL and the University of Toronto (UofT). He has a background in HPC and worked on a Rust compiler fork, as well as an LLVM-based autodiff tool for the last 3 years during his undergrad. He is now in a research-based master’s degree program. Supervision and discussion on the LLVM side will happen with Johannes Doerfert and Tom Scogland.

Resources: Domain and CI for the autodiff work is being provided by MIT. This might be moved to the LLVM org later this year. Hardware for benchmarks is being provided by LLNL and UofT. CI for the offloading work will be provided by LLNL or LLVM (see below).

Minimal “smoke test” reviews will be needed from the compiler-team. The Rust language changes at this stage are expected to be a minimal wrapper around the underlying LLVM functionality and the compiler team need only vet that the feature will not hinder usability for ordinary Rust users or cause undue burden on the compiler architecture itself. There is no requirement to vet the quality or usability of the design.

TaskOwner(s) or team(s)Notes
DevelopmentManuel Drehwald
Lang-team experimentTeam lang(approved)
Standard reviewsTeam compiler

Outputs and milestones

Outputs

  • An #[offload] rustc-builtin-macro which makes a function definition known to the LLVM offloading backend.

    • Made a PR to enable LLVM’s offloading runtime backend.
    • Merge the offload macro frontend
    • Merge the offload Middle-end
  • An offload!([GPU1, GPU2, TPU1], foo(x, y,z)); macro (placeholder name) which will execute function foo on the specified devices.

  • An #[autodiff] rustc-builtin-macro which differentiates a given function.

    • Merge the Autodiff macro frontend
    • Merge the Autodiff Enzyme backend
    • Merge the Autodiff Middle-end
  • A #[batching] rustc-builtin-macro which fuses N function calls into one call, enabling better vectorization.

Milestones

  • The first offloading step is the automatic copying of a slice or vector of floats to a device and back.

  • The second offloading step is the automatic translation of a (default) Clone implementation to create a host-to-device and device-to-host copy implementation for user types.

  • The third offloading step is to run some embarrassingly parallel Rust code (e.g. scalar times Vector) on the GPU.

  • Fourth we have examples of how rayon code runs faster on a co-processor using offloading.

  • Stretch-goal: combining autodiff and offloading in one example that runs differentiated code on a GPU.

Frequently asked questions

Why do you implement these features only on the LLVM backend?

Performance-wise, we have LLVM and GCC as performant backends. Modularity-wise, we have LLVM and especially Cranelift being nice to modify. It seems reasonable that LLVM thus is the first backend to have support for new features in this field. Especially the offloading support should be supportable by other compiler backends, given pre-existing work like OpenMP offloading and WebGPU.

Do these changes have to happen in the compiler?

Yes, given how Rust works today.

However, both features could be implemented in user-space if the Rust compiler someday supported reflection. In this case we could ask the compiler for the optimized backend IR for a given function. We would then need use either the AD or offloading abilities of the LLVM library to modify the IR, generating a new function. The user would then be able to call that newly generated function. This would require some discussion on how we can have crates in the ecosystem that work with various LLVM versions, since crates are usually expected to have a MSRV, but the LLVM (and like GCC/Cranelift) backend will have breaking changes, unlike Rust.

Batching?

This is offered by all autodiff tools. JAX has an extra command for it, whereas Enzyme (the autodiff backend) combines batching with autodiff. We might want to split these since both have value on their own.

Some libraries also offer array-of-struct vs struct-of-array features which are related but often have limited usability or performance when implemented in userspace.

Writing a GPU backend in 6 months sounds tough…

True. But similar to the autodiff work, we’re exposing something that’s already existing in the backend.

Rust, Julia, C++, Carbon, Fortran, Chappel, Haskell, Bend, Python, etc. should not all have write their own GPU or autodiff backends. Most of these already share compiler optimization through LLVM or GCC, so let’s also share this. Of course, we should still push to use our Rust specific magic.

Rust Specific Magic?

TODO

How about Safety?

We want all these features to be safe by default, and are happy to not expose some features if the gain is too small for the safety risk. As an example, Enzyme can compute the derivative with respect to a global. That’s probably too niche, and could be discouraged (and unsafe) for Rust.

Testing infra + contributors for a-mir-formality

Metadata
Point of contactNiko Matsakis
StatusAccepted
Tracking issuerust-lang/rust-project-goals#122
Zulip channel#t-types/formality
Teamstypes
Task ownersNiko Matsakis, and others, lcnr

Summary

The goal for a-mir-formality this year is to bootstrap it as a live, maintained project:

  • Achieve 2 regular contributors from T-types in addition to Niko Matsakis
  • Support fuzz testing and/or the ability to test against rustc

Motivation

The status quo

Most communication and definition of Rust’s type/trait system today takes place through informal argument and with reference to compiler internals. a-mir-formality offers a model of Rust at a much higher level, but it remains very incomplete compared to Rust and, thus far, it has been primarily developed by Niko Matsakis.

The next six months

The goal for a-mir-formality this year is to bootstrap it as a live, maintained project:

  • Achieve 2 regular contributors from T-types in addition to Niko Matsakis
  • Support fuzz testing and/or the ability to test against rustc

The “shiny future” we are working towards

The eventual goal is for a-mir-formality to serve as the official model of how the Rust type system works. We have found that having a model enables us to evaluate designs and changes much more quickly than trying to do everything in the real compiler. We envision a-mir-formality being updated with new features prior to stabilization which will require it to be a living codebase with many contributors. We also envision it being tested both through fuzzing and by comparing its results to the compiler to detect drift.

Design axioms

  • Designed for exploration and extension by ordinary Rust developers. Editing and maintaining formality should not require a PhD. We prefer lightweight formal methods over strong static proof.
  • Focused on the Rust’s static checking. There are many things that a-mir-formality could model. We are focused on those things that we need to evaluate Rust’s static checks. This includes the type system and trait system.
  • Clarity over efficiency. Formality’s codebase is only meant to scale up to small programs. Efficiency is distinctly secondary.
  • The compiler approximates a-mir-formality, a-mir-formality approximates the truth. Rust’s type system is Turing Complete and cannot be fully evaluated. We expect the compiler to have safeguards (for example, overflow detection) that may be more conservative than those imposed by a-mir-formality. In other words, formality may accept some programs the compiler cannot evaluate for practical reasons. Similarly, formality will have to make approximations relative to the “platonic ideal” of what Rust’s type system would accept.

Ownership and team asks

Owner: Niko Matsakis

We will require participation from at least 2 other members of T-types. Current candidates are lcnr + compiler-errors.

TaskOwner(s) or team(s)Notes
ImplementationNiko Matsakis, lcnr, and others
Standard reviewsTeam types

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Use annotate-snippets for rustc diagnostic output

Metadata
Point of contactScott Schafer
StatusAccepted
Tracking issuerust-lang/rust-project-goals#123
Zulip channelN/A
Teamscompiler
Task ownersScott Schafer, Esteban Kuber

Summary

Switch to annotate-snippets for rendering rustc’s output, with no loss of functionality or visual regressions.

Motivation

Cargo has been adding its own linting system, where it has been using annotate-snippets to try and match Rust’s output. This has led to duplicate code between the two, increasing the overall maintenance load. Having one renderer that produces Rust-like diagnostics will make it so there is a consistent style between Rust and Cargo, as well as any other tools with similar requirements like miri, and should lower the overall maintenance burden by rallying behind a single unified solution.

The status quo

Currently rustc has its own Emitter that encodes the theming properties of compiler diagnostics. It has handle all of the intricancies of terminal support (optional color, terminal width querying and adapting of output), layout (span and label rendering logic), and the presentation of different levels of information. Any tool that wants to approximate rustc’s output for their own purposes, needs to use a third-party tool that diverges from rustc’s output, like annotate-snippets or miette. Any improvements or bugfixes contributed to those libraries are not propagated back to rustc. Because the emitter is part of the rustc codebase, the barrier to entry for new contributors is artificially kept high than it otherwise would be.

annotate-snippets is already part of the rustc codebase, but it is disabled by default, doesn’t have extensive testing and there’s no way of enabling this output through cargo, which limits how many users can actually make use of it.

The next 6 months

  • annotate-snippets rendered output reaches full partity (modulo reasonable non-significant divergences) with rustc’s output
  • rustc is fully using annotate-snippets for their output.

The “shiny future” we are working towards

The outputs of rustc and cargo are fully using annotate-snippets, with no regressions to the rendered output. annotate-snippets grows its feature set, like support for more advanced rendering formats or displaying diagnostics with more than ASCII-art, independently of the compiler development cycle.

Design axioms

This section is optional, but including [design axioms][da] can help you signal how you intend to balance constraints and tradeoffs (e.g., “prefer ease of use over performance” or vice versa). Teams should review the axioms and make sure they agree. [Read more about design axioms][da].

  • Match rustc’s output: The output of annotate-snipepts should match rustc, modulo reasonable non-significant divergences
  • Works for Cargo (and other tools): annotate-snippets is meant to be used by any project that would like “Rust-style” output, so it should be designed to work with any project, not just rustc. [da]: https://rust-lang.github.io/rust-project-goals/about/design_axioms.html

Ownership and team asks

Owner: Esteban Kuber, Scott Schafer

Identify a specific person or small group of people if possible, else the group that will provide the owner

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams.

  • Subgoal:
    • Describe the work to be done and use to mark “subitems”.
  • Owner(s) or team(s):
    • List the owner for this item (who will do the work) or Help wanted if an owner is needed.
    • If the item is a “team ask” (i.e., approve an RFC), put Team and the team name(s).
  • Status:
    • List Help wanted if there is an owner but they need support, for example funding.
    • Other needs (e.g., complete, in FCP, etc) are also fine.

Adjust the table below; some common examples are shown below.

TaskOwner(s) or team(s)Notes
Standard reviewsTeam compiler
Top-level Rust blog post inviting feedback

Reach output parity for rustc/annotation-snippets

TaskOwner(s) or team(s)Notes
Port a subset of rustc’s UI testsScott Schafer
Make list of current unnaddressed divergencesScott Schafer
address divergencesScott Schafer

Initial use of annotate-snippets

TaskOwner(s) or team(s)Notes
update annotate-snippets to latest version
teach cargo to pass annotate-snippets flagEsteban Kuber
add ui test mode comparing new output
switch default nightly rustc output

Production use of annotate-snippets

TaskOwner(s) or team(s)Notes
switch default rustc output
release notes
switch ui tests to only check new output
Dedicated reviewerTeam compilerEsteban Kuber will be the reviewer

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Bring the Async Rust experience closer to parity with sync Rust

Bring the Async Rust experience closer to parity with sync Rust

Metadata
Short titleAsync
Point of contactTyler Mandry
StatusAccepted
FlagshipYes
Tracking issuerust-lang/rust-project-goals#105
Zulip channel#wg-async
Teamscompiler, lang, libs, libs-api
Task ownersMichael Goulet, Niko Matsakis, Santiago Pastorino, Tyler Mandry, Michael Goulet, compiler

Summary

Over the next six months, we will deliver several critical async Rust building block features

Motivation

This goal represents the next step on a multi-year program aiming to raise the experience of authoring “async Rust” to the same level of quality as “sync Rust”. Async Rust is a crucial growth area, with 52% of the respondents in the 2023 Rust survey indicating that they use Rust to build server-side or backend applications.

The status quo

Async Rust performs great, but can be hard to use

Async Rust is the most common Rust application area according to our 2023 Rust survey. Rust is a great fit for networked systems, especially in the extremes:

  • Rust scales up. Async Rust reduces cost for large dataplanes because a single server can serve high load without significantly increasing tail latency.
  • Rust scales down. Async Rust can be run without requiring a garbage collector or even an operating system, making it a great fit for embedded systems.
  • Rust is reliable. Networked services run 24/7, so Rust’s “if it compiles, it works” mantra means fewer unexpected failures and, in turn, fewer pages in the middle of the night.

Despite async Rust’s popularity, using async I/O makes Rust significantly harder to use. As one Rust user memorably put it, “Async Rust is Rust on hard mode.” Several years back the async working group collected a number of “status quo” stories as part of authoring an async vision doc. These stories reveal a number of characteristic challenges:

First focus: language parity, interop traits

Based on the above analysis, the Rust org has been focused on driving async/sync language parity, especially in those areas that block the development of a rich ecosystem. The biggest progress took place in Dec 2023, when async fn in traits and return position impl trait in trait were stabilized. Other work includes documenting async usability challenges in the original async vision doc, stabilizing helpers like std::future::poll_fn, and polishing and improving async error messages.

The need for an aligned, high judgment group of async experts

Progress on async-related issues within the Rust org has been slowed due to lack of coherence around a vision and clear steps. General purpose teams such as lang and libs-api have a hard time determining how to respond to, e.g., particular async stabilization requests, as they lack a means to judge whether any given decision is really the right step forward. Theoretically, the async working group could play this role, but it has not really been structured with this purpose in mind. For example, the criteria for membership is loose and the group would benefit from more representation from async ecosystem projects. This is an example of a larger piece of Rust “organizational debt”, where the term “working group” has been used for many different purposes over the years.

The next six months

In the second half of 2024 we are planning on the following work items. The following three items are what we consider to be the highest priority, as they do the most to lay a foundation for future progress (and they themselves are listed in priority order):

We have also identified three “stretch goals” that we believe could be completed:

Resolve the “send bound” problem

Although async functions in traits were stabilized, there is currently no way to write a generic function that requires impls where the returned futures are Send. This blocks the use of async function in traits in some core ecosystem crates, such as tower, which want to work across all kinds of async executors. This problem is called the “send bound” problem and there has been extensive discussion of the various ways to solve it. RFC #3654 has been opened proposing one solution and describing why that path is preferred. Our goal for the year is to adopt some solution on stable.

A solution to the send bound problem should include a migration path for users of the trait_variant crate, if possible. For RFC #3654 (RTN), this would require implementable trait aliases (see RFC #3437).

Reorganize the Async WG

We plan to reorganize the async working group into a structure that will better serve the projects needs, especially when it comes to aligning around a clear async vision. In so doing, we will help “launch” the async working group out from the launchpad umbrella team and into a more permanent structure.

Despite its limitations, the async working group serves several important functions for async Rust that need to continue:

  • It provides a forum for discussion around async-related topics, including the #async-wg zulip stream as well as regular sync meetings. These forums don’t necessarily get participation by the full set of voices that we would like, however.
  • It owns async-related repositories, such as the sources for the async Rust book (in dire need of improvement), arewewebyet, and the futures-rs crate. Maintenance of these sites has varied though and often been done by a few individuals acting largely independently.
  • It advises the more general teams (typically lang and libs-api) on async-related matters. The authoring of the (mildly dated) async vision doc took place under the auspices of the working group, for example. However, the group lacks decision making power and doesn’t have a strong incentive to coalesce behind a shared vision, so it remains more a “set of individual voices” that does not provide the general purpose teams with clear guidance.

We plan to propose one or more permanent teams to meet these same set of needs. The expectation is that these will be subteams under the lang and libs top-level teams.

Stabilize async closures

Building ergonomic APIs in async is often blocked by the lack of async closures. Async combinator-like APIs today typically make use of an ordinary Rust closure that returns a future, such as the filter API from StreamExt:

#![allow(unused)]
fn main() {
fn filter<Fut, F>(self, f: F) -> Filter<Self, Fut, F>
where
    F: FnMut(&Self::Item) -> Fut,
    Fut: Future<Output = bool>,
    Self: Sized,
}

This approach however does not allow the closure to access variables captured by reference from its environment:

#![allow(unused)]
fn main() {
let mut accept_list = vec!["foo", "bar"]
stream
    .filter(|s| async { accept_list.contains(s) })
}

The reason is that data captured from the environment is stored in self. But the signature for sync closures does not permit the return value (Self::Output) to borrow from self:

#![allow(unused)]
fn main() {
trait FnMut<A>: FnOnce<A> {
    fn call_mut(&mut self, args: A) -> Self::Output;
}
}

To support natural async closures, a trait is needed where call_mut is an async fn, which would allow the returned future to borrow from self and hence modify the environment (e.g., accept_list, in our example above). Or, desugared, something that is equivalent to:

#![allow(unused)]
fn main() {
trait AsyncFnMut<A>: AsyncFnOnce<A> {
    fn call_mut<'s>(
        &'s mut self,
        args: A
    ) -> impl Future<Output = Self::Output> + use<'s, A>;
    //                                        ^^^^^^^^^^ note that this captures `'s`
    //
    // (This precise capturing syntax is unstable and covered by
    // rust-lang/rust#123432).
}
}

The goal for this year to be able to

  • support some “async equivalent” to Fn, FnMut, and FnOnce bounds
    • this should be usable in all the usual places
  • support some way to author async closure expressions

These features should be sufficient to support methods like filter above.

The details (syntax, precise semantics) will be determined via experimentation and subject to RFC.

Stabilize trait for async iteration

Stretch Goal

There has been extensive discussion about the best form of the trait for async iteration (sometimes called Stream, sometimes AsyncIter, and now being called AsyncGen). We believe the design space has been sufficiently explored that it should be possible to author an RFC laying out the options and proposing a specific plan.

Release a proc macro for dyn dispatch with async fn in traits

Stretch Goal

Currently we do not support using dyn with traits that use async fn or -> impl Trait. This can be solved without language extensions through the use of a proc macro. This should remove the need for the use of the async_trait proc macro in new enough compilers, giving all users the performance benefits of static dispatch without giving up the flexibility of dynamic dispatch.

Complete async drop experiments

Not funded

Authors of async code frequently need to call async functions as part of resource cleanup. Because Rust today only supports synchronous destructors, this cleanup must take place using alternative mechanisms, forcing a divergence between sync Rust (which uses destructors to arrange cleanup) and async Rust. MCP 727 proposed a series of experiments aimed at supporting async drop in the compiler. We would like to continue and complete those experiments. These experiments are aimed at defining how support for async drop will be implemented in the compiler and some possible ways that we could modify the type system to support it (in particular, one key question is how to prevent types whose drop is async from being dropped in sync code).

The “shiny future” we are working towards

Our eventual goal is to provide Rust users building on async with

  • the same core language capabilities as sync Rust (async traits with dyn dispatch, async closures, async drop, etc);
  • reliable and standardized abstractions for async control flow (streams of data, error recovery, concurrent execution), free of accidental complexity;
  • an easy “getting started” experience that builds on a rich ecosystem;
  • good performance by default, peak performance with tuning;
  • the ability to easily adopt custom runtimes when needed for particular environments, language interop, or specific business needs.

Design axiom

  • Uphold sync Rust’s bar for reliability. Sync Rust famously delivers on the general feeling of “if it compiles, it works” – async Rust should do the same.
  • We lay the foundations for a thriving ecosystem. The role of the Rust org is to develop the rudiments that support an interoperable and thriving async crates.io ecosystem.
  • When in doubt, zero-cost is our compass. Many of Rust’s biggest users are choosing it because they know it can deliver the same performance (or better) than C. If we adopt abstractions that add overhead, we are compromising that core strength. As we build out our designs, we ensure that they don’t introduce an “abstraction tax” for using them.
  • From embedded to GUI to the cloud. Async Rust covers a wide variety of use cases and we aim to make designs that can span those differing constraints with ease.
  • Consistent, incremental progress. People are building async Rust systems today – we need to ship incremental improvements while also steering towards the overall outcome we want.

Ownership and team asks

Here is a detailed list of the work to be done and who is expected to do it. This table includes the work to be done by owners and the work to be done by Rust teams (subject to approval by the team in an RFC/FCP). The overall owners of the async effort (and authors of this goal document) are Tyler Mandry and Niko Matsakis. We have identified owners for subitems below; these may change over time.

TaskOwner(s) or team(s)Notes
Overall program managementTyler Mandry, Niko Matsakis

“Send bound” problem

TaskOwner(s) or team(s)Notes
ImplementationMichael GouletComplete
Author RFCNiko MatsakisComplete
RFC decisionTeam langComplete
Stabilization decisionTeam lang

Async WG reorganization

TaskOwner(s) or team(s)Notes
Author proposal
Org decisionTeam libs, lang

Async closures

TaskOwner(s) or team(s)Notes
implementationComplete
Author RFC
RFC decisionTeam lang
Design meetingTeam lang2 meetings expected
Author call for usageMichael Goulet
Stabilization decisionTeam lang

Trait for async iteration

TaskOwner(s) or team(s)Notes
Author RFC
RFC decisionTeam libs-api lang
Design meetingTeam lang2 meetings expected
Implementation

Dyn dispatch for AFIT

TaskOwner(s) or team(s)Notes
ImplementationSantiago Pastorino
Standard reviewsTyler Mandry

Async drop experiments

TaskOwner(s) or team(s)Notes
author MCPComplete
MCP decisioncompilerComplete
Implementation workNot funded (*)
Design meetingTeam lang2 meetings expected
Standard reviewsTeam compiler
(*) Implementation work on async drop experiments is currently unfunded. We are trying to figure out next steps.

Support needed from the project

Agreement from lang, libs libs-api to prioritize the items marked Team in the table above.

The expectation is that

  • async closures will occupy 2 design meetings from lang during H2
  • async iteration will occupy 2 design meetings from lang during H2 and likely 1-2 from libs API
  • misc matters will occupy 1 design meeting from lang during H2

for a total of 4-5 meetings from lang and 1-2 from libs API.

Frequently asked questions

Can we really do all of this in 6 months?

This is an ambitious agenda, no doubt. We believe it is possible if the teams are behind us, but things always take longer than you think. We have made sure to document the “priority order” of items for this reason. We intend to focus our attention first and foremost on the high priority items.

Why focus on send bounds + async closures?

These are the two features that together block the authoring of traits for a number of common interop purposes. Send bounds are needed for generic traits like the Service trait. Async closures are needed for rich combinator APIs like iterators.

Why not build in dyn dispatch for async fn in traits?

Async fn in traits do not currently support native dynamic dispatch. We have explored a number of designs for making it work but have not completed all of the language design work needed, and are not currently prioritizing that effort. We do hope to support it via a proc macro this year and extend to full language support later, hopefully in 2025.

Why are we moving forward on a trait for async iteration?

There has been extensive discussion about the best design for the “Stream” or “async iter” trait and we judge that the design space is well understood. We would like to unblock generator syntax in 2025 which will require some form of trait.

The majority of the debate about the trait has been on the topic of whether to base the trait on a poll_next function, as we do today, or to try and make the trait use async fn next, making it more anaologous with the Iterator trait (and potentially even making it be two versions of a single trait). We will definitely explore forwards compatibility questions as part of this discussion. Niko Matsakis for example still wants to explore maybe-async-like designs, especially for combinator APIs like map. However, we also refer to the design axiom that “when in doubt, zero-cost is our compass” – we believe we should be able to stabilize a trait that does the low-level details right, and then design higher level APIs atop that.

Why do you say that we lack a vision, don’t we have an [async vision doc][avd]?

Yes, we do, and the [existing document][avd] has been very helpful in understanding the space. Moreover, that document was never RFC’d and we have found that it lacks a certain measure of “authority” as a result. We would like to drive stronger alignment on the path forward so that we can focus more on execution. But doing that is blocked on having a more effective async working group structure (hence the goal to reorganize the async WG).

What about “maybe async”, effect systems, and keyword generics?

Keyword generics is an ambitious initiative to enable code that is “maybe async”. It has generated significant controversy, with some people feeling it is necessary for Rust to scale and others judging it to be overly complex. One of the reasons to reorganize the async WG is to help us come to a consensus around this point (though this topic is broader than async).

Stabilize cargo-script

Metadata
Point of contactEd Page
StatusAccepted
Tracking issuerust-lang/rust-project-goals#119
Zulip channelN/A
Teamscargo, lang
Task ownersEd Page

Summary

Stabilize support for “cargo script”, the ability to have a single file that contains both Rust code and a Cargo.toml.

Motivation

Being able to have a Cargo package in a single file can reduce friction in development and communication, improving bug reports, educational material, prototyping, and development of small utilities.

The status quo

Today, at minimum a Cargo package is at least two files (Cargo.toml and either main.rs or lib.rs). The Cargo.toml has several required fields.

To share this in a bug report, people resort to

  • Creating a repo and sharing it
  • A shell script that cats out to multiple files
  • Manually specifying each file
  • Under-specifying the reproduction case (likely the most common due to being the easiest)

To create a utility, a developer will need to run cargo new, update the Cargo.toml and main.rs, and decide on a strategy to run this (e.g. a shell script in the path that calls cargo run --manifest-path ...).

The next six months

The support is already implemented on nightly. The goal is to stabilize support. With RFC #3502 and RFC #3503 approved, the next steps are being tracked in rust-lang/cargo#12207.

At a high-level, this is

  • Add support to the compiler for the frontmatter syntax
  • Add support in Cargo for scripts as a “source”
  • Polish

The “shiny future” we are working towards

Design axioms

  • In the trivial case, there should be no boilerplate. The boilerplate should scale with the application’s complexity.
  • A script with a couple of dependencies should feel pleasant to develop without copy/pasting or scaffolding generators.
  • We don’t need to support everything that exists today because we have multi-file packages.

Ownership and team asks

Owner: epage

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams.

  • Subgoal:
    • Describe the work to be done and use to mark “subitems”.
  • Owner(s) or team(s):
    • List the owner for this item (who will do the work) or Help wanted if an owner is needed.
    • If the item is a “team ask” (i.e., approve an RFC), put Team and the team name(s).
  • Status:
    • List Help wanted if there is an owner but they need support, for example funding.
    • Other needs (e.g., complete, in FCP, etc) are also fine.
TaskOwner(s) or team(s)Notes
ImplementationEd Page
Stabilization decisionTeam lang cargo

Begin resolving cargo-semver-checks blockers for merging into cargo

Metadata
Point of contactPredrag Gruevski
StatusAccepted
Tracking issuerust-lang/rust-project-goals#104
Zulip channelN/A
Teamscargo
Task ownersPredrag Gruevski

Summary

Design and implement cargo-semver-checks functionality that lies on the critical path for merging the tool into cargo itself.

Motivation

Cargo assumes that all packages adhere to semantic versioning (SemVer). However, SemVer adherence is quite hard in practice: research shows that accidental SemVer violations are relatively common (lower-bound: in 3% of releases) and happen to Rustaceans of all skill levels. Given the significant complexity of the Rust SemVer rules, improvements here require better tooling.

cargo-semver-checks is a linter for semantic versioning (SemVer) in Rust. It is broadly adopted by the Rust community, and the cargo team has expressed interest in merging it into cargo itself as part of the existing cargo publish workflow. By default, cargo publish would require SemVer compliance, but offer a flag (analogous to the --allow-dirty flag for uncommitted changes) to override the SemVer check and proceed with publishing anyway.

The cargo team has identified a set of milestones and blockers that must be resolved before cargo-semver-checks can be integrated into the cargo publish workflow. Our goal here is to resolve one of those blockers (cargo manifest linting), and chart a path toward resolving the rest in the future.

The status quo

Work in three major areas is required to resolve the blockers for running cargo-semver-checks as part of cargo publish:

  • Support for cargo manifest linting, and associated CLI changes
  • Checking of cross-crate items
  • SemVer linting of type information

Fully resolving all three areas is likely a 12-24 month undertaking, and beyond the scope of this goal on its own. Instead, this goal proposes to accomplish intermediate steps that create immediate value for users and derisk the overall endeavor, while needing only “moral support” from the cargo team as its only requirement.

Cargo manifest linting

Package manifests have SemVer obligations: for example, removing a feature name that used to exist is a major breaking change.

Currently, cargo-semver-checks is not able to catch such breaking changes. It only draws information from a package’s rustdoc JSON, which does not include the necessary manifest details and does not have a convincing path to doing so in the future. Design and implementation work is required to allow package manifests to be linted for breaking changes as well.

This “rustdoc JSON only” assumption is baked into the cargo-semver-checks CLI as well, with options such as --baseline-rustdoc and --current-rustdoc that allow users to lint with a pre-built rustdoc JSON file instead of having cargo-semver-checks build the rustdoc JSON itself. Once manifest linting is supported, users of such options will need to somehow specify a Cargo.toml file (and possibly even a matching Cargo.lock) in addition to the rustdoc JSON. Additional work is required to determine how to evolve the CLI to support manifest linting and future-proof it to the level necessary to be suitable for stabilizing as part of cargo’s own CLI.

Checking of cross-crate items

Currently, cargo-semver-checks performs linting by only using the rustdoc JSON of the target package being checked. However, the public API of a package may expose items from other crates. Since rustdoc no longer inlines the definitions of such foreign items into the JSON of the crate whose public API relies on them, cargo-semver-checks cannot see or analyze them.

This causes a massive number of false-positives (“breakage reported incorrectly”) and false-negatives (“lint for issue X fails to spot an instance of issue X”). In excess of 90% of real-world false-positives are traceable back to a cross-crate item, as measured by our SemVer study!

For example, the following change is not breaking but cargo-semver-checks will incorrectly report it as breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example() {}

// in the new release, imagine this function moved to `another_crate`:
pub use another_crate::example;
}

This is because the rustdoc JSON that cargo-semver-checks sees indeed does not contain a function named example. Currently, cargo-semver-checks is incapable of following the cross-crate connection to another_crate, generating its rustdoc JSON, and continuing its analysis there.

Resolving this limitation will require changes to how cargo-semver-checks generates and handles rustdoc JSON, since the set of required rustdoc JSON files will no longer be fully known ahead of time. It will also require CLI changes in the same area as the changes required to support manifest linting.

While there may be other challenges on rustc and rustdoc’s side before this feature could be fully implemented, we consider those out of scope here since there are parallel efforts to resolve them. The goal here is for cargo-semver-checks to have its own story straight and do the best it can.

SemVer linting of type information

Currently, cargo-semver-checks lints cannot represent or examine type information. For example, the following change is breaking but cargo-semver-checks will not detect or report it:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: i64) {}
}

Analogous breaking changes to function return values, struct fields, and associated types would also be missed by cargo-semver-checks today.

The main difficulty here lies with the expressiveness of the Rust type system. For example, none of the following changes are breaking:

#![allow(unused)]
fn main() {
// previous release:
pub fn example(value: String) {}

// new release:
pub fn example(value: impl Into<String>) {}

// subsequent release:
pub fn example<S: Into<String>>(value: S) {}
}

Similar challenges exist with lifetimes, variance, trait solving, async fn versus fn() -> impl Future, etc.

While there are some promising preliminary ideas for resolving this challenge, more in-depth design work is necessary to determine the best path forward.

The next 6 months

Three things:

  • Implement cargo manifest linting
  • Implement CLI future-proofing changes, with manifest linting and cross-crate analysis in mind
  • Flesh out a design for supporting cross-crate analysis and type information linting in the future

The “shiny future” we are working towards

Accidentally publishing SemVer violations that break the ecosystem is never fun for anyone involved.

From a user perspective, we want a fearless cargo update: one’s project should never be broken by updating dependences without changing major versions.

From a maintainer perspective, we want a fearless cargo publish: we want to prevent breakage, not to find out about it when a frustrated user opens a GitHub issue. Just like cargo flags uncommitted changes in the publish flow, it should also quickly and accurately flag breaking changes in non-major releases. Then the maintainer may choose to release a major version instead, or acknowledge and explicitly override the check to proceed with publishing as-is.

To accomplish this, cargo-semver-checks needs the ability to express more kinds of lints (including manifest and type-based ones), eliminate false-positives, and stabilize its public interfaces (e.g. the CLI). At that point, we’ll have lifted the main merge-blockers and we can consider making it a first-party component of cargo itself.

Ownership and team asks

Owner: Predrag Gruevski, as maintainer of cargo-semver-checks

I (Predrag Gruevski) will be working on this effort. The only other resource request would be occasional discussions and moral support from the cargo team, of which I already have the privilege as maintainer of a popular cargo plugin.

TaskOwner(s) or team(s)Notes
Implementation of cargo manifest linting + CLIPredrag Gruevski
Initial design for cross-crate checkingPredrag Gruevski
Initial design for type-checking lintsPredrag Gruevski
Discussion and moral supportTeam cargo

Frequently asked questions

Why not use semverver instead?

Semverver is a prior attempt at enforcing SemVer compliance, but has been deprecated and is no longer developed or maintained. It relied on compiler-internal APIs, which are much more unstable than rustdoc JSON and required much more maintenance to “keep the lights on.” This also meant that semverver required users to install a specific nightly versions that were known to be compatible with their version of semverver.

While cargo-semver-checks relies on rustdoc JSON which is also an unstable nightly-only interface, its changes are much less frequent and less severe. By using the Trustfall query engine, cargo-semver-checks can simultaneously support a range of rustdoc JSON formats (and therefore Rust versions) within the same tool. On the maintenance side, cargo-semver-checks lints are written in a declarative manner that is oblivious to the details of the underlying data format, and do not need to be updated when the rustdoc JSON format changes. This makes maintenance much easier: updating to a new rustdoc JSON format usually requires just a few lines of code, instead of “a few lines of code apiece in each of hundreds of lints.”

Const traits

Metadata
Point of contactDeadbeef
StatusAccepted
Tracking issuerust-lang/rust-project-goals#106
Zulip channel#t-compiler/project-const-traits
Teamslang, types
Task ownersDeadbeef and project-const-traits

Summary

Experiment with effects-based desugaring for “maybe-const” functionality

Motivation

Rust’s compile time functionalities (const fn, consts, etc.) are greatly limited in terms of expressivity because const functions currently do not have access to generic trait bounds as runtime functions do. Developers want to write programs that do complex work in compile time, most of the times to offload work from runtime, and being able to have const traits and const impls will greatly reduce the difficulty of writing such compile time functions.

The status quo

People write a lot of code that will be run in compile time. They include procedural macros, build scripts (42.8k hits on GitHub for build.rs), and const functions/consts (108k hits on GitHub for const fn). Not being able to write const functions with generic behavior is often cited as a pain point of Rust’s compile time capabilities. Because of the limited expressiveness of const fn, people may decide to move some compile time logic to a build script, which could increase build times, or simply choose not to do it in compile time (even though it would have helped runtime performance).

There are also language features that require the use of traits, such as iterating with for and handling errors with ?. Because the Iterator and Try traits currently cannot be used in constant contexts, people are unable to use ? to handle results, nor use iterators e.g. for x in 0..5.

The next six months

In 2024, we plan to:

  • Finish experimenting with an effects-based desugaring for ensuring correctness of const code with trait bounds
  • Land a relatively stable implementation of const traits
  • Make all UI tests pass.

The “shiny future” we are working towards

We’re working towards enabling developers to do more things in general within a const context. Const traits is a blocker for many future possibilities (see also the const eval feature skill tree) including heap operations in const contexts.

Design axioms

None.

Ownership and team asks

Owner: Deadbeef

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams.

  • Subgoal:
    • Describe the work to be done and use to mark “subitems”.
  • Owner(s) or team(s):
    • List the owner for this item (who will do the work) or Help wanted if an owner is needed.
    • If the item is a “team ask” (i.e., approve an RFC), put Team and the team name(s).
  • Status:
    • List Help wanted if there is an owner but they need support, for example funding.
    • Other needs (e.g., complete, in FCP, etc) are also fine.
TaskOwner(s) or team(s)Notes
ImplementationDeadbeef and project-const-traits
Discussion and moral supportTeam types lang

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Stabilize doc_cfg

Metadata
Point of contactGuillaume Gomez
StatusAccepted
Tracking issuerust-lang/rust-project-goals#120
Zulip channelN/A
Teamsrustdoc
Task ownersGuillaume Gomez
Guillaume Gomez: https://github.com/GuillaumeGomez

Motivation

The doc_cfg features would allow to provide more information to crate users reading the documentation.

The status quo

The next six months

  • Merge the RFC.
  • Implement it.
  • Stabilize it.

The “shiny future” we are working towards

Stable support for doc_cfg features.

Design axioms

N/A

Ownership and team asks

Owner: Guillaume Gomez

TaskOwner(s) or team(s)Notes
ImplementationGuillaume Gomez
RFC decisionTeam rustdoc
Standard reviewsTeam rustdoc

Outputs and milestones

Outputs

Milestones

MilestoneExpected date
Merge RFCTBD
Implement RFCTBD
Stabilize the featuresTBD

Frequently asked questions

None yet.

Ergonomic ref-counting

Metadata
Point of contact@jkelleyrtp
StatusAccepted
Tracking issuerust-lang/rust-project-goals#107
Zulip channelN/A
Teamscompiler, lang, libs-api
Task owners@jkelleyrtp, Santiago Pastorino, TBD

Summary

Deliver nightly support some solution to reduce the ergonomic pain of working with ref-counted and cheaply cloneable types.

Motivation

For 2024H2 we propose to improve ergonomics of working with “cheaply cloneable” data, most commonly reference-counted values (Rc or Arc). Like many ergonomic issues, these impact all users, but the impact is particularly severe for newer Rust users, who have not yet learned the workarounds, or those doing higher-level development, where the ergonomics of Rust are being compared against garbage-collected languages like Python, TypeScript, or Swift.

The status quo

Many Rust applications—particularly those in higher-level domains—use reference-counted values to pass around core bits of context that are widely used throughout the program. Reference-counted values have the convenient property that they can be cloned in O(1) time and that these clones are indistinguishable from one another (for example, two handles to a Arc<AtomicInteger> both refer to the same counter). There are also a number of data structures found in the stdlib and ecosystem, such as the persistent collections found in the im crate or the Sender type from std::sync::mpsc and tokio::sync::mpsc, that share this same property.

Rust’s current rules mean that passing around values of these types must be done explicitly, with a call to clone. Transforming common assignments like x = y to x = y.clone() can be tedious but is relatively easy. However, this becomes a much bigger burden with closures, especially move closures (which are common when spawning threads or async tasks). For example, the following closure will consume the state handle, disallowing it from being used in later closures:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);
tokio::spawn(async move { /* code using `state` */ });
}

This scenario can be quite confusing for new users (see e.g. this 2014 talk at StrangeLoop where an experienced developer describes how confusing they found this to be). Many users settle on a workaround where they first clone the variable into a fresh local with a new name, such as:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);

let _state = state.clone();
tokio::spawn(async move { /*code using `_state` */ });

let _state = state.clone();
tokio::spawn(async move { /*code using `_state` */ });
}

Others adopt a slightly different pattern leveraging local variable shadowing:

#![allow(unused)]
fn main() {
let state = Arc::new(some_state);

tokio::spawn({
    let state = state.clone();
    async move { /*code using `state`*/ }
});
}

Whichever pattern users adopt, explicit clones of reference counted values leads to significant accidental complexity for many applications. As noted, cloning these values is both cheap at runtime and has zero semantic importance, since each clone is as good as the other.

Impact on new users and high-level domains

The impact of this kind of friction can be severe. While experienced users have learned the workaround and consider this to be a papercut, new users can find this kind of change bewildering and a total blocker. The impact is also particularly severe on projects attempting to use Rust in domains traditionally considered “high-level” (e.g., app/game/web development, data science, scientific computing). Rust’s strengths have made it a popular choice for building underlying frameworks and libraries that perform reliably and with high performance. However, thanks in large part to these kind of smaller, papercut issues, it is not a great choice for consumption of these libraries

Users in higher-level domains are accustomed to the ergonomics of Python or TypeScript, and hence ergonomic friction can make Rust a non-starter. Those users that stick with Rust long enough to learn the workarounds, however, often find significant value in its emphasis on reliability and long-term maintenance (not to mention performance). Small changes like avoiding explicit clones for reference-counted data can both help to make Rust more appealing in these domains and help Rust in other domains where it is already widespead.

The next six months

The goal for the next six months is to

  • author and accept an RFC that reduces the burden of working with clone, particularly around closures
  • land a prototype nightly implementation.

The “shiny future” we are working towards

This goal is scoped around reducing (or eliminating entirely) the need for explicit clones for reference-counted data. See the FAQ for other potential future work that we are not asking the teams to agree upon now.

Design consensus points

We don’t have consensus around a full set of “design axioms” for this design, but we do have alignment around the following basic points:

  • Explicit ref-counting is a major ergonomic pain point impacting both high- and low-level, performance oriented code.
  • The worst ergonomic pain arises around closures that need to clone their upvars.
  • Some code will want the ability to precisely track reference count increments.
  • The design should allow user-defined types to “opt-in” to the lightweight cloning behavior.

Ownership and team asks

The work here is proposed by @jkelleyrtp on behalf of Dioxus Labs. We have funding for 1-2 engineers depending on the scope of work. Dioxus Labs is willing to take ownership and commit funding to solve these problems.

TaskOwner(s) or team(s)Notes
Overall program management@jkelleyrtp
Author RFCTBD
Design meetingTeam lang2 meetings expected
RFC decisionTeam lang libs-api
Nightly implementationSantiago Pastorino
Standard reviewsTeam compiler
Blog post on Inside Rust
  • The Team badge indicates a requirement where Team support is needed.

Support needed from the project

As owners of this goal…

  • We are happy to author RFCs and/or work with other experienced RFC authors.
  • We are happy to host design meetings, facilitate work streams, logistics, and any other administration required to execute. Some subgoals proposed might be contentious or take longer than this goals period, and we’re committed to timelines beyond six months.
  • We are happy to author code or fund the work for an experienced Rustlang contributor to do the implementation. For the language goals, we expect more design required than actual implementation. For cargo-related goals, we expected more engineering required than design. We are also happy to back any existing efforts as there is ongoing work in cargo itself to add various types of caching.
  • We would be excited to write blog posts about this effort. This goals program is a great avenue for us to get more corporate support and see more Rust adoption for higher-level paradigms. Having a blog post talking about this work would be a significant step in changing the perception of Rust for use in high-level codebases.

The primary project support will be design bandwidth from the [lang team].

Outputs and milestones

Outputs

Final outputs that will be produced

Milestones

Milestones you will reach along the way

Frequently asked questions

After this, are we done? Will high-level Rust be great?

Accepting this goal only implies alignment around reducing (or eliminating entirely) the need for explicit clones for reference-counted data. For people attempting to use Rust as part of higher-level frameworks like Dioxus, this is an important step, but one that would hopefully be followed by further ergonomics work. Examples of language changes that would be helpful are described in the (not accepted) goals around a renewed ergonomics initiative and improve compilation speed.

Implement “merged doctests” to save doctest time

Metadata
Point of contactGuillaume Gomez
StatusAccepted
Tracking issuerust-lang/rust-project-goals#111
Zulip channelN/A
Teamsrustdoc
Task ownersGuillaume Gomez
Guillaume Gomez: https://github.com/GuillaumeGomez

Motivation

Most of the time in doctests is spent in compilation. Merging doctests and compiling them together allows to greatly reduce the overall amount of time.

The status quo

The next six months

  • Finish reviewing the pull request
  • Run crater with the feature enabled by default.
  • Merge it.

The “shiny future” we are working towards

Merged doctests.

Design axioms

N/A

Ownership and team asks

Owner: Guillaume Gomez

TaskOwner(s) or team(s)Notes
ImplementationGuillaume Gomez
Standard reviewsTeam rustdoc

Frequently asked questions

None yet.

“Stabilizable” prototype for expanded const generics

Metadata
Point of contactBoxy
StatusAccepted
Tracking issuerust-lang/rust-project-goals#100
Zulip channel#project-const-generics
Teamslang, types
Task ownersBoxy, Noah Lev, Michael Goulet

Summary

Experiment with a new min_generic_const_args implementation to address challenges found with the existing approach

Motivation

min_const_generics was stabilized with the restriction that const-generic arguments may not use generic parameters other than a bare const parameter, e.g. Foo<N> is legal but not Foo<{ T::ASSOC }>. This restriction is lifted under feature(generic_const_exprs) however its design is fundamentally flawed and introduces significant complexity to the compiler. A ground up rewrite of the feature with a significantly limited scope (e.g. min_generic_const_args) would give a viable path to stabilization and result in large cleanups to the compiler.

The status quo

A large amount of rust users run into the min_const_generics limitation that it is not legal to use generic parameters with const generics. It is generally a bad user experience to hit a wall where a feature is unfinished, and this limitation also prevents patterns that are highly desirable. We have always intended to lift this restriction since stabilizing min_const_generics but we did not know how.

It is possible to use generic parameters with const generics by using feature(generic_const_exprs). Unfortunately this feature has a number of fundamental issues that are hard to solve and as a result is very broken. It being so broken results in two main issues:

  • When users hit a wall with min_const_generics they cannot reach for the generic_const_exprs feature because it is either broken or has no path to stabilization.
  • In the compiler, to work around the fundamental issues with generic_const_exprs, we have a number of hacks which negatively affect the quality of the codebase and the general experience of contributing to the type system.

The next six months

We have a design for min_generic_const_args approach in mind but we want to validate it through implementation as const generics has a history of unforeseen issues showing up during implementation. Therefore we will pursue a prototype implementation in 2024.

As a stretch goal, we will attempt to review the design with the lang team in the form of a design meeting or RFC. Doing so will likely also involve authoring a design retrospective for generic_const_exprs in order to communicate why that design did not work out and why the constraints imposed by min_generic_const_args makes sense.

The “shiny future” we are working towards

The larger goal here is to lift most of the restrictions that const generics currently have:

  • Arbitrary types can be used in const generics instead of just: integers, floats, bool and char.
    • implemented under feature(adt_const_params) and is relatively close to stabilization
  • Generic parameters are allowed to be used in const generic arguments (e.g. Foo<{ <T as Trait>::ASSOC_CONST }>).
  • Users can specify _ as the argument to a const generic, allowing inferring the value just like with types.
    • implemented under feature(generic_arg_infer) and is relatively close to stabilization
  • Associated const items can introduce generic parameters to bring feature parity with type aliases
    • implemented under feature(generic_const_items), needs a bit of work to finish it. Becomes significantly more important after implementing min_generic_const_args
  • Introduce associated const equality bounds, e.g. T: Trait<ASSOC = N> to bring feature parity with associated types
    • implemented under feature(associated_const_equality), blocked on allowing generic parameters in const generic arguments Allowing generic parameters to be used in const generic arguments is the only part of const generics that requires significant amounts of work while also having significant benefit. Everything else is already relatively close to the point of stabilization. I chose to specify this goal to be for implementing min_generic_const_args over “stabilize the easy stuff” as I would like to know whether the implementation of min_generic_const_args will surface constraints on the other features that may not be possible to easily fix in a backwards compatible manner. Regardless I expect these features will still progress while min_generic_const_args is being implemented.

Design axioms

  • Do not block future extensions to const generics
  • It should not feel worse to write type system logic with const generics compared to type generics
  • Avoid post-monomorphization errors
  • The “minimal” subset should not feel arbitrary

Ownership and team asks

Owner: Boxy, project-const-generics lead, T-types member

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams.

  • Subgoal:
    • Describe the work to be done and use to mark “subitems”.
  • Owner(s) or team(s):
    • List the owner for this item (who will do the work) or Help wanted if an owner is needed.
    • If the item is a “team ask” (i.e., approve an RFC), put Team and the team name(s).
  • Status:
    • List Help wanted if there is an owner but they need support, for example funding.
    • Other needs (e.g., complete, in FCP, etc) are also fine.
TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam lang types
Implementation and mentoringBoxy
ImplementationNoah Lev
ReviewerMichael Goulet

Outputs and milestones

Outputs

  • A sound, fully implemented feature(min_generic_const_args) available on nightly
  • All issues with generic_const_exprs’s design have been comprehensively documented (stretch goal)
  • RFC for min_generic_const_args’s design (stretch goal)

Milestones

  • Prerequisite refactorings for min_generic_const_args have taken place
  • Initial implementation of min_generic_const_args lands and is useable on nightly
  • All known issues are resolved with min_generic_const_args
  • Document detailing generic_const_exprs issues
  • RFC is written and filed for min_generic_const_args

Frequently asked questions

Do you expect min_generic_const_args to be stabilized by the end?

No. The feature should be fully implemented such that it does not need any more work to make it ready for stabilization, however I do not intend to actually set the goal of stabilizing it as it may wind up blocked on the new trait solver being stable first.

Next-generation trait solver

Metadata
Point of contactlcnr
StatusAccepted
Tracking issuerust-lang/rust-project-goals#113
Zulip channel#t-types/trait-system-refactor
Teamsrust-analyzer, types
Task ownersMichael Goulet, lcnr, TBD, owner and others

Summary

In the next 6 months we plan to extend the next-generation trait solver as follows:

  • stabilize the use of the next-generation trait solver in coherence checking
  • use the new implementation in rustdoc and lints where applicable
  • share the solver with rust-analyser
  • successfully bootstrap the compiler when exclusively using the new implementation and run crater

Motivation

The existing trait system implementation has many bugs, inefficiencies and rough corners which require major changes to its implementation. To fix existing unsound issues, accommodate future improvements, and to improve compile times, we are reimplementing the core trait solver to replace the existing implementations of select and fulfill.

The status quo

There are multiple type system unsoundnesses blocked on the next-generation trait solver: project board. Desirable features such as coinductive trait semantics and perfect derive, where-bounds on binders, and better handling of higher-ranked bounds and types are also stalled due to shortcomings of the existing implementation.

Fixing these issues in the existing implementation is prohibitively difficult as the required changes are interconnected and require major changes to the underlying structure of the trait solver. The Types Team therefore decided to rewrite the trait solver in-tree, and has been working on it since EOY 2022.

The next six months

  • stabilize the use of the next-generation trait solver in coherence checking
  • use the new implementation in rustdoc and lints where applicable
  • share the solver with rust-analyser
  • successfully bootstrap the compiler when exclusively using the new implementation and run crater

The “shiny future” we are working towards

  • we are able to remove the existing trait solver implementation and significantly cleanup the type system in general, e.g. removing most normalize in the caller by handling unnormalized types in the trait system
  • all remaining type system unsoundnesses are fixed
  • many future type system improvements are unblocked and get implemented
  • the type system is more performant, resulting in better compile times

Design axioms

In order of importance, the next-generation trait solver should be:

  • sound: the new trait solver is sound and its design enables us to fix all known type system unsoundnesses
  • backwards-compatible: the breakage caused by the switch to the new solver should be minimal
  • maintainable: the implementation is maintainable, extensible, and approachable to new contributors
  • performant: the implementation is efficient, improving compile-times

Ownership and team asks

Owner: lcnr

Add’l implementation work: Michael Goulet

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam types

Stabilize next-generation solver in coherence

TaskOwner(s) or team(s)Notes
Implementationlcnr, Michael Goulet
Standard reviewsTeam types
Standard reviewsTeam rust-analyzer
Stabilization decisionTeam types

Support next-generation solver in rust-analyzer

TaskOwner(s) or team(s)Notes
Implementation (library side)owner and others
Implementation (rust-analyzer side)TBD
Standard reviewsTeam types
Standard reviewsTeam rust-analyzer

Support needed from the project

  • Types team
    • review design decisions
    • provide technical feedback and suggestion
  • rust-analyzer team
    • contribute to integration in Rust Analyzer
    • provide technical feedback to the design of the API

Outputs and milestones

See next few steps :3

Outputs

Milestones

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Optimizing Clippy & linting

(a.k.a The Clippy Performance Project)

Metadata
Point of contactAlejandra González
StatusAccepted
Tracking issuerust-lang/rust-project-goals#114
Zulip channelN/A
Teamsclippy
Task ownersAlex Macleod, Alejandra González

Summary

This is the formalization and documentation of the Clippy Performance Project, a project first talked about on Zulip, July 2023. As the project consists of several points and is ever-changing, this document also has a dynamic structure and the team can add points.

In short, this is an effort to optimize Clippy, and Rust’s linting infrastructure with a point of view of making Clippy faster (both on CI/CD pipelines, and on devs’ machines)

Motivation

Clippy can take up to 2.5 times the time that a normal cargo check takes, and it doesn’t need to be! Taking so long is expensive both in development time, and in real money.

The status quo

Based on some informal feedback [polls][poll-mastodon], it’s clear that Clippy is used in lots of different contexts. Both in developer’s IDEs and outside them.

The usage for IDEs is not as smooth as one may desire or expect when comparing to prior art like [Prettier][prettier], [Ruff][ruff], or other tools in the Rust ecosystem rustfmt and Rust-analyzer.

The other big use-case is as a test before committing or on CI. Optimizing Clippy for performance would fold the cost of these tests.

On GitHub Actions, this excessive time can equal the cost of running cargo check on a Linux x64 32-cores machine, instead of a Linux x64 2-cores machine. A 3.3x cost increase.

The next 6 months

In order to achieve a better performance we want to:

  • Keep working on, and eventually merge rust#125116
  • Improve of checking on proc-macros & expansions, maybe by precomputing expanded spans or memoizing the checking functions.
  • Optimize checking for MSRVs and #[clippy::msrv] attributes. (Probably using static values, precomputing MSRV spans?)
  • Migrate applicable lints to use incremental compilation

Apart from these 4 clear goals, any open issue, open PR or merged PRs with the label performance-project are a great benefit.

The “shiny future” we are working towards

The possible outcome would be a system that can be run on-save without being a hassle to the developer, and that has the minimum possible overhead over cargo check (which, would also be optimized as a side of a lot of a subset of the optimizations).

A developer shouldn’t have to get a high-end machine to run a compiler swiftly; and a server should not spend more valuable seconds on linting than strictly necessary.

Ownership and team asks

Owner: Alejandra Gonzalez, a.k.a. Alejandra González

TaskOwner(s) or team(s)Notes
ImplementationAlejandra González, Alex Macleod
Standard reviewsTeam clippy

Frequently Asked Questions

[poll-mastodon]: https://tech.lgbt/Alejandra González/112747808297589676 [prettier]: https://github.com/prettier/prettier [ruff]: https://github.com/astral-sh/ruff

Stabilize parallel front end

Metadata
Point of contactSparrow Li
StatusAccepted
Tracking issuerust-lang/rust-project-goals#121
Zulip channel#t-compiler/wg-parallel-rustc
Teamscompiler
Task ownersSparrow Li

Summary

We will move rustc’s support for parallel front end closer to stability by resolving ICE and deadlock issues, completing the test suite for multithreaded scenario and integrating parallel front end into bootstrap. This fits into our larger goal of improving rustc build times by 20% by leveraging multiple cores and enhance its robustness.

Motivation

The parallel front end has been implemented in nightly, but there are still many problems that prevent it from being stable and used at scale.

The status quo

Many current issues reflect ICE or deadlock problems that occur during the use of parallel front end. We need to resolve these issues to enhance its robustness.

The existing compiler testing framework is not sufficient for the parallel front end, and we need to enhance it to ensure the correct functionality of the parallel front end.

The current parallel front end still has room for further improvement in compilation performance, such as parallelization of HIR lowering and macro expansion, and reduction of data contention under more threads (>= 16).

We can use parallel front end in bootstrap to alleviate the problem of slow build of the whole project.

Cargo does not provide an option to enable the use of parallel front end, so it can only be enabled by passing rustc options manually.

The next 6 months

  • Solve ICE and deadlock issues (unless they are due to lack of rare hardware environment or are almost impossible to reproduce).
  • Improve the parallel compilation test framework and enable parallel front end in UI tests.
  • Enable parallel frontends in bootstrap.
  • Continue to improve parallel compilation performance, with the average speed increase from 20% to 25% under 8 cores and 8 threads.
  • Communicate with Cargo team on the solution and plan to support parallel front end.

The “shiny future” we are working towards

The existing rayon library implementation is difficult to fundamentally eliminate the deadlock problem, so we may need a better scheduling design to eliminate deadlock without affecting performance.

The current compilation process with GlobalContext as the core of data storage is not very friendly to parallel front end. Maybe try to reduce the granularity (such as modules) to reduce data competition under more threads and improve performance.

Design axioms

The parallel front end should be:

  • safe: Ensure the safe and correct execution of the compilation process
  • consistent: The compilation result should be consistent with that in single thread
  • maintainable: The implementation should be easy to maintain and extend, and not cause confusion to developers who are not familiar with it.

Ownership and team asks

Owner: Sparrow Li and Parallel Rustc WG own this goal

TaskOwner(s) or team(s)Notes
ImplementationSparrow Li
Author testsSparrow Li
Discussion and moral supportTeam compiler

Frequently asked questions

Extend pubgrub to match cargo’s dependency resolution

Metadata
Point of contactJacob Finkelman
StatusAccepted
Tracking issuerust-lang/rust-project-goals#110
Zulip channelN/A
Teamscargo
Task ownerseh2046

Summary

Implement a standalone library based on pubgrub that model’s cargo dependency resolution and validate its accurate with testing against crates found on crates.io. This lays the groundwork for improved cargo error messages, extensions for hotly requested features (e.g., better MSRV support, CVE-aware resolution, etc), and support for a richer ecosystem of cargo extensions.

Motivation

Cargo’s dependency resolver is brittle and under-tested. Disentangling implementation details, performance optimizations, and user-facing functionality will require a rewrite. Making the resolver a standalone modular library will make it easier to test and maintain.

The status quo

Big changes are required in cargo’s resolver: there is lots of new functionality that will require changes to the resolver and the existing resolver’s error messages are terrible. Cargo’s dependency resolver solves the NP-Hard problem of taking a list of direct dependencies and an index of all available crates and returning an exact list of versions that should be built. This functionality is exposed in cargo’s CLI interface as generating/updating a lock file. Nonetheless, any change to the current resolver in situ is extremely treacherous. Because the problem is NP-Hard it is not easy to tell what code changes break load-bearing performance or correctness guarantees. It is difficult to abstract and separate the existing resolver from the code base, because the current resolver relies on concrete datatypes from other modules in cargo to determine if a set of versions have any of the many ways two crate versions can be incompatible.

The next six months

Develop a standalone library for doing dependency resolution with all the functionality already supported by cargo’s resolver. Extensively test this library to ensure maximum compatibility with existing behavior. Prepare for experimental use of this library inside cargo.

The “shiny future” we are working towards

Eventually we should replace the existing entangled resolver in cargo with one based on separately maintained libraries. These libraries would provide simpler and isolated testing environments to ensure that correctness is maintained. Cargo plugins that want to control or understand what lock file cargo uses can interact with these libraries directly without interacting with the rest of cargo’s internals.

Design axioms

  • Correct: The new resolver must perform dependency resolution correctly, which generally means matching the behavior of the existing resolver, and switching to it must not break Rust projects.
  • Complete output: The output from the new resolver should be demonstrably correct. There should be enough information associated with the output to determine that it made the right decision.
  • Modular: There should be a stack of abstractions, each one of which can be understood, tested, and improved on its own without requiring complete knowledge of the entire stack from the smallest implementation details to the largest overall use cases.
  • Fast: The resolver can be a slow part of people’s workflow. Overall performance must be a high priority and a focus.

Ownership and team asks

Owner: Jacob Finkelman will own and lead the effort.

I (Jacob Finkelman) will be working full time on this effort. I am a member of the Cargo Team and a maintainer of pubgrub-rs.

Integrating the new resolver into Cargo and reaching the shiny future will require extensive collaboration and review from the Cargo Team. However, the next milestones involve independent work exhaustively searching for differences in behavior between the new and old resolvers and fixing them. So only occasional consultation-level conversations will be needed during this proposal.

TaskOwner(s) or team(s)Notes
Implementation work on pubgrub libraryeh2046
Discussion and moral supportTeam cargo

Outputs

Standalone crates for independent components of cargo’s resolver. We have already developed https://github.com/pubgrub-rs/pubgrub for solving the core of dependency resolution and https://github.com/pubgrub-rs/semver-pubgrub for doing mathematical set operations on Semver requirements. The shiny future will involve several more crates, although their exact borders have not yet been determined. Eventually we will also be delivering a -Z pubgrub for testing the new resolver in cargo itself.

Milestones

For all crate versions on crates.io the two resolvers agree about whether there is a solution.

Build a tool that will look at the index from crates.io and for each version of each crate, make a resolution problem out of resolving the dependencies. This tool will save off an independent test case for each time pubgrub and cargo disagree about whether there is a solution. This will not check if the resulting lock files are the same or even compatible, just whether they agree that a lock file is possible. Even this crude comparison will find many bugs in how the problem is presented to pubgrub. This is known for sure, because this milestone has already been achieved.

For all crate versions on crates.io the two resolvers accept the other one’s solution.

The tool from previous milestone will be extended to make sure that the lock file generated by pubgrub can be accepted by cargo’s resolver and vice versa. How long will this take? What will this find? No way to know. To quote FractalFir “If I knew where / how many bugs there are, I would have fixed them already. So, providing any concrete timeline is difficult.”

For all crate versions on crates.io the performance is acceptable.

There are some crates where pubgrub takes a long time to do resolution, and many more where pubgrub takes longer than cargo’s existing resolver. Investigate each of these cases and figure out if performance can be improved either by improvements to the underlying pubgrub algorithm or the way the problem is presented to pubgrub.

Frequently asked questions

If the existing resolver defines correct behavior then how does a rewrite help?

Unless we find critical bugs with the existing resolver, the new resolver and cargo’s resolver should be 100% compatible. This means that any observable behavior from the existing resolver will need to be matched in the new resolver. The benefits of this work will come not from changes in behavior, but from a more flexible, reusable, testable, and maintainable code base. For example: the base pubgrub crate solves a simpler version of the dependency resolution problem. This allows for a more structured internal algorithm which enables complete error messages. It’s also general enough not only to be used in cargo but also in other package managers. We already have contributions from the maintainers of uv who are using the library in production.

Resolve the biggest blockers to Linux building on stable Rust

Metadata
Short titleRust-for-Linux
Point of contactNiko Matsakis
StatusAccepted
FlagshipYes
Tracking issuerust-lang/rust-project-goals#116
Zulip channel#rust-for-linux
Teamscompiler, lang
Task ownersAlice Ryhl, Ding Xiang Fei, Josh Triplett, Niko Matsakis, lang

Summary

Stabilize unstable features required by Rust for Linux project including

  • Stable support for RFL’s customized ARC type
  • Labeled goto in inline assembler and extended offset_of! support
  • RFL on Rust CI
  • Pointers to statics in constants

Motivation

The experimental support for Rust development in the Linux kernel is a watershed moment for Rust, demonstrating to the world that Rust is indeed capable of targeting all manner of low-level systems applications. And yet today that support rests on a number of unstable features, blocking the effort from ever going beyond experimental status. For 2024H2 we will work to close the largest gaps that block support.

The status quo

The Rust For Linux (RFL) project has been accepted into the Linux kernel in experimental status. The project’s goal, as described in the Kernel RFC introducing it, is to add support for authoring kernel components (modules, subsystems) using Rust. Rust would join C as the only two languages permitted in the linux kernel. This is a very exciting milestone for Rust, but it’s also a big challenge.

Integrating Rust into the Linux kernel means that Rust must be able to interoperate with the kernel’s low-level C primitives for things like locking, linked lists, allocation, and so forth. This interop requires Rust to expose low-level capabilities that don’t currently have stable interfaces.

The dependency on unstable features is the biggest blocker to Rust exiting “experimental” status. Because unstable features have no kind of reliability guarantee, this in turn means that RFL can only be built with a specific, pinned version of the Rust compiler. This is a challenge for distributions which wish to be able to build a range of kernel sources with the same compiler, rather than having to select a particular toolchain for a particular kernel version.

Longer term, having Rust in the Linux kernel is an opportunity to expose more C developers to the benefits of using Rust. But that exposure can go both ways. If Rust is constantly causing pain related to toolchain instability, or if Rust isn’t able to interact gracefully with the kernel’s data structures, kernel developers may have a bad first impression that causes them to write off Rust altogether. We wish to avoid that outcome. And besides, the Linux kernel is exactly the sort of low-level systems application we want Rust to be great for!

For deeper background, please refer to these materials:

The next six months

The RFL project has a tracking issue listing the unstable features that they rely upon. After discussion with the RFL team, we identified the following subgoals as the ones most urgent to address in 2024. Closing these issues gets us within striking distance of being able to build the RFL codebase on stable Rust.

  • Stable support for RFL’s customized ARC type
  • Labeled goto in inline assembler and extended offset_of! support
  • RFL on Rust CI ([done now!])
  • Pointers to statics in constants

Stable support for RFL’s customized ARC type

One of Rust’s great features is that it doesn’t “bake in” the set of pointer types. The common types users use every day, such as Box, Rc, and Arc, are all (in principle) library defined. But in reality those types enjoy access to some unstable features that let them be used more widely and ergonomically. Since few users wish to define their own smart pointer types, this is rarely an issue and there has been relative little pressure to stabilize those mechanisms.

The RFL project needs to integrate with the Kernel’s existing reference counting types and intrusive linked lists. To achieve these goals they’ve created their own variant of Arc (hereafter denoted as rfl::Arc), but this type cannot be used as idiomatically as the Arc type found in libstd without two features:

  • The ability to be used in methods (e.g., self: rfl::Arc<Self>), aka “arbitrary self types”, specified in RFC #3519.
  • The ability to be coerce to dyn types like rfl::Arc<dyn Trait> and then support invoking methods on Trait through dynamic dispatch.
    • This requires the use of two unstable traits, CoerceUnsized and DynDispatch, neither of which are close to stabilization.
    • However, RFC #3621 provides for a “shortcut” – a stable interface using derive that expands to those traits, leaving room to evolve the underlying details.

Our goal for 2024 is to close those gaps, most likely by implementing and stabilizing RFC #3519 and RFC #3621.

Labeled goto in inline assembler and extended offset_of! support

These are two smaller extensions required by the Rust-for-Linux kernel support. Both have been implemented but more experience and/or development may be needed before stabilization is accepted.

RFL on Rust CI

Update: Basic work was completed in PR #125209 by Jakub Beránek during the planning process! We are however still including a team ask of T-compiler to make sure we have agreed around the policy regarding breakage due to unstable features.

Rust sometimes integrates external projects of particular importance or interest into its CI. This gives us early notice when changes to the compiler or stdlib impact that project. Some of that breakage is accidental, and CI integration ensures we can fix it without the project ever being impacted. Otherwise the breakage is intentional, and this gives us an early way to notify the project so they can get ahead of it.

Because of the potential to slow velocity and incur extra work, the bar for being integrated into CI is high, but we believe that Rust For Linux meets that bar. Given that RFL would not be the first such project to be integrated into CI, part of pursuing this goal should be establishing clearer policies on when and how we integrate external projects into our CI, as we now have enough examples to generalize somewhat.

Pointers to statics in constants

The RFL project has a need to create vtables in read-only memory (unique address not required). The current implementation relies on the const_mut_refs and const_refs_to_static features (representative example). Discussion has identified some questions that need to be resolved but no major blockers.

The “shiny future” we are working towards

The ultimate goal is to enable smooth and ergonomic interop between Rust and the Linux kernel’s idiomatic data structures.

In addition to the work listed above, there are a few other obvious items that the Rust For Linux project needs. If we can find owners for these this year, we could even get them done as a “stretch goal”:

Stable sanitizer support

Support for building and using sanitizers, in particular KASAN.

Custom builds of core/alloc with specialized configuration options

The RFL project builds the stdlib with a number of configuration options to eliminate undesired aspects of libcore (listed in RFL#2). They need a standard way to build a custom version of core as well as agreement on the options that the kernel will continue using.

Code-generation features and compiler options

The RFL project requires various code-generation options. Some of these are related to custom features of the kernel, such as X18 support (rust-lang/compiler-team#748) but others are codegen options like sanitizers and the like. Some subset of the options listed on RFL#2 will need to be stabilized to support being built with all required configurations, but working out the precise set will require more effort.

Ergonomic improvements

Looking further afield, possible future work includes more ergonomic versions of the special patterns for safe pinned initialization or a solution to custom field projection for pinned types or other smart pointers.

Design axioms

  • First, do no harm. If we want to make a good first impression on kernel developers, the minimum we can do is fit comfortably within their existing workflows so that people not using Rust don’t have to do extra work to support it. So long as Linux relies on unstable features, users will have to ensure they have the correct version of Rust installed, which means imposing labor on all Kernel developers.
  • Don’t let perfect be the enemy of good. The primary goal is to offer stable support for the particular use cases that the Linux kernel requires. Wherever possible we aim to stabilize features completely, but if necessary, we can try to stabilize a subset of functionality that meets the kernel developers’ needs while leaving other aspects unstable.

Ownership and team asks

Here is a detailed list of the work to be done and who is expected to do it. This table includes the work to be done by owners and the work to be done by Rust teams (subject to approval by the team in an RFC/FCP).

  • The Team badge indicates a requirement where Team support is needed.
TaskOwner(s) or team(s)Notes
Overall program managementNiko Matsakis, Josh Triplett

Arbitrary self types v2

TaskOwner(s) or team(s)Notes
author RFCComplete RFC #3519
RFC decisionlangComplete
Implementation
Standard reviewsTeam compiler
Stabilization decisionTeam lang

Derive smart pointer

TaskOwner(s) or team(s)Notes
author RFCRFC #3621
RFC decisionTeam langComplete
ImplementationDing Xiang Fei
Author stabilization reportDing Xiang Fei
Stabilization decisionTeam lang

asm_goto

TaskOwner(s) or team(s)Notes
implementationComplete
Real-world usage in Linux kernelAlice Ryhl
Extend to cover full RFC
Author stabilization report
Stabilization decisionTeam lang

RFL on Rust CI

TaskOwner(s) or team(s)Notes
implementationComplete #125209
Policy draft
Policy decisionTeam compiler

Pointers to static in constants

TaskOwner(s) or team(s)Notes
Stabilization report
Stabilization decisionTeam lang

Support needed from the project

  • Lang team:
    • Prioritize RFC and any related design questions (e.g., the unresolved questions)

Outputs and milestones

Outputs

Final outputs that will be produced

Milestones

Milestones you will reach along the way

Frequently asked questions

None yet.

Make Rustdoc Search easier to learn

Metadata
Point of contactMichael Howell
StatusAccepted
Tracking issuerust-lang/rust-project-goals#112
Zulip channelN/A
Teamsrustdoc, rustdoc-frontend
Task ownersMichael Howell

Summary

To make rustdoc’s search engine more useful:

  • Respond to some existing feedback.
  • Write blog and forum posts to advertise these new features to the larger community, and seek out feedback to continue the progress.

Motivation

Rustdoc Search is going to be some people’s primary resource for finding things. There are a few reasons for this:

  • It’s available. Away from the computer and trying to help someone else out from a smartphone? Evaluating Rust before you install anything? Rustdoc outputs web pages, so you can still use it.
  • If you have a pretty good idea of what you’re looking for, it’s way better than a general search engine. It offers structured features based on Rust, like type-driven search and crate filtering, that aren’t available in DuckDuckGo because it doesn’t know about them.

The status quo

Unfortunately, while most people know it exists, they don’t know about most of what it can do. A lot of people literally ask “Does Rust have anything like Hoogle?”, and they don’t know that it’s already there. We’ve had other people who didn’t see the tab bar, and it doesn’t seem like people look under the ? button, either.

Part of the problem is that they just never try.

@Deleted User: I’d never used the search bar inside the docs before
@Deleted User: It’s because usually the searches inside all of the sites are pretty broken & useless
@Deleted User: but this site is cool. docs are very well written and search is fast, concise…

Mostly, we’ve got a discoverability problem.

The next 6 months

  • Implement a feature to show type signatures in type-driven search results, so it’s easier to figure out why a result came up https://github.com/rust-lang/rust/pull/124544.
    • When unintuitive results come up, respond by either changing the algorithm or changing the way it’s presented to help it make sense.
    • Do we need to do something to make levenshtein matches more obvious?
  • Seek out user feedback on Internals.

Popular stuff should just be made to work, and what’s already there can be made more obvious with education and good UI design.

The “shiny future” we are working towards

Rustdoc Search should be a quick, natural way to find things in your dependencies.

Design axioms

The goal is to reach this point without trying to be a better Google than Google is. Rustdoc Search should focus on what it can do that other search engines can’t:

  • Rustdoc Search is not magic, and it doesn’t have to be.
    • A single crate, or even a single dependency tree, isn’t that big. Extremely fancy techniques—beyond simple database sharding and data structures like bloom filters or tries—aren’t needed.
    • If you’ve already added a crate as a dependency or opened its page on docs.rs, there’s no point in trying to exploit it with SEO spam (the crate is already on the other side of the airtight hatchway).
    • Rustdoc is completely open source. There are no secret anti-spam filters. Because it only searches a limited set of pre-screened crates (usually just one), it will never need them.
  • Rustdoc knows the Rust language. It can, and should, offer structured search to build on that.

Ownership and team asks

Owner: Michael Howell

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam rustdoc
Implementation: show type signature in SERPMichael Howell
Implementation: tweak search algoMichael Howell
Standard reviewsTeam rustdoc-frontend
Design meetingTeam rustdoc-frontend
FCP decision(s)Team rustdoc-frontend
Feedback and testing

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Author RFC and Implementation means actually writing the code, document, whatever.
  • Design meeting means holding a synchronous meeting to review a proposal and provide feedback (no decision expected).
  • RFC decisions means reviewing an RFC and deciding whether to accept.
  • Org decisions means reaching a decision on an organizational or policy matter.
  • Secondary review of an RFC means that the team is “tangentially” involved in the RFC and should be expected to briefly review.
  • Stabilizations means reviewing a stabilization and report and deciding whether to stabilize.
  • Standard reviews refers to reviews for PRs against the repository; these PRs are not expected to be unduly large or complicated.
  • Prioritized nominations refers to prioritized lang-team response to nominated issues, with the expectation that there will be some response from the next weekly triage meeting.
  • Dedicated review means identifying an individual (or group of individuals) who will review the changes, as they’re expected to require significant context.
  • Other kinds of decisions:
    • Lang team experiments are used to add nightly features that do not yet have an RFC. They are limited to trusted contributors and are used to resolve design details such that an RFC can be written.
    • Compiler Major Change Proposal (MCP) is used to propose a ‘larger than average’ change and get feedback from the compiler team.
    • Library API Change Proposal (ACP) describes a change to the standard library.

Frequently asked questions

Search over all of the crates when?

Docs.rs can do it if they want, but Michael Howell isn’t signing up for a full-time job dealing with SEO bad actors.

Full-text search when?

That path is pretty rough. Bugs, enormous size, and contentious decisions on how to handle synonyms abound.

Explore sandboxed build scripts

Metadata
Point of contactWeihang Lo
StatusAccepted
Tracking issuerust-lang/rust-project-goals#108
Zulip channelN/A
Teamscargo, compiler
Task ownersHelp wanted, Weihang Lo

Summary

Explore different strategies for sandboxing build script executions in Cargo.

Motivation

Cargo users can opt-in to run build scripts in a sandboxed environment, limiting their access to OS resources like the file system and network. By providing a sandboxed environment for build script executions, fewer repetitive code scrutinies are needed. The execution of a build script also becomes more deterministic, helping the caching story for the ecosystem in the long run.

The status quo

Build scripts in Cargo can do literally anything from network requests to executing arbitrary binaries. This isn’t deemed a security issue as it is “by design”. Unfortunately, this “by design” virtue relies on trust among developers within the community. When trust is broken by some incidents, even just once, the community has no choice but to intensively review build scripts in their dependencies.

Although there are collaborative code review tools like cargo-vet and cargo-crev to help build trust, comprehensive review is still impractical, especially considering the pace of new version releases. In Rust, the unsafe keyword helps reviewers identify code sections that require extra scrutiny. However, an unsandboxed build script is effectively an enormous unsafe block, making comprehensive review impractical for the community.

Besides the security and trust issues, in an unsandboxed build script, random network or file system access may occur and fail. These kinds of “side effects” are notoriously non-deterministic, and usually cause retries and rebuilds in build pipelines. Because the build is not deterministic, reproducibility cannot be easily achieved, making programs harder to trace and debug.

There is one 2024 GSoC project “Sandboxed and Deterministic Proc Macro using Wasm” experimenting with the possibility of using WebAssembly to sandbox procedural macros. While build scripts and proc-macros are different concepts at different levels, they share the same flaw — arbitrary code execution. Given that we already have experiments on the proc-macros side, it’s better we start some groundwork on build scripts in parallel, and discuss the potential common interface for Cargo to configure them.

The next 6 months

  • Look at prior art in this domain, especially for potential blockers and challenges.
  • Prototype on sandboxing build scripts. Currently looking at WebAssembly System Interface (WASI) and Cackle.
  • Provide a way to opt-in sandboxed build scripts for Cargo packages, and design a configurable interface to grant permissions to each crate.
  • Based on the results of those experiments, consider whether the implementation should be a third-party Cargo plugin first, or make it into Cargo as an unstable feature (with a proper RFC).

The “shiny future” we are working towards

These could become future goals if this one succeeds:

  • The sandboxed build script feature will be opted-in at first when stabilized. By the next Edition, sandboxed build scripts will be on by default, hardening the supply chain security.
  • Cargo users only need to learn one interface for both sandboxed proc-macros and build scripts. The configuration for build scripts will also cover the needs for sandboxed proc-macros,
  • Crates.io and the cargo info command display the permission requirements of a crate, helping developers choose packages based on different security level needs.
  • The runtime of the sandbox environment is swappable, enabling the potential support of remote execution without waiting for a first-party solution. It also opens a door to hermetic builds.

Design axioms

In order of importance, a sandboxed build script feature should provide the following properties:

  • Restrict runtime file system and network access, as well as process spawning, unless allowed explicitly.
  • Cross-platform supports. Cargo is guaranteed to work on tier 1 platforms. This is not a must have for experiments, but is a requirement for stabilization.
  • Ensure -sys crates can be built within the sandbox. Probing and building from system libraries is the major use case of build scripts. We should support it as a first-class citizen.
  • Declarative configuration interface to grant permissions to packages. A declarative configuration helps us analyze permissions granted more easily, without running the actual code.
  • Don’t block the build when the sandboxed feature is off. The crates.io ecosystem shouldn’t rely on the interface to successfully build things. That would hurt the integration with other external build systems. It should work as if it is an extra layer of security scanning.
  • Room for supporting different sandbox runtimes and strategies. This is for easier integration into external build systems, as well as faster iteration for experimenting with new ideas.

Currently out of scope:

  • Terminal user interface.
  • Pre-built build script binaries.
  • Hermetic builds, though this extension should be considered.
  • Support for all tier 2 with-host-tools platforms. As an experiment, we follow what the chosen sandbox runtime provides us.
  • On-par build times. The build time is expected to be impacted because build script artifacts are going to build for the sandbox runtime. This prevents an optimization that when “host” and “target” platforms are the same, Cargo tries to share artifacts between build scripts and applications.

Ownership and team asks

Owner: Weihang Lo, though I also welcome someone else to take ownership of it. I would be happy to support them as a Cargo maintainer.

TaskOwner(s) or team(s)Notes
DesignWeihang Lo(or mentee)
Discussion and moral supportTeam cargo
Security reviewsHelp wanted
Standard reviewsTeam cargo
MiscellaneousTeam compilerCollaboration with GSoC proc-macro project
Summary of experiments or RFCWeihang Lo(or mentee)

For security reviews, I’d like assistance from experts in security domains. Ideally those experts would be from within the community, such as the Security Response or Secure Code working groups. However, I don’t want to pressure that goal since comprehensive security reviews are extremely time-consuming. Outside experts are also welcome.

Outputs and milestones

Outputs

As the work here is mostly experiments and prototyping, based on the results, the outputs could be:

  • A report about why these methods have failed to provide a proper sandboxed environment for build scripts in Cargo, plus some other areas worth exploring in the future.
  • A configurable sandboxed environment for build scripts landed as an unstable feature in Cargo, or provided via crates.io as a third-party plugin for faster experimenting iteration.
  • An RFC proposing a sandboxed build script design to the Rust project.

Milestones

MilestoneExpected Date
Summarize the prior art for sandbox strategies2024-07
Prototype a basic sandboxed build script implementation2024-08
Draft a configurable interface in Cargo.toml2024-10
Integrate the configurable interface with the prototype2024-12
Ask some security experts for reviewing the designTBD
Write an RFC summary for the entire prototyping processTBD

Frequently asked questions

Q: Why can’t build script be removed?

The Rust crates.io ecosystem depends heavily on build scripts. Some foundational packages use build scripts for essential tasks, such as linking to C dependencies. If we shut down this option without providing an alternative, half of the ecosystem would collapse.

That is to say, build script is a feature included in the stability guarantee that we cannot simply remove, just like the results of the dependency resolution Cargo produces.

Q: Why are community tools like cargo-vet and cargo-crev not good enough?

They are all excellent tools. A sandboxed build script isn’t meant to replace any of them. However, as aforementioned, those tools still require intensive human reviews, which are difficult to achieve (cargo-crev has 103 reviewers and 1910 reviews at the time of writing).

A sandboxed build script is a supplement to them. Crate reviews are easier to complete when crates explicitly specify the permissions granted.

Q: What is the difference between sandboxed builds and deterministic builds?

Sandboxing is a strategy that isolates the running process from other resources on a system, such as file system access.

A deterministic build always produces the same output given the same input.

Sandboxing is not a requirement for deterministic builds, and vice versa. However, sandboxing can help deterministic builds because hidden dependencies often come from the system via network or file system access.

Q: Why do we need to build our own solution versus other existing solutions?

External build systems are aware of this situation. For example, Bazel provides a sandboxing feature. Nix also has a sandbox build via a different approach. Yet, migrating to existing solutions will be a long-term effort for the entire community. It requires extensive exploration and discussions from both social and technical aspects. At this moment, I don’t think the Cargo team and the Rust community are ready for a migration.

Survey tools suitability for Std safety verification

Metadata
Point of contactCelina G. Val
StatusAccepted
Tracking issuerust-lang/rust-project-goals#126
Zulip channelN/A
Teamslibs
Task ownersCelina G. Val, @jaisnan, Help Wanted, Own Committee

Summary

Instrument a fork of the standard library (the verify-rust-std repository) with safety contracts, and employ existing verification tools to verify the standard library.

Motivation

The Rust Standard Library is the foundation of portable Rust software. It provides efficient implementations and safe abstractions for the most common general purpose programming data structures and operations. For doing so, they perform unsafe operations internally.

Despite being constantly battle-tested, the implementation of the standard library has not been formally verified or proven safe. A safety issue in the Standard Library may affect almost all Rust applications, and this effort is the first step to enhance the safety guarantees of the Standard Library, hence, the Rust ecosystem.

The status quo

Rust has a very active and diverse formal methods community that has been developing automated or semi-automated verification tools that can further validate Rust code beyond the guarantees provided by the compiler. These tools can complement Rust’s safety guarantees, and allow developers to eliminate bugs and formally prove the correctness of their Rust code.

There are multiple verification techniques, and each have their own strength and limitations. Some tools like Creusot and Prusti can prove correctness of Rust, including generic code, but they cannot reason about unsafe Rust, and they are not fully automated.

On the other hand, tools like Kani and Verus are able to verify unsafe Rust, but they have their own limitations, for example, Kani verification is currently bounded in the presence of loops, and it can only verify monomorphic code, while Verus requires an extended version of the Rust language which is accomplished via macros.

Formal verification tools such as Creusot, Kani, and Verus have demonstrated that it is possible to write verify Rust code that is amenable to automated or semi-automated verification. For example, Kani has been successfully applied to different Rust projects, such as: Firecracker microVM, s2n-quic, and Hifitime.

Applying those techniques to the Standard library will allow us to assess these different verification techniques, identify where all these tools come short, and help us guide research required to address those gaps.

Contract language

Virtually every verification tool has its own contract specification language, which makes it hard to combine tools to verify the same system. Specifying a contract language is outside the scope of this project. However, we plan to adopt the syntax that proposed in this MCP, and keep our fork synchronized with progress made to the compiler contract language, and help assess its suitability for verification.

This will also allow us to contribute back the contracts added to the fork.

Repository Configuration

Most of the work for this project will be developed on the top of the verify-rust-std. This repository has a subtree of the Rust library folder, which is the verification target. We have already integrated Kani in CI, and we are in the process of integrating more tools.

This repository also includes “Challenges”, which are verification problems that we believe are representative of different verification targets in the Standard library. We hope that these challenges will help contributors to narrow down which parts of the standard library they can verify next. New challenges can also be proposed by any contributor.

The next 6 months

First, we will instrument some unsafe functions of the forked Rust Standard Library with function contracts, and safe abstractions with safety type invariants.

Then we will employ existing verification tools to verify that the annotated unsafe functions are in-fact safe as long as its contract pre-conditions are preserved. And we will also check that any post condition is respected. With that, we will work on proving that safe abstractions do not violate any safety contract, and that it does not leak any unsafe value through its public interface.

Type invariants will be employed to verify that unsafe value encapsulation is strong enough to guarantee the safety of the type interface. Any method should be able to assume the type invariant, and it should also preserve the type invariant. Unsafe methods contract must be enough to guarantee that the type invariant is also preserved at the end of the call.

Finally, we hope to contribute upstream contracts and type invariants added to this fork using the experimental contract support proposed in this MCP.

This is open source and very much open to contributions of tools/techniques/solutions. We introduce problems (currently phrased as challenges) that we believe are important to the Rust and verification communities. These problems can be solved by anyone.

The “shiny future” we are working towards

We are working towards the enhancement of Rust verification tools, so it can eventually be incorporated as part of regular Rust development cycle for code that require the usage of unsafe Rust.

The Rust Standard Library is the perfect candidate given its blast radios and its extensive usage of unsafe Rust to provide performant abstractions.

Design axioms

  • No runtime penalty: Instrumentation must not affect the standard library runtime behavior, including performance.
  • Automated Verification: Our goal is to verify the standard library implementation. Given how quickly the standard library code evolves, automated verification is needed to ensure new changes preserve the properties previously verified.
  • Contract as code: Keeping the contract language and specification as close as possible to Rust syntax and semantics will lower the barrier for users to understand and be able to write their own contracts.

Ownership and team asks

Owner: Celina G. Val

TaskOwner(s) or team(s)Notes
Discussion and moral supportTeam libs
Standard reviewsTeam libsWe would like to contribute upstream the contracts added to the fork.
Problem proposalsHelp Wanted
Fork maintenanceCelina G. Val, @jaisnan
Fork PR ReviewsOwn CommitteeWe are gathering a few contributors with expertise knowledge.
Instrumentation and verificationHelp Wanted

Definitions

Definitions for terms used above:

  • Discussion and moral support is the lowest level offering, basically committing the team to nothing but good vibes and general support for this endeavor.
  • Standard reviews refers to reviews for PRs against the Rust repository; these PRs are not expected to be unduly large or complicated.
  • Problem proposals refers to creating a scoped task that involves verifying a chunk of the standard library.
  • Fork PR reviews means a group of individuals who will review the changes made to the fork, as they’re expected to require significant context. Besides contracts, these changes may include extra harnesses, lemmas, ghost-code.
  • Fork maintenance means configuring CI, performing periodic fork update from upstream, tool integration.
  • Instrumentation and verification is the work of specifying contracts, invariants, and verifying a specific part of the standard library.

Frequently asked questions

User-wide build cache

Metadata
Point of contactEd Page
StatusAccepted
Contingent onContributor
Tracking issuerust-lang/rust-project-goals#124
Zulip channelN/A
Teamscargo
Task ownersEd Page, Goal owner

Summary

Extend Cargo’s caching of intermediate artifacts across a workspace to caching them across all workspaces of the user.

Motivation

The primary goal of this effort is to improve build times by reusing builds across projects.

Secondary goals are

  • Reduce disk usage
  • More precise cross-job caching in CI

The status quo

When Cargo performs a build, it will build the package you requested and all dependencies individually, linking them in the end. These build results (intermediate build artifacts) and the linked result (final build artifact) are stored in the target-dir, which is per-workspace by default.

Ways cargo will try to reuse builds today:

  • On a subsequent build, Cargo tries to reuse these build results by “fingerprinting” the inputs to the prior build and checking if that fingerprint has changed.
  • When dependencies are shared by host (build.rs, proc-macros) and platform-target and the platform-target is the host, Cargo will attempt to share host/target builds

Some users try to get extra cache reuse by assigning all workspaces to use the same target-dir.

  • Cross-project conflicts occur because this shares both intermediate (generally unique) and final build artifacts (might not be unique)
  • cargo clean will clear the entire cache for every project
  • Rebuild churn from build inputs, like RUSTFLAGS, that cause a rebuild but aren’t hashed into the file path

In CI, users generally have to declare what directory is should be cached between jobs. This directory will be compressed and uploaded at the end of the job. If the next job’s cache key matches, the tarball will be downloaded and decompressed. If too much is cached, the time for managing the cache can dwarf the benefits of the cache. Some third-party projects exist to help manage cache size.

The next 6 months

Add support for user-wide intermediate artifact caching

  • Re-work target directory so each intermediate artifact is in a self-contained directory
    • Develop and implement transition path for tooling that accesses intermediate artifacts
  • Adjust cargo build to
    • Hash all build inputs into a user-wide hash key
    • If hash key is present, use the artifacts straight from the cache, otherwise build it and put it in the cache
    • Limit this immutable packages (“non-local” in cargo terms, like Registry, git dependencies)
    • Limit this to idempotent packages (can’t depend on proc-macro, can’t have a build.rs)
    • Evaluate risks and determine how we will stabilize this (e.g. unstable to stable, opt-in to opt-out to only on)
  • Track intermediate build artifacts for garbage collection
  • Explore
    • Idempotence opt-ins for build.rs or proc-macros until sandboxing solutions can determine the level of idempotence.
    • a CLI interface for removing anything in the cache that isn’t from this CI job’s build, providing more automatic CI cache management without third-party tools.

Compared to pre-built binaries, this is adaptive to what people use

  • feature flags
  • RUSTFLAGS
  • dependency versions

A risk is that this won’t help as many people as they hope because being able to reuse caches between projects will depend on the exact dependency tree for every intermediate artifact. For example, when building a proc-macro

  • unicode-ident has few releases, so its likely this will get heavy reuse
  • proc-macro2 is has a lot of releases and depends on unicode-ident
  • quote has a lot of releases and depends on proc-macro2 and unicode-ident
  • syn has a lot of releases and depends on proc-macro2, unicode-ident, and optionally on quote

With syn being a very heavy dependency, if it or any of its dependency versions are mismatched between projects, the user won’t get shared builds of syn.

See also cargo#5931.

The “shiny future” we are working towards

The cache lookup will be extended with plugins to read and/or write to different sources. Open source projects and companies can have their CI read from and write to their cache. Individuals who trust the CI can then configure their plugin to read from the CI cache.

A cooperating CI service could provide their own plugin that, instead of caching everything used in the last job and unpacking it in the next, their plugin could download only the entries that will be needed for the current build (e.g. say a dependency changed) and only upload the cache entries that were freshly built. Fine-grained caching like this would save the CI service on bandwidth, storage, and the compute time from copying, decompressing, and compressing the cache. Users would have faster CI time and save money on their CI service, minus any induced demand that faster builds creates.

On a different note, as sandboxing efforts improve, we’ll have precise details on the inputs for build.rs and proc-macros and can gauge when there is idempotence (and verify the opt-in mentioned earlier).

Design axioms

This section is optional, but including design axioms can help you signal how you intend to balance constraints and tradeoffs (e.g., “prefer ease of use over performance” or vice versa). Teams should review the axioms and make sure they agree. Read more about design axioms.

Ownership and team asks

Owner: Identify a specific person or small group of people if possible, else the group that will provide the owner. GitHub user names are commonly used to remove ambiguity.

This section defines the specific work items that are planned and who is expected to do them. It should also include what will be needed from Rust teams. The table below shows some common sets of asks and work, but feel free to adjust it as needed. Every row in the table should either correspond to something done by a contributor or something asked of a team. For items done by a contributor, list the contributor, or ![Heap wanted][] if you don’t yet know who will do it. For things asked of teams, list Team and the name of the team. The things typically asked of teams are defined in the Definitions section below.

TaskOwner(s) or team(s)Notes
ImplementationGoal owner
Standard reviewsTeam cargo
Mentoring and guidanceEd Page
Design meetingTeam cargo

Frequently asked questions

Why not pre-built packages?

Pre-built packages requires guessing

  • CPU Architecture
  • Feature flags
  • RUSTFLAGS
  • Dependency versions

If there are any mismatches there, then the pre-built package can’t be used.

A build cache can be populated with pre-built packages and react to the unique circumstances of the user.

Why not sccache?

Tools like sccache try to infer inputs for hashing a cache key from command-line arguments. This has us reusing the extra knowledge Cargo has to get more accurate cache key generation.

If this is limited to immutable, idempotent packages, is this worth it?

In short, yes.

First, this includes an effort to allow packages to declare themselves as idempotent. Longer term, we’ll have sandboxing to help infer / verify idempotence.

If subtle dependency changes prevent reuse across projects, is this worth it?

In short, yes.

This is a milestone on the way to remote caches. Remote caches allows access to CI build caches for the same project you are developing on, allowing full reuse at the cost of network access.

Provided reasons for yanked crates

Metadata
Point of contact@Rustin170506
StatusAccepted
Tracking issuerust-lang/rust-project-goals#101
Zulip channelN/A
Teamscargo, crates-io
Task owners@Rustin170506

Summary

Over the next 6 months, we will add support to the registry yank API for providing a reason when a crate is yanked. This reason can then be displayed to users. After this feature has been up and running for a while, we’ll open it up to Cargo to support filling in the reason for yanking.

Motivation

When a crate is updated to address a critical issue—such as a fix for a soundness bug or a security vulnerability—it is beneficial to yank previous versions and prompt users to upgrade with a yank reason. Additionally, if a crate is renamed or deprecated, the yank message can provide guidance on the new recommended crate or version. This ensures that users are aware of necessary updates and can maintain the security and stability of their projects.

The status quo

We came up with this need eight years ago, but it was never implemented.

This feature has the following potential use cases:

  1. When a crate is fixed because it will be broken in the next version of the compiler (e.g. a soundness fix or bug fix) then the previous versions can be yanked and nudge users forward.
  2. If a crate is fixed for a security reason, the old versions can be yanked and the new version can be suggested.
  3. If a crate is renamed (or perhaps deprecated) to another then the yank message can indicate what to do in that situation.

Additionally, if we can persist this information to the crates.io index, we can make it available as meta-information to other platforms, such as security platforms like RustSec.

The next 6 months

The primary goal for the next 6 months is to add support to the registry’s yank API.

After that, next steps include (these can be done in many different orders):

  • add support on the browser frontend for giving a reason
  • add support on the cargo CLI for giving a reason
  • add reason to the index
  • add support on the cargo CLI for showing the reason

Design axioms

When considering this feature, we need to balance our desire for a perfect, structured yank message with a usable, easy-to-use yank message. We need to start with this feature and leave room for future extensions, but we shouldn’t introduce complexity and support for all requirements from the start.

Ownership and team asks

Owner:

  • @Rustin170506: wearing my crates.io team member’s hat
  • @Rustin170506: wearing my Cargo regular contributor’s hat
TaskOwner(s) or team(s)Notes
Implementation@Rustin170506
Standard reviewsTeam crates-io
Deploy to productionTeam crates-io
Author RFC@Rustin170506
RFC decisionTeam cargo, crates-io
Implementation in Cargo side@Rustin170506
Inside Rust blog post inviting feedback@Rustin170506
Stabilization decisionTeam cargo

Frequently asked questions

What might we do next?

We could start with plain text messages, but in the future we could consider designing it as structured data. This way, in addition to displaying it to Cargo users, we can also make it available to more crates-related platforms for data integration and use.

Not accepted

This section contains goals that were proposed but ultimately not accepted, either for want of resources or consensus. In many cases, narrower versions of these goals were accepted.

General notes

This is a place for the goal slate owner to track notes and ideas for later follow-up.

Candidate goals:

  • Track feature stabilization
  • Finer-grained infra permissions
  • Host Rust contributor event

Areas where Rust is best suited and how it grows

Rust offers particular advantages in two areas:

  • Latency sensitive or high scale network services, which benefit from Rust’s lack of garbage collection pauses (in comparison to GC’d languages).
  • Low-level systems applications, like kernels and embedded development, benefit from Rust’s memory safety guarantees and high-level productivity (in comparison to C or C++).
  • Developer tooling has proven to be an unexpected growth area, with tools ranging from IDEs to build systems being written in Rust.

Who is using Rust

Building on the characters from the async vision doc, we can define at least three groups of Rust users:

  • Alan1, an experienced developer in a Garbage Collected language, like Java, Swift, or Python.
    • Alan likes the idea of having his code run faster and use less memory without having to deal with memory safety bugs.
    • Alan’s biggest (pleasant) surprise is that Rust’s type system prevents not only memory safety bugs but all kinds of other bugs, like null pointer exceptions or forgetting to close a file handle.
    • Alan’s biggest frustration with Rust is that it sometimes makes him deal with low-level minutia – he sometimes finds himself just randomly inserting a * or clone to see if it will build – or complex errors dealing with features he doesn’t know yet.
  • Grace2, a low-level, systems programming expert.
    • Grace is drawn to Rust by the promise of having memory safety while still being able to work “close to the hardware”.
    • Her biggest surprise is cargo and the way that it makes reusing code trivial. She doesn’t miss ./configure && make at all.
    • Her biggest frustration is
  • Barbara3

How Rust adoption grows

The typical pattern is that Rust adoption begins in a system where Rust offers particular advantage. For example, a company building network services may begin with a highly scaled service. In this setting, the need to learn Rust is justified by its advantage.

Once users are past the initial learning curve, they find that Rust helps them to move and iterate quickly. They spend slightly more time getting their program to compile, but they spend a lot less time debugging. Refactorings tend to work “the first time”.

Over time, people wind up using Rust for far more programs than they initially expected. They come to appreciate Rust’s focus on reliability, quality tooling, and attention to ergonomics. They find that while other languages may have helped them edit code faster, Rust gets them to production more quickly and reduces maintenance over time. And of course using fewer languages is its own advantage.

How Rust adoption stalls

Anecdotally, the most commonly cited reasons to stop using Rust is a feeling that development is “too slow” or “too complex”. There is not any one cause for this.

  • Language complexity: Most users that get frustrated with Rust do not cite the borrow checker but rather the myriad workarounds needed to overcome various obstacles and inconsistencies. Often “idomatic Rust” involves a number of crates to cover gaps in core functionality (e.g., anyhow as a better error type, or async_recursion to permit recursive async functions). Language complexity is a particular problem
  • Picking crates: Rust intentionally offers a lean standard library, preferring instead to support a rich set of crates. But when getting started users are often overwhelmed by the options available and unsure which one would be best to use. Making matters worse, Rust documentation often doesn’t show examples making use of these crates in an effort to avoid picking favorites, making it harder for users to learn how to do things.
  • Build times and slow iteration: Being able to make a change and quickly see its effect makes learning and debugging effortless. Despite our best efforts, real-world Rust programs do still have bugs, and finding and resolving those can be frustratingly slow when every change requires waiting minutes and minutes for a build to complete.

Additional concerns faced by companies

For larger users, such as companies, there are additional concerns:

  • Uneven support for cross-language invocations: Most companies have large existing codebases in other languages. Rewriting those codebases from scratch is not an option. Sometimes it possible to integrate at a microservice or process boundary, but many would like a way to rewrite individual modules in Rust, passing data structures easily back and forth. Rust’s support for this kind of interop is uneven and often requires knowing the right crate to use for any given language.
  • Spotty ecosystem support, especially for older things: There are a number of amazing crates in the Rust ecosystem, but there are also a number of notable gaps, particularly for older technologies. Larger companies though often have to interact with legacy systems. Lacking quality libraries makes that harder.
  • Supply chain security: Leaning on the ecosystem also means increased concerns about supply chain security and business continuity. In short, crates maintained by a few volunteers rather than being officially supported by Rust are a risk.
  • Limited hiring pool: Hiring developers skilled in Rust remains a challenge. Companies have to be ready to onboard new developers and to help them learn Rust. Although there are many strong Rust books available, as well as a number of well regarded Rust training organizations, companies must still pick and choose between them to create a “how to learn Rust” workflow, and many do not have the extra time or skills to do that.

  1. In honor of Alan Kay, inventor of Smalltalk, which gave rise in turn to Java and most of the object-oriented languages we know today.

  2. In honor of Grace Hopper, a computer scientist, mathematician, and rear admiral in the US Navy; inventor of COBOL.

  3. In honor of Barbara Liskov, a computer science professor at MIT who invented of the [CLU](https://en.wikipedia.org/wiki/CLU_(programming_language) programming language.

Propose a new goal

Status: Accepting for 2026

What steps do I take to submit a goal?

Goal proposed are submitted as Pull Requests:

  • Fork the GitHub repository and clone it locally
  • Copy the src/TEMPLATE.md to a file like src/2026/your-goal-name.md. Don’t forget to run git add.
  • Fill out the your-goal-name.md file with details, using the template and other goals as an example.
    • The goal text does not have to be complete. It can be missing details.
  • Open a PR.

Who should propose a goal?

Opening a goal is an indication that you (or your company, etc) is willing to put up the resources needed to make it happen, at least if you get the indicated support from the teams. These resources are typically development time and effort, but they could be funding (in that case, we’d want to identify someone to take up the goal). If you pass that bar, then by all means, yes, open a goal.

Note though that controversial goals are likely to not be accepted. If you have an idea that you think people won’t like, then you should find ways to lower the ask of the teams. For example, maybe the goal should be to perform experiments to help make the case for the idea, rather than jumping straight to implementation.

Help! I have no idea what Rust teams to ask for help from.

Don’t stress. The most important thing is to write-up the motivation. It’s fine to open a PR that is semi-completed, the goals team will help you figure things out! That’s what we are here for.

Can I still do X, even if I don’t submit a goal for it?

Yes. Goals are not mandatory for work to proceed. They are a tracking mechanism to help stay on course.

TEMPLATE (replace with title of your goal)

Instructions: Copy this template to a fresh file with a name based on your plan. Give it a title that describes what you plan to get done in the next 6 months (e.g., “stabilize X” or “nightly support for X” or “gather data about X”). Feel free to replace any text with anything, but there are placeholders designed to help you get started.

The point of contact is the person responsible for providing updates.

The status should be Proposed for new goals or Accepted once approved.

If your goal is contingent on something, add one or more Contingent on rows:

  • Contingent on | Contributor — the goal needs someone to step up and do the work. The project goals team will try to help you find someone.
  • Contingent on | Funding — the goal needs funding to proceed.

If you add a “contingent” line, please add a section in the summary giving more details.

Metadata
Point of contactmust be a single GitHub username like @ghost
StatusProposed
Tracking issueif this is a continuing goal, add the old tracking issue, else leave blank
Zulip channelN/A (an existing stream can be re-used or new streams can be created on request)

Summary

Short description of what you will do over the next year.

Motivation

The status quo

Elaborate in more detail about the problem you are trying to solve. This section is making the case for why this particular problem is worth prioritizing with project bandwidth. A strong status quo section will (a) identify the target audience and (b) give specifics about the problems they are facing today. Sometimes it may be useful to start sketching out how you think those problems will be addressed by your change, as well, though it’s not necessary.

What we propose to do about it

Explain your overall approach to solving the problem. Explain your design philosophy (including design axioms). Focus your discussion on what you aim to get done this year, but it is good to also give a sense for the “overall goal” you are working towards, if it extends beyond the work for this year. Team(s) should give you feedback on whether they are aligned both with your short-term and longer-term goals.

Work items over the next year

Sketch out the specific things you are trying to achieve in this goal period. This should be short and high-level – we don’t want to see the design!

TaskOwner(s)Notes
Do the workowner

Team asks

This section outlines what support you need from the Rust teams. For each team, identify the level of support you need:

  • Small: You only need the team to do its routine activities, or you simply need the team’s approval.
    • Example: Prototyping a new feature on crates.io that you hope to eventually upstream.
    • Example: Conducting research that might eventually become a language feature.
    • Example: A compiler change that will require a few small PRs to be reviewed.
    • Example: Asking the lang team to approve a lint.
  • Medium: You need dedicated support from one person, but the rest of the team doesn’t have to do much.
    • Example: A compiler change that doesn’t require any rearchitecting but
    • Example: Implementing a small, noncontroversial language feature.
  • Large: You need deeper review from the entire team.
    • Example: Rearchitecting part of the compiler.
    • Example: Implementing a complex language feature that will require design meetings.

If you’re not sure, leave it blank, the project goals team can help.

“Small” asks require someone on the team to “second” your goal; “Medium” and “Large” asks require a dedicated champion from the team. If you don’t have a second or a champion, the project goals team will help you find them, don’t worry about it.

TeamSupport levelNotes
cargo
compiler
infra
lang
libs
opsem
types
Feel free to add rows for other teams

Frequently asked questions

What do I do with this space?

This is a good place to elaborate on your reasoning above – for example, why did you put the design axioms in the order that you did? It’s also a good place to put the answers to any questions that come up during discussion. The expectation is that this FAQ section will grow as the goal is discussed and eventually should contain a complete summary of the points raised along the way.

Report status

Every accepted project goal has an associated tracking issue. These are created automatically by the project-goals admin tool. Your job as a project goal point of contact is to provide regular status updates in the form of a comment indicating how things are going. These will be collected into regular blog posts on the Rust blog as well as being promoted in other channels.

Updating the progress bar

When we display the status of goals, we include a progress bar based on your documented plan. We recommend you keep this up to date. You can mix and match any of the following ways to list steps.

Checkboxes

The first option is to add checkboxes into the top comment on the tracking issue. Simply add boxes like * [ ] or * [x] for a completed item. The tool will count the number of checkboxes and use that to reflect progress. Your tracking issue will be pre-propulated with checkboxes based on the goal doc, but feel free to edit them.

Best practice is to start with a high level list of tasks:

* [ ] Author code
* [ ] Author RFC
* [ ] Accept RFC
* [ ] Test
* [ ] Stabilize

each time you provide a status update, check off the items that are done, and add new items with more detailed to-do items that represent your next steps.

Search queries

For larger project goals, it can be more convenient to track progress via github issues. You can do that by removing all the checkboxes from your issue and instead adding a “Tracked issues” line into the metadata table on your tracking issue. It should look like this:

| Metadata      | |
| --------      | --- |
| Point of contact | ... |
| Team(s)       | ... |
| Goal document | ... |
| Tracked issues | [rust-lang/rust label:A-edition-2024 label:C-tracking-issue -label:t-libs](...) |

The first 3 lines should already exist. The last line is the one you have to add. The “value” column should have a markdown link, the contents of which begin with a repo name and then search parameters in GitHub’s format. The tool will conduct the search and count the number of open vs closed issues. The (...) part of the link should be to github so that users can click to do the search on their own.

You can find an example on the Rust 2024 Edition tracking issue.

Use “See also” to refer to other tracking issues

If you already have a tracking issue elsewhere, just add a “See also” line into your metadata. The value should be a comma-or-space-separated list of URLs or org/repo#issue github references:

| Metadata      | |
| --------      | --- |
| Point of contact | ... |
| Team(s)       | ... |
| Goal document | ... |
| See also | rust-lang/rust#123 |

We will recursively open up the “see also” issue and extract checkboxes (or search queries / see-also tags) from there.

Binary issues

If we don’t find any of the above, we will consider your issue either 0% done if it is not yet closed or 100% done if it is.

Status update comments and summaries

We encourage you to post regular detailed updates about your progress as comments on the GitHub tracking issue. There is no strict format for these updates but we recommend including the following information:

  • What happened since the last update? Were any key decisions made or milestones achieved?
  • What is the next step to get done?
  • Are you blocked on anyone or anything?

Status update comments will be included verbatim in a “details” section of the monthly blog post.

Help wanted comments

If your updates include the text Help wanted: or **Help wanted:** at the start of a line, then the remainder of that line (and any non-block lines afterwards) will be extracted as a “help wanted” request. This will be highlighted in the monthly blog post.

Summary comments

Once per month, you will start receiving pings to author a monthly status update. This is a special update that will be included verbatim in the blog post. Unless you have a flagship goal, the monthly status update should be short, no more than 2 or 3 bullet points. For a flagship goal it can be longer. To write your monthly status update, leave a comment that begins with the text “TL;DR:”. It’s a good idea to take the opportunity to update your progress checkboxes as well, as the status bar in the blog post will be based on those.

Closing the issue

Closing the tracking issue is a signal that you are no longer working on it. This can be because you’ve achieved your goal or because you have decided to focus on other things. Also, tracking issues will automatically be closed at the end of the project goal period.

When you close an issue, the state of your checkboxes makes a difference. If they are 100% finished, the goal will be listed as completed. If there are unchecked items, the assumption is that the goal is only partly done, and it will be listed as unfinished. So make sure to check the boxes if the goal is done!

Goals team

The Rust goals program is administered by the Goals team. This document serves as the team charter.

Mission

Our mission is to focus the Rust programming language efforts by running and administering an inclusive and dynamic goals program. We work with the project teams to identify the highest priority items and to make sure that the teams are budgeting adequate time and resources to ensure those items are successful. For new contributors who have an idea they’d like to pursue, we work to provide a welcoming “front door” to Rust, connecting their proposal to the maintainers whose support will be needed to make it reality. For existing maintainers, we help them to document the work they are doing and to find new contributors.

Role and duties of team members

Team members perform some subset of the following roles:

  • Attending short sync meetings.
  • When preparing a new goal slate:
    • Advertising the goal program to teams and soliciting participation
    • Reviewing incoming goal proposals for quality and accuracy
    • Seeking feedback on behalf of outsiders’ goals
    • Authoring the RFC and hounding team leads to check their boxes
    • Deciding which goals to propose as roadmap goals.
  • During the year:
    • Authoring round-up blog posts highlighting progress
    • Updating and maintaining the web-site
    • Checking in with the goal points of contact that are not reporting progress to see if they need help

Role of the lead

The team lead is the owner of the program, meaning that they take ultimately responsible for ensuring the goals program moves forward smoothly. They perform and and all of the member functions as needed, delegating where possible. In the event of conflicts (e.g., which goals to propose as roadmap goals in the RFC), team lead makes the final decision.

Running the program

Thank you for helping to run the goals program. Congratulations! This page will walk you through what is involved at each step of the the process.

Calendar

This section summarizes the dates involved with a theoretical program taking place in the year 2222. Each item has a link to more instructions.

Each of the calendars has someoverlap with the previous and next previous.

H1 calendar

TaskNov–Dec
(prev. H2)
JanFeb–JunJul
(next H2
)
[CFP]██████░░░
[RFC]███
[Updates]███████████████
[Retro]███

H2 calendar

TaskMay–Jun
(prev. H1)
JulAug–DecJan
(next H1)
[CFP]██████░░░
[RFC]███
[Updates]███████████████
[Retro]███
[CFP]: ./cfp.md
[RFC]: ./prepare_rfc.md
[Updates]: ./author_updates.md
[Retro]: ./retro.md

Team coordination

Discussion channels

The project-goals channel on Zulip is used for discussing the “meat” of project goals: e.g., updates, proposed goals, etc.

The project-goals/meta channel on Zulip is used for meta discussions about running the program itself rest.

To broadcast updates about the status of the goal program, we create a goal in every goal program corresponding to running the program. Updates posted on that tracking issue will be posted in project-goals.

Meetings

We do not currently have a regularly scheduled meeting. Sync meetings are coordinated ad-hoc and typically take place on Zulip in the project-goals/meta channel.

Tracking our work

To track work items, we use issues tagged with the meta label on the rust-lang/rust-project-goals repository.

Issues tagged with “help wanted” indicates places where we would like somebody to jump in. Every such issue will also be tagged with mentoring instructions giving some idea how to get started.

There are also “meta” milestones for each program period to track specific goals related to that period.

Call for proposals

Each goal milestone corresponds to six months, designated in the format YYYYhN, e.g., 2024h2 or 2025h1. To launch a new goal season, you should get started a couple of months before the new season starts:

  • For an H1 season, start around mid October of the year before.
  • For an H2 season, start around mid April of the year before.

Using the automated setup command

The easiest way to set up a new Call For Proposals (CFP) period is to use the cargo rpg cfp command. This command automates the process of creating the necessary directory structure, copying template files, and updating both the SUMMARY.md and README.md files.

# Basic usage
cargo rpg cfp 2025h2

# Force overwrite without asking for confirmation
cargo rpg cfp 2025h2 --force

# Dry run - don't make any changes, just show what would be done
cargo rpg cfp 2025h2 --dry-run

The command will:

  1. Create a new directory for the specified timeframe (e.g., src/2025h2/)
  2. Copy and process template files from src/admin/samples/ to the new directory
  3. Update the SUMMARY.md file to include the new timeframe section
  4. Update the main README.md with information about the new timeframe

Manual steps required

After running the cargo rpg cfp command, there are still important manual steps that need to be completed:

1. Prepare and publish a blog post

You need to prepare a Call For Proposals blog post on the Inside Rust blog:

  • Use this sample as a starting point
  • Copy the sample to the blog.rust-lang.org repository as a new post
  • Replace placeholders like YYYYHN with the actual timeframe (e.g., 2025H2)
  • We use Inside Rust and not the Main blog because the target audience is would-be Rust contributors and maintainers

2. Email the mailing list

Send an email to the all@rust-lang.org mailing list to announce the Call For Proposals:

  • Include a link to the blog post
  • Summarize the key dates and process
  • Encourage team participation and feedback
  • This step is crucial for ensuring all Rust team members are aware of the upcoming goal period

Manual setup checklist

If you prefer to set up the CFP manually, or need to customize the process beyond what the automated command provides, here’s a checklist of steps:

  • Prepare a Call For Proposals blog post on the Inside Rust blog based on this sample.
    • We use Inside Rust and not the Main blog because the target audience is would-be Rust contributors and maintainers.
  • Update the main README page to indicate that the next round of goals is begin accepted.
  • Create a new directory src/YYYYhN, e.g., src/2025h1, with the following files. Note that the sample files below include <!-- XXX --> directives that are detected by the mdbook plugin and replaced with appropriate content automatically.
  • Modify SUMMARY.md to include your new milestone with some text like what is shown below.

Sample SUMMARY.md comments from 2025H1:

# ⏳ 2025H1 goal process

- [Overview](./2025h1/README.md)
- [Proposed goals](./2025h1/goals.md)
- [Goals not accepted](./2025h1/not_accepted.md)

Receiving PRs

to be written

Preparing the RFC

Review with teams

Before opening the RFC it is best to review its current state with teams that have large number of goals. You want there to be as little surprise as possible once the RFC itself is opened, as it will be more annoying to make changes.

Encourage teams to read over the list of asks assigned to them and answer questions like

  • Are there any goals that you are not aligned with? (i.e., work that you do not think should happen, or do not think should happen now)
  • Is there important work not represented here? Should that work have a project goal?
  • Is the team capable of following through on the total asks, or will that exceed team capacity?
  • If roadmap goals have been decided, are there any concerns with those goals? Any suggestions for changes or alternatives?

Select roadmap goals

Roadmap goals represent the 2-3 items that will be highlighted and will be the focus of external communication. The project goal team is responsible for selecting roadmap goals. The criteria for roadmap goals is described in the About page. Because roadmap goals generally take longer than 6 months to complete, most roadmap goals are continuations from previous sessions, but as those goals get closer to completion, it may be good to shift the messaging towards a fresh focus.

Creating the RFC

Run cargo rpg rfc to export the RFC text in a format suitable for adding into the RFCs repository.

Beginning Final Comment Period

Unlike ordinary RFCs, project goal RFCs are not chosen by any one team. Instead we craft a comment with the names of all project members. The leads of each team at minimum are required to check their box, though obviously the more boxes the better. You can craft this comment with the cargo rpg fcp command.

Merging the RFC

Once the RFC is accepted, you need to take the following steps.

Merge the RFC itself

Update the RFC and merge as normal

Update the teams

Run cargo rpg teams to prepare adjustment to the teams repository. You will need to have a checkout of the teams repository somewhere; you pass the command the path to that repo and it will make changes. You can then commit the changes and prepare a PR.

This will create a project-goal-owners team containing all the project goal owners. It will also add people to the rust-lang repository. This may trigger them to get invites if they are not already members of the org. You should encourage them to accept those invites. If they don’t take these steps you won’t be able to assign them to issues and they won’t be able to author updates, etc.

Create the milestone

Next you need to (manually) create a milestone on the rust-project-goals repository with the appropriate name (e.g., 2025h1). We usually create a paired meta milestone like 2025h1-meta to track other tasks related to running the program.

Create tracking issues

Finally, you can create the tracking issues. To do this, you run cargo rpg issues. Before doing so, make sure that the metadata for any goals that are continuing from the previous milestone already lists the appropriate tracking issue, otherwise the comment will create a duplicate issue.

You can run the command more than once, it tries to pick up from where it left off. It will adjust the state of all issues to match what is expected.

Author the “why this goal” sections for the roadmap goals

For each roadmap goal, you should add a section entitled ## Why this goal? into the tracking issue. Put in there about a paragraph of text that explains the background for this goal. This text will be included verbatim when you prepare monthly updates, so make it readily understood. Often this is the same text that appeared in the RFC itself.

Close old tracking issues

Finally, you can go to the previous milestone, find all remaining issues, and close them. These should correspond to goals from the previous session that were not continued into the current one.

Author updates

Soliciting updates

Triagebot can ping project-goal owners for updates. To use it, go to Zulip and execute a command like this (you need to use an @ in front of triagebot).

@triagebot ping-goals 14 Oct-21

The first number (14) is a threshold, it is typically set to the current day of the month (e.g., the above command assumes it is Oct 14). It means “if they have posted a comment in the last 14 days, don’t bug them”.

The second string (“Oct-21”) is the deadline for updates to be included.

We need to improve this UI.

Filling out the template

After the updates have been published, they can be summarized in a monthly blog post, as described in this dedicated chapter.

Sample texts

Call for PRs: YYYYHN goals

NOTE: This is a sample blog post you can use as a starting point. To begin a new goal season (e.g., 2222H1), do the following:

  • Copy this file to to the blog.rust-lang.org repository as a new post.
  • Search and replace YYYYHN with 2222H1 and delete this section.
  • Look for other “TBD” sections, you’ll want to replace those eventually.

As of today, we are officially accepting proposals for Rust Project Goals targeting YYYYHN (the (TBD) half of YYYY). If you’d like to participate in the process, or just to follow along, please check out the YYYYHN goal page. It includes listings of the goals currently under consideration , more details about the goals program, and instructions for how to submit a goal.

What is the project goals program and how does it work?

Every six months, the Rust project commits to a set of goals for the upcoming half-year. The process involves:

  • the owner of the goal program (currently me) posts a call for proposals (this post);
  • would-be goal points of contact open PRs against the rust-project-goals repository;
  • the goal-program owner gathers feedback on these goals and chooses some of them to be included in the RFC proposing the final slate of goals.

To get an idea what the final slate of goals looks like, check out the RFC from the previous round of goals, RFC (TBD). The RFC describes a set of goals, designates a few of them as roadmap goals, and summarizes the work expected from each team. The RFC is approved by (at least) the leads of each team, effectively committing their team to prove the support that is described.

Should I submit a goal?

Opening a goal is an indication that you (or your company, etc) is willing to put up the resources needed to make it happen, at least if you get the indicated support from the teams. These resources are typically development time and effort, but they could be funding (in that case, we’d want to identify someone to take up the goal). If you pass that bar, then by all means, yes, open a goal.

Note though that controversial goals are likely to not be accepted. If you have an idea that you think people won’t like, then you should find ways to lower the ask of the teams. For example, maybe the goal should be to perform experiments to help make the case for the idea, rather than jumping straight to implementation.

Can I still do X, even if I don’t submit a goal for it?

Yes. Goals are not mandatory for work to proceed. They are a tracking mechanism to help stay on course.

Conclusion

The Rust Project Goals program is driving progress, increasing transparency, and energizing the community. As we enter the second round, we invite you to contribute your ideas and help shape Rust’s future. Whether you’re proposing a goal or following along, your engagement is vital to Rust’s continued growth and success. Join us in making Rust even better in 2025!

Sample: Text for the main README

NOTE: This is a sample section you can use as a starting point.

  • Copy and paste the markdown below into the main README.
  • Replace YYYYHN with 2222h1 or whatever.

(Note that the links on this page are relative to the main README, not its current location.)

Next goal period (YYYYHN)

The next goal period will be YYYYHN, running from MM 1 to MM 30. We are currently in the process of assembling goals. Click here to see the current list. If you’d like to propose a goal, instructions can be found here.

Rust project goals YYYY

NOTE: This is a sample RFC you can use as a starting point. To begin a new goal season (e.g., 2222), do the following:

  • Copy this file to src/2222/README.md.
  • Search and replace YYYY with 2222 and delete this section.
  • Look for other “TBD” sections, you’ll want to replace those eventually.
  • Customize anything else that seems relevant.

Summary

Status: Accepting goal proposals We are in the process of assembling the goal slate.

This is a draft for the eventual RFC proposing the YYYY goals.

Motivation

The YYYY goal slate consists of 0 project goals, of which we have selected (TBD) as roadmap goals. Roadmap goals represent the goals expected to have the broadest overall impact.

How the goal process works

Project goals are proposed bottom-up by a point of contact, somebody who is willing to commit resources (time, money, leadership) to seeing the work get done. The point of contact identifies the problem they want to address and sketches the solution of how they want to do so. They also identify the support they will need from the Rust teams (typically things like review bandwidth or feedback on RFCs). Teams then read the goals and provide feedback. If the goal is approved, teams are committing to support the point of contact in their work.

Project goals can vary in scope from an internal refactoring that affects only one team to a larger cross-cutting initiative. No matter its scope, accepting a goal should never be interpreted as a promise that the team will make any future decision (e.g., accepting an RFC that has yet to be written). Rather, it is a promise that the team are aligned on the contents of the goal thus far (including the design axioms and other notes) and will prioritize giving feedback and support as needed.

Of the proposed goals, a small subset are selected by the roadmap owner as roadmap goals. Roadmap goals are chosen for their high impact (many Rust users will be impacted) and their shovel-ready nature (the org is well-aligned around a concrete plan). Roadmap goals are the ones that will feature most prominently in our public messaging and which should be prioritized by Rust teams where needed.

Rust’s mission

Our goals are selected to further Rust’s mission of empowering everyone to build reliable and efficient software. Rust targets programs that prioritize

  • reliability and robustness;
  • performance, memory usage, and resource consumption; and
  • long-term maintenance and extensibility.

We consider “any two out of the three” as the right heuristic for projects where Rust is a strong contender or possibly the best option.

Axioms for selecting goals

We believe that…

  • Rust must deliver on its promise of peak performance and high reliability. Rust’s maximum advantage is in applications that require peak performance or low-level systems capabilities. We must continue to innovate and support those areas above all.
  • Rust’s goals require high productivity and ergonomics. Being attentive to ergonomics broadens Rust impact by making it more appealing for projects that value reliability and maintenance but which don’t have strict performance requirements.
  • Slow and steady wins the race. For this first round of goals, we want a small set that can be completed without undue stress. As the Rust open source org continues to grow, the set of goals can grow in size.

Guide-level explanation

Roadmap goals

The roadmap goals proposed for this roadmap are as follows:

(TBD)

Why these particular roadmap goals?

(TBD–typically one paragraph per goal)

Project goals

The full slate of project goals are as follows. These goals all have identified points of contact who will drive the work forward as well as a viable work plan. The goals specify the level of support needed from the listed Rust teams, which is cataloged in the reference-level explanation section below.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as a point of contact. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactProgress

Reference-level explanation

The following table highlights the support level requested from each affected team. Each goal specifies the level of involvement needed:

  • Small: The team only needs to do routine activities (e.g., reviewing a few small PRs).
  • Medium: Dedicated support from one team member, but the rest of the team doesn’t need to be heavily involved.
  • Large: Deeper review and involvement from the entire team (e.g., design meetings, complex RFCs).

“Small” asks require someone on the team to “second” the goal. “Medium” and “Large” asks require a dedicated champion from the team.

Goals

NOTE: This is a sample starting point for the goals.md page in a milestone directory.

  • Search and replace YYYYHN with 2222H1 and delete this section.

This page lists the 0 project goals proposed for YYYYHN.

Just because a goal is listed on this list does not mean the goal has been accepted. The owner of the goal process makes the final decisions on which goals to include and prepares an RFC to ask approval from the teams.

Roadmap goals

Roadmap goals represent the goals expected to have the broadest overall impact.

GoalPoint of contactProgress

Other goals

These are the other proposed goals.

Invited goals. Some goals of the goals below are “invited goals”, meaning that for that goal to happen we need someone to step up and serve as a point of contact. To find the invited goals, look for the Help wanted badge in the table below. Invited goals have reserved capacity for teams and a mentor, so if you are someone looking to help Rust progress, they are a great way to get involved.

GoalPoint of contactProgress

Technical reference

Overall setup

The rust-project-goals repository is set up as follows

  • an mdbook for generating the main content
  • a Rust binary in src that serves as
    • a runnable utility for doing various admin functions on the CLI (e.g., generating a draft RFC)
    • an mdbook preprocessor for generating content like the list of goals
    • a utility invoked in CI that can query github and produce a JSON with the goal status
  • pages on the Rust website that fetches JSON data from rust-project-goals repo to generate content
    • the JSON data is generated by the Rust binary
  • tracking issues for each active project goal:
    • tagged with C-tracking-issue
    • and added to the appropriate milestone
  • triagebot modifications to link Zulip and the repo tracking issues
    • the command &#64;triagebot ping-goals N D will ping all active goal points of contact to ask them to add updates
      • N is a threshold number of days; if people have posted an update within the last N days, we won’t bother them. Usually I do this as the current date + 7, so that people who posted during the current month or the last week of the previous month don’t get any pings.
      • D is a word like Sep-22 that indicates the day
    • the bot monitors for comments on github and forwards them to Zulip

Mdbook Plugin

The mdbook is controlled by the mdbook-goals plugin in this repo. This plugin makes various edits to the source:

  • Linking usernames like @foo to their github page and replacing them with their display name.
  • Linking GH references like rust-lang/rust#123.
  • Collating goals, creating tables, etc.

The plugin can also be used from the command line.

Expected book structure

The plugin is designed for the book to have a directory per phase of the goal program, e.g., src/2024h2, src/2025h1, etc. Within this directory there should be:

  • A README.md file that will contain the draft slate RFC.
  • One file per goal. Each goal file must follow the TEMPLATE structure and in particular must have
  • One file per “phase” of the program, e.g., proposed.md etc. (These are not mandatory.)

Plugin replacement text

The plugin will replace the following placeholder texts. Each placeholder is enclosed within an html comment <!-- -->.

Goal count

The placeholder <– #GOALS –> will be replaced with the total number of goals under consideration (this count excludes goals with the status Not accepted).

Goal listing

The placeholder <– GOALS ‘$Status’ –> will insert a goal table listing goals of the given status $Status, e.g., <– GOALS ‘Roadmap’ –>. You can also list multiple status items, e.g., <– GOALS ‘Accepted,Proposed’ –>

Commands

The cargo rpg command is a CLI for manipulating and checking project goals. This section provides a reference describing (some of) the ability commands. You can also try cargo rpg --help to get a summary.

Note that this relies on the gh client, which needs to be installed and configured with a token (for example using gh auth login).

Available Commands

cargo rpg cfp

Sets up a new Call For Proposals (CFP) period. This command automates the process of creating the necessary directory structure, copying template files, and updating both the SUMMARY.md and README.md files.

# Basic usage
cargo rpg cfp <timeframe>

# Options
cargo rpg cfp <timeframe> --force    # Force overwrite without asking for confirmation
cargo rpg cfp <timeframe> --dry-run  # Don't make any changes, just show what would be done

Example:

cargo rpg cfp 2025h2

Note that after running this command, you’ll still need to manually:

  1. Prepare and publish a blog post on the Inside Rust blog
  2. Send an email to the all@rust-lang.org mailing list

For more details, see the Call for proposals documentation.

cargo rpg csv

Generates CSV reports for analysis and tracking purposes. Currently supports generating champion tracking reports.

# Generate champions report for a milestone
cargo rpg csv champions <milestone>

Example:

cargo rpg csv champions 2025h2

champions subcommand

The champions subcommand generates a CSV report showing the champion assignments for each goal in a milestone. The output includes:

  • Title: The goal title
  • POC(s): Point of contact for the goal
  • Team columns: One column per team that has asks across all goals in the milestone
    • Shows champion name if assigned
    • Shows ! if team has an ask but no champion assigned
    • Shows - if team has no ask for this goal
  • URL: Link to the goal document on GitHub

This report is useful for:

  • Tracking champion coverage across teams
  • Identifying goals that need champion assignments
  • Understanding team involvement across the milestone

The CSV output can be redirected to a file or piped to other tools for further analysis:

cargo rpg csv champions 2025h2 > champions.csv

rfc, export RFC text

The cargo rpg rfc command exports RFC text suitable for inclusion in the rust-lang/rfcs repository. It is intended for use when preparing the RFC at the start of a goal period.

To use, simply invoke the command with the directory for the goal period, e.g., something like this:

> cargo rpg rfc src/2025h1

This will read the README.md file and dump a version to stdout that can be copy-and-paste. This version will have URLs adjusted to point at the rust-lang/rust-project-goals repository and other cosmetic changes.

fcp, create the FCP merge comment

The cargo rpg fcp command creates an FCP comment, since the format for the project goals RFC is distinct from other RFCs.

To use, simply invoke the command with the directory for the goal period, e.g., something like this:

> cargo rpg rfc src/2025h1

This will emit a comment to stdout that includes the name of each team which has registered asks along with checkboxes for each individual on that team.

To avoid exceeding GitHub’s limit of 50 usernames per message, only leads are cited with @ usernames.

Creating tracking issues

Usage:

> cargo rpg issues

The issues command is used to create tracking issues at the start of a project goal session. When you first run it, it will simply tell you what actions it plans to take.

To actually commit and create the issues, supply the --commit flag:

> cargo rpg issues --commit

This will also edit the goal documents to include a link to each created tracking issue. You should commit those edits.

You can later re-run the command and it will not repeat actions it has already taken.c

Summarize updates for the monthly blog post

Usage:

> cargo rpg updates --help

Run the cargo rpg updates command to create the blog post template. If running from within vscode, the --vscode command will open the result in a fresh tab, which is convenient. Otherwise, use --output-file $file.md to create a new file.

The template will be filled in with the list of roadmap goals. Each roadmap goal will have their Why this goal? section auto-inserted from the corresponding tracking issue.

The template will also include the detailed list of updates in a <details> section as well as any TL;DR comments left by users.

The update template itself is maintained with handlebars, you will find it here. This command can also take optional dates to control which comments and updates in the given date range are included in the blog post. This is usually needed to correctly set the starting date right after the previous month’s blog post.

The updates on the Rust blog typically cover a single calendar month. Since the start date is inclusive and the end date is exclusive, to generate an update for e.g. March 2025 you’d type:

> cargo rpg updates 2025h1 2025-03-01 2025-04-01