Rust 项目目标:不可移动类型与保证析构
Rust project goals: Immobile types and guaranteed destructors

原始链接: https://github.com/rust-lang/rust-project-goals/blob/main/src/2026/move-trait.md

Rust 团队正提议引入新的自动特征(auto-traits)——`Move`、`Destruct` 和 `Forget`,旨在使内存操作显式化,并允许类型选择退出目前通用的默认假设。 过去,Rust 假设所有类型都可以被移动和遗忘(通过 `mem::forget`)。该提议遵循 `Sized` 层级的先例,旨在放宽这些假设: * **`!Move`(不可移动性):** 通过将不可移动性定义为类型属性而非位置属性,团队旨在用一套更简单、更稳健的系统来取代 `Pin`,以处理自引用类型(例如 Linux 内核中所使用的类型)。 * **`!Forget`(保证析构):** 允许类型选择退出“可被遗忘”的特性,从而确保必须执行析构函数。这可以实现诸如“作用域生成(scoped spawn)”等安全模式,即任务句柄的析构函数可确保在父作用域退出前任务已完成合并。 该项目涉及编译器实现、RFC 开发以及在 Linux 内核中的验证。最终目标是提供一种比 `Pin` 更简洁的替代方案,并有可能弃用 `Pin`。这将支持构建更复杂的数据结构和更安全的异步模式,而无需在语言层面长期支持 `Pin` 的工程化方案。

最近在 Hacker News 上的一场讨论聚焦于 Rust 项目的新目标,即“不可移动类型”(immobile types)和“保证析构”(guaranteed destructors)。 社区成员解释说,这些功能旨在解决 Rust 异步生态系统中长期存在的挑战,特别是在“结构化并发”(structured concurrency)和“异步取消”(async cancellation)方面。与同步函数(保证运行完成或展开)不同,Rust 的异步 Future 是可以随时被丢弃的状态机。这使得安全地在异步任务中共享栈分配数据的引用变得困难。 通过引入这些概念,Rust 团队希望实现类似于现有“作用域线程”(scoped threads)的模式,允许任务从外部作用域安全地借用数据,而无需进行昂贵的克隆。除了异步编程之外,参与者指出,确保对象无法被移动或“遗忘”(泄漏)将使开发者能够在整个语言中设计出更健壮、更易用的 API。总体而言,该提案被视为迈向使递归异步函数和复杂生命周期管理变得更直观、更安全的重要一步。
相关文章

原文
Metadata
Point of contact @lcnr
Status Accepted
What and why Let types opt out of being moved or forgotten, enabling scoped spawn, async drop, and pin-by-default
Timespan 2026-2027
Roadmap Just add async
Roadmap Rust for Linux
Tracking issue [#635]
Other tracking issues [rust-lang/rust#149607]
Zulip channel #t-lang/move-trait
[types] champion @lcnr
[lang] champion @jackh726

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.

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:

#[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:

// 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

Let types opt out of being relocated in memory, encoding immovability as a type property rather than a place property.

Task Owner(s) Notes
Compiler implementation for Move @lcnr and @nia-e
Write the Move RFC @yoshuawuyts
Test in Linux kernel @BennoLossin RfL is an important Rust user which uses a lot of self-referential data structures.
Test interactions between Iterator and !Move @yoshuawuyts It's important to prove that generator-based effects can be desugared to impl Trait + !Move so they can support self-references.

Explore letting types opt out of mem::forget, enabling patterns like safe scoped spawn for async.

Task Owner(s) Notes
Design exploration for guaranteed destructors @nikomatsakis Explore trait hierarchy options and interaction with existing features

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 Support level Notes
[lang] Large Design session needed to work through design
[types] Large Involved 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:

联系我们 contact @ memedata.com