← Back to news

Rust project goals: Immobile types and guaranteed destructors

github.com|191 points|72 comments|by paavohtl|Aug 3, 2026

Rust Project Goals: Immobile Types and Guaranteed Destructors

Rust Logo

📌 Metadata

FieldDetail
Point of Contact@lcnr
Current StatusAccepted
Timeline2026–2027
RoadmapJust add async
Primary Tracking#635
Secondary Trackingrust-lang/rust#149607
Zulip Channel#t-lang/move-trait
Champions@lcnr (types), @jackh726 (lang)

🎯 Summary

We intend to introduce a set of new traits that explicitly define which operations are permissible for a given type. Currently, the Rust compiler operates under the blanket assumption that every type can be moved (relocated in memory) and forgotten (via std::mem::forget). By introducing traits like Move and Forget, we allow types to opt out of these behaviors.

This initiative mirrors the logic used in the Sized hierarchy project, which moved away from the assumption that all types possess a known size at compile time. The plan involves developing MVPs within the compiler, drafting RFCs, and validating the implementation through the Rust for Linux project.


💡 Motivation

Historically, Rust has relied on two fundamental assumptions:

  1. All values can be relocated in memory (moved).
  2. All values can be discarded without running their destructors (mem::forget).

These are not just conventions; they are baked into the language's core. For example, a simple assignment is treated as a move, and mem::forget is globally safe. However, certain use cases make these assumptions problematic:

1. Immobile Types

Many async futures are self-referential. If a type contains a pointer to its own data, moving that type in memory invalidates the pointer.

  • Current Fix: We use Pin. However, Pin treats immovability as a property of the location (the place) rather than the type itself.
  • The Problem: As noted in the Safe Pinned Initialization Problem, this approach is cumbersome for systems like the Linux kernel.

2. Guaranteed Destructors

Some types must be destroyed to maintain system integrity.

  • Example: A Transaction type that requires a commit() or rollback() call during cleanup.
  • The Problem: Because mem::forget is always safe, Rust cannot strictly guarantee that a destructor will execute. This prevents the implementation of safe scoped spawns for async tasks, where a spawned task must be joined before the parent scope closes.

🛠️ The Proposal

We propose expanding the type system with auto-traits that describe operational capabilities. Mathematically, we are moving from a state where: T:Moveable(T)Forgettable(T)\forall T : \text{Moveable}(T) \land \text{Forgettable}(T) To a state where these are conditional properties: Type T    {Move,Destruct,Forget}\text{Type } T \implies \{ \text{Move}, \text{Destruct}, \text{Forget} \}

Proposed Traits

  • Move: Indicates the type can be relocated in memory.
  • Destruct: Indicates the type can be implicitly dropped when it leaves scope.
  • Forget: Indicates the type can be passed to mem::forget without running its destructor.

The Move Trait

By making movability a property of the type, we simplify the logic compared to Pin.

#[lang = "move"]
unsafe auto trait Move { }

If a type is marked as !Move, it is forbidden from being relocated and must maintain a stable memory address for its entire lifetime. This will integrate with ongoing work in #t-lang/in-place-init.

The Forget Trait

This allows types to mandate that their destructors must run.

// This type cannot be forgotten; its destructor is guaranteed to execute.
unsafe impl !Forget for ScopedTaskHandle { }

Impact: With !Forget, a ScopedTaskHandle can guarantee that its destructor joins the associated task, enabling safe scoped async spawns.

Visualizing the Change


📅 Work Items (Next 12 Months)

📦 Move Trait Implementation

Goal: Encode immovability as a type property.

TaskOwner(s)Notes
Compiler implementation@lcnr, @nia-eCore logic for Move
Draft Move RFC@yoshuawuytsFormalize the specification
Linux Kernel Testing@BennoLossinValidate with self-referential structures
Iterator & !Move interaction@yoshuawuytsEnsure generator-based effects work
  • Implement Move in compiler
  • Finalize RFC
  • Verify impl Trait + !Move for generators

🛡️ Guaranteed Destructors

Goal: Prevent mem::forget for specific types.

TaskOwner(s)Notes
Design Exploration@nikomatsakisHierarchy and feature interactions

⚠️ Out of Scope: We are not updating the Future trait this year. While Future relies on Pin and would benefit from Move, it has too many other issues (13+ tracked) and requires a dedicated migration strategy.


👥 Team Requirements

TeamSupport LevelRole
[lang]LargeRequired for high-level design sessions
[types]LargeRequired for implementation and review

❓ FAQ

How does this relate to the Sized hierarchy work? The Sized hierarchy established the architectural pattern for this project: it proved that Rust can successfully relax a global assumption (that all types have a known size) by introducing a trait-based system to handle the exceptions. We are applying that same logic to movability and forgettability.