在过去的几年里,Rust 已经从少数忠实用户使用的语言发展成为许多引人注目的项目和成功公司使用的知名语言。随着 Rust 用户群、社区和生态系统的持续增长,我们需要展望未来,考虑如何扩展以适应不断扩大的 Rust 生态系统的需求。
最近,编译器团队分享了 他们的博客文章,详细介绍了他们 2022 年的雄心壮志,而语言团队发布了 路线图,其中包含他们对 2024 年 Rust 的愿景。
在这篇博客文章中,我们,Rust 库团队,将分享我们对 Rust 标准库和库生态系统未来的看法。
重要的是要注意,团队的角色是协调变更,并进行指导、审查和决策。大部分工作本身由贡献者完成,就像您一样,无论是在 Rust 团队内部还是外部。虽然我们经常也参与设计和实现工作,但我们是像其他人一样的贡献者。
以下是我们认为重要并希望协调和指导的主题的(不完整)摘要;我们希望看到发生的事情,作为邀请和灵感的来源。
可扩展性
如上所述,Rust 语言、标准库和生态系统正在发展并变得更加成熟。我们需要投入资源来保持这些方面的平稳发展。
标准库的可演化性和修复错误
Rust 的稳定性保证使得标准库很难演化。与大多数 crate 不同,我们不能发布新的主要版本,因为那实际上相当于发布“Rust 2.0”。因此,一旦 API 稳定下来,我们就必须永远保持它,这意味着我们在稳定任何新东西时必须非常小心。
虽然我们在添加新 API 时非常小心,但仍然可能发生错误。根据目前的经验,如果可以回到过去,我们会做一些不同的事情。这些情况不多,但随着时间的推移,这些情况仍然会积累到一定程度,以至于拥有纠正过去错误的机制是有用的。
Rust 语言具有 版本 的概念,以便能够在不干扰 Rust 用户的情况下对语言本身进行重大更改。但是,库可以非常有限地使用版本来纠正错误。我们已将它们用于 panic!()
宏 和 prelude。但是,一般来说,利用版本机制进行向后不兼容的库更改非常棘手,因为不同版本的 crate 可以混合使用,同时都使用相同的标准库。
在某些情况下,即使不更改任何现有 API,添加新 API 也可能会微妙地破坏现有的 Rust 代码。例如,当一个类型获得一个新方法时,而该方法已经可以通过一个流行的 trait(例如 itertools::Itertools
或 num::Integer
)获得,就会发生这种情况。向标准库添加一个方法可能会导致现有方法调用以不同的方式解析,从而可能破坏代码。这通常被认为是“可接受的”破坏,但随着 Rust 使用量的增长,这种破坏的影响会增加,通常在实践中使得这种破坏不可接受。
因此,为了保持标准库的发展,我们希望合作开发能够缓解这些问题的语言特性
- 基于版本的 method 消除歧义
- 一种修复
Range
类型的方法,以便1..2
可以是Copy
。 - 一种在不破坏现有代码的情况下删除或改进锁中毒的方法。
- 为库提供与版本为语言提供的通用机制。
人员和协作
保持 Rust 和生态系统可扩展性的最重要因素是人:Rust 团队成员、生态系统中 crate 的维护者、审查人员、贡献者等等。重要的是,我们要继续努力改进协作方式,并尽可能让每个人都以适合他们的方式参与进来。
具体而言,我们希望致力于
- 为贡献者和审查者提供更好和更完整的指南;以及
- 与生态系统的其他部分进行更多互动。
使 std
不那么特殊 / 增强生态系统中其他 crate 的能力
标准库使用了 大量不稳定的语言特性,而生态系统中的其他 crate 不能(或不应该)使用。虽然对于 core
来说这是不可避免的,因为它包含与 Rust 内置类型相关的所有内容,但我们应该能够使 alloc
和 std
对不稳定特性的依赖性降低。也许有一天,这些库可能与生态系统中的任何其他流行 crate 没有什么不同。
这方面的大部分工作将与语言团队合作,以帮助我们将所需的不稳定语言特性转移到可以稳定的状态。
适应不同的平台
随着 Rust 的普及,它被用于越来越多的平台。Rust 标准库通过 File
和 TcpStream
等方式,在抽象 Linux 和 Windows 等流行平台之间的一些差异方面做得还不错,但是对于那些看起来不像这些平台的 target(例如 Wasm 或内核模块),我们做得不好。
例如,core
包括 f32
和 f64
,即使平台不支持浮点运算,而 std
包括 File::open
,即使它没有实现并且在您所针对的特定平台上总是失败。
为了更好地支持 Rust 所使用的不断增长的平台多样性,我们希望与语言和编译器团队合作,使标准库更容易正确支持具有非常不同需求的 target,而不会对维护者、贡献者或用户造成极大的不便
- 使 std 更容易移植到新平台,可能允许相关代码在不太流行的平台上的
rust-lang/rust
存储库之外存在。 - 一种更好的方法,可以根据平台仅允许使用
std
的一部分。例如,where Platform: Unix
边界,或类似#[cfg]
可移植性 lint 的东西。 - 一种允许在支持它的平台上使用不可移植功能的方法,例如,允许在声明仅在 64 位平台上运行的代码中,
u64
和usize
之间进行无误转换。 - 使标准库更加模块化,允许在某些平台上禁用例如浮点支持或文件系统支持。
改进和添加新 API
库团队的主要重点始终是并将始终是标准库的公共接口。从去年开始,我们甚至有一个单独的团队来对 API 更改和添加做出最终决定:库 API 团队。
Rust 有意使用最少的标准库。许多常用的功能都在生态系统中的其他 crate 中找到,而不是标准库中。
我们究竟在哪里划定应该进入标准库和不应该进入标准库的事物的界限可能很难定义,并且具有一定的灵活性,但是我们对以下几个类别最感兴趣。
人体工程学
添加到标准库的许多内容都是非常小的,可以提高人体工程学。通常,这些都是已经以某种方式实现的事情,只是不是以符合人体工程学的方式实现。最近的一些例子是
abs_diff()
Path::is_symlink
iter::from_fn
NonZero*::saturating_add
虽然我们总是必须考虑小众功能对某些类型和 trait 上已经很大的接口的权衡,但像这样的添加会继续定期发生。
标准化生态系统所需的一些更大的功能
随着 Rust 发展到新的领域,越来越需要将某些功能包含在标准库中。对于一致的、标准的接口很重要的东西尤其如此。一些更大的例子是
- 异步 trait 和函数
- 分配器和可失败的分配
- 错误和 panic 处理
- 可移植 SIMD
- 基准测试和自定义测试/基准框架
减少和改进不安全代码
通过提供正确的底层 API 和抽象,我们可以大大减少用户需要编写的复杂不安全代码的数量。像 MaybeUninit
这样的工具引导用户编写易于遵循和证明正确的不安全代码。更好的是,某些 API 可以完全消除在许多情况下对不安全代码的需求。这包括用户出于性能原因倾向于使用 unsafe
的情况。
std::arch
std::simd
- 作用域线程
- 更多原子原语
- 用于数组的静态长度的“
Iterator
” - 改进
MaybeUninit
和相关方法 - 扩展
NonNull
和指针方法 OsString
、Path
和CString
的更完整的接口Pin
和其他“不安全”类型的文档- 文件描述符(
OwnedFd
、AsFd
等)和句柄(OwnedHandle
、AsHandle
等)
改进标准库内部事物的实现
从历史上看,标准库的实现细节不如其公共 API 受关注。但是,最近,我们看到越来越多的贡献致力于改进标准库各个部分的实现。
以下是我们特别希望看到改进的一些部分
core::fmt
以及format_args!()
和fmt::Arguments
的实现- 像
Mutex
、RwLock
和Condvar
这样的同步原语 - 清理
std::sys
中特定于平台的代码 - 尽可能避免分配,例如在调用
std::fs
中的函数时 - 使广泛使用的类型 例如
std::io::Error
更加轻量化 - 清理所有不必要的
SeqCst
内存排序 - 优化线程局部变量
结论
我们希望此摘要能提供足够的灵感和兴奋感,并让您了解库团队的未来方向。如果您想提供帮助,无论是想从事实现工作、设计、文档、组织还是任何其他有用的工作,我们都热烈邀请您 参与其中!