Hacker News 中文摘要

RSS订阅

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

文章摘要

该文章提出为Rust语言引入新trait,允许类型选择禁止移动或遗忘操作,从而支持作用域内生成、异步析构和默认固定等功能,计划在2026-2027年实现。

文章总结

不可移动类型与保证析构函数

| 元数据 | | | --- | --- | | 联系人 | @lcnr | | 状态 | 已接受 | | 内容与目标 | 允许类型选择不被移动或遗忘,从而支持作用域生成、异步析构和默认固定 | | 时间跨度 | 2026-2027 | | 路线图 | 添加异步支持 | | 路线图 | Rust for Linux | | 追踪问题 | [#635] | | 其他追踪问题 | [rust-lang/rust#149607] | | Zulip频道 | #t-lang/move-trait | | [类型] 负责人 | @lcnr | | [语言] 负责人 | @jackh726 |

摘要

我们提议引入新的特质来描述类型允许的操作。目前Rust假设所有类型都可以被移动(在内存中重新定位)和遗忘(通过mem::forget)。我们将引入MoveForget等特质,使这些能力显式化,允许类型选择退出。这遵循了Sized层次结构工作的先例,该工作放宽了所有类型都具有编译时已知大小的假设。我们将在编译器中实现最小可行产品,编写RFC,并通过在Linux内核中的实际测试验证可行性。

动机

现状

Rust历来假设所有值都可以被移动(在内存中重新定位)和遗忘(通过mem::forget,不运行析构函数)。这些假设已融入语言:赋值会移动值,而mem::forget是安全的。但某些类型需要选择退出这些能力:

不可移动类型: 许多异步future希望是自引用的,但自引用类型无法安全移动。当前的解决方案是Pin,它将不可移动性编码为位置而非类型的属性。这导致了显著的复杂性。正如安全固定初始化问题所述,Pin在Linux内核等系统中难以安全编码自引用类型。

保证析构函数: 某些类型需要运行其析构函数。Transaction类型可能需要在清理前调用commit()rollback()。作用域任务句柄必须在作用域退出前加入。但mem::forget是安全的,因此Rust无法保证析构函数运行。这阻碍了异步安全作用域生成等模式,其中生成的任务借用父作用域的资源。

我们的提议

我们提议通过新的自动特质来泛化Rust的类型系统,描述类型允许的操作。框架是积极的:特质代表能力。在基础层,类型可能没有特殊能力。然后我们添加所需的功能:

  • Move:类型可以在内存中重新定位。
  • Destruct:类型可以隐式丢弃(超出作用域时运行析构函数)。
  • Forget:类型可以通过mem::forget遗忘,而不运行其析构函数。

这遵循了Sized层次结构工作的先例。正如该工作放宽了"所有类型都具有编译时已知大小"以支持可扩展向量,本工作放宽了"所有类型都可以被移动"和"所有类型都可以被遗忘"。

Move特质将可移动性编码为类型的属性而非位置的属性:

```rust

[lang = "move"]

unsafe auto trait Move {} ```

实现!Move的类型不能被移动,并且必须在其整个生命周期内保持稳定的地址。这比Pin更简单,因为不可移动性是类型属性,而非位置属性。!Move类型的构造将依赖于#t-lang/in-place-init的工作。

Forget特质允许类型选择退出可遗忘性:

rust // 实现 !Forget 的类型必须运行其析构函数 unsafe impl !Forget for ScopedTaskHandle {}

有了!Forget,我们可以构建安全的作用域生成:句柄的析构函数加入任务,由于句柄不能被遗忘,加入操作得到保证。这解锁了当前在安全Rust中不可能实现的模式。

未来一年的工作项

Move特质

允许类型选择退出内存重新定位,将不可移动性编码为类型属性而非位置属性。

| 任务 | 负责人 | 备注 | | --- | --- | --- | | Move的编译器实现 | @lcnr 和 @nia-e | | | 编写MoveRFC | @yoshuawuyts | | | 在Linux内核中测试 | @BennoLossin | RfL是重要的Rust用户,使用大量自引用数据结构。 | | 测试Iterator!Move的交互 | @yoshuawuyts | 证明基于生成器的效果可以脱糖为impl Trait + !Move以支持自引用。 |

保证析构函数

探索允许类型选择退出mem::forget,从而支持异步安全作用域生成等模式。

| 任务 | 负责人 | 备注 | | --- | --- | --- | | 保证析构函数的设计探索 | @nikomatsakis | 探索特质层次结构选项及与现有功能的交互 |

今年明确不在范围内的是任何与更改或更新Future特质相关的工作。这是Rust中唯一依赖Pin的稳定特质,需要迁移故事才能使用Move。然而,依赖Pin并非Future的唯一缺陷(1 + 2 + 另外10个问题),因此修复Future特质最好作为独立项目处理。

团队需求

| 团队 | 支持级别 | 备注 | | --- | --- | --- | | [语言] | 大 | 需要设计会议来完善设计 | | [类型] | 大 | 参与实现和审查 |

常见问题

这与Sized层次结构工作有何关系?

Sized层次结构工作确立了模式:Rust可以通过引入允许类型选择退出的特质层次结构来放宽先前普遍存在的假设。该工作放宽了"所有类型都具有编译时已知大小"以支持可扩展向量和外部类型。本目标将相同模式应用于"所有类型都可以被移动"和"所有类型都可以被遗忘"。

这与"固定人体工程学"倡议有何关系?

本工作是2025H2项目目标:继续固定人体工程学实验的替代方案,后者包括以下扩展:

  • 左值中的新项族pin,例如&pin x&pin mut x&pin const x
  • Rust的Drop特质的一次性重载,例如fn drop(&pin mut self)
  • 模式中的新项种类pin,例如&pin <pat>

值得注意的是,本工作并未解决固定的重复定义问题,这意味着即使有了这些扩展,我们仍然会得到现有特质的TraitPinnedTrait变体。Drop特质是例外,因为该倡议提议使用一次性重载对其进行特殊处理。

我们相信问题在于Pin本身,而不是试图改变语言使其工作,我们应该改进Rust中不可移动类型的编码方式。最终目标是完全弃用Rust中的Pin

由于Rust承诺永远保持向后兼容,使pin成为与&mut同等的语言项是我们需要永远支持的事情。鉴于我们的最终目标是弃用Pin,我们认为不应将pin作为语言的一部分。这就是为什么Move不仅是补充提案,而是作为替代方案。

什么支持安全作用域生成?

安全作用域生成需要保证析构函数。模式:生成返回一个句柄,其析构函数加入任务。如果你能通过mem::forget遗忘句柄,任务可能超出作用域并访问悬垂引用。有了!Forget,句柄的析构函数保证运行,使模式安全。这是本目标中保证析构函数部分的关键动机之一。

在哪里可以了解更多关于这个设计空间的信息?

几篇博客文章探讨了这一领域:

评论总结

根据评论内容,总结如下:

核心观点:Rust拟引入“不可移动类型”(immovable types),以替代当前的Pin机制,填补语言关键空白。

支持方观点: - 这是Rust长期缺失的关键特性,解决了自2016年以来就存在的痛点(评论4) - 能解锁安全Rust中当前无法实现的模式,如自引用(评论9) - 可能推动Rust逐步采用C++模型,解决“必要破坏性移动”带来的限制(评论9) - 关键引用:"it became apparent that immovable types were a crucial missing part of Rust"(评论4) - 关键引用:"This unblocks patterns that are currently impossible in safe Rust"(评论9)

质疑/讨论方观点: - 有替代方案(pinned places)存在,需确认官方倾向(评论6) - 目前仅是项目目标,设计可能大幅变更甚至废弃(评论7) - 关键引用:"this is not an accepted language change. It's just a project goal"(评论7) - 关键引用:"a different proposal by @withoutboats to make immovability a property of the place/reference"(评论6)

技术细节讨论: - 与!Destruct(线性类型)的关系:不可移动类型要求销毁时必须调用特定函数(评论5) - 与mem::forget和引用循环的关系:安全泄漏的现有方式可能被影响(评论3) - 关键引用:"it also mentions !Destruct/must-move types, aka linear types"(评论5) - 关键引用:"mem::forget isn't the only way you can safely leak a value, you can do it with reference cycles too"(评论3)

潜在影响: - 可能使C/C++代码自动翻译为安全Rust更可行(评论9) - 可能推动不可移动类型成为Rust对象类型的默认选择(评论9)