Rust 1.100.0发布:永不类型稳定及多项工具链改进

Rust 1.100.0发布,核心语言特性与工具链迎来多项改进。历经十年,永不类型正式稳定,分配器API核心部分同步进入稳定版,旨在提升软件构建的可靠性与效率。

Rust 团队正式发布 Rust 1.100.0。该版本带来了多项核心语言特性与工具链改进,旨在提升软件构建的可靠性与效率。

永不类型历经十年终稳定

已安装 Rust 的用户可通过以下命令升级至稳定版:

$ rustup update stable

新用户可访问官网获取 Rustup 并查阅 1.100.0 详细发布说明。开发者也可通过切换至 beta 或 nightly 频道参与测试,并反馈潜在问题。

Rust 1.100.0 主要更新内容

  • 永不类型(Never Type)正式稳定
  • 分配器 API 核心部分稳定
  • 新增 DropGuard API
  • 引入零大小类型构造函数
  • Cargo 支持报告未使用依赖
  • 优化 Cargo 缓存机制以减少冲突
  • Cargo 新增最低发布年龄限制功能
  • 多项标准库 API 稳定化

永不类型(!)正式稳定

历经十年及五次尝试,Rust 中的“永不”类型(Never Type,写作 !)终于进入稳定版。这一进展标志着相关长期目标的完成。

在代码中,! 代表一种无实例类型,用于表示永远不会产生值的计算分支(如终止控制流的表达式)。由于不存在属于该类型的值,Rust 允许“never-to-any”强制转换,即 ! 可以隐式转换为任何其他类型。这使得类型检查能够处理诸如 match 语句中某些分支不返回值的情况:

fn mrrrow(option: Option<u32>) {
    let value = match option {
        Some(x) => x,
        // return 的类型为 !,被强制转换为 u32,使 match 通过类型检查
        None => return,
    };
    ...
}

此前 ! 仅可在函数返回类型位置观察或使用,本版本起允许在任何类型位置显式命名 !:

fn infallible_unwrap<T>(res: Result<T, !>) -> T {
    // 此前不允许编写 Result<_, !>
    let Ok(v) = res;
    v
}

此外,Infallible 现在被定义为 ! 的类型别名。这一变更使得所有使用 Infallible 的旧 API 自动兼容 !。这也是导致 ! 稳定过程复杂的原因之一。

为实现这一统一,引入了破坏性变更:在 2015、2018 和 2021 版本中,() 在某些上下文中的行为调整为类似 !,以匹配 2024 版本的既定行为。虽然影响通常不可察觉,但在极少数情况下(如忽略泛型参数函数的返回值时)可能触发编译器对不可达代码的检测。官方已通过提前提供兼容性警告及修复受影响的公共 crate 来降低冲击,建议用户更新依赖以获取最新修复。

分配器 API 核心稳定

本版本稳定了 allocator_api 的核心组件,允许库作者定义自定义分配器,目前主要支持 Vec 和 Box。这通过新稳定的 Allocator trait 实现,是“分配器 1.0”项目的基础。未来计划扩展 API 覆盖面,支持更多集合与指针类型。

DropGuard:简化资源清理

针对需要在作用域退出时无条件执行清理逻辑的场景,Rust 引入了 core::mem::DropGuard。这是一个辅助类型,接收一个变量和一个闭包作为参数。它实现了 Deref 和 DerefMut,允许正常使用内部变量;当 guard 被 drop 时,会执行闭包并消耗变量。

DropGuard 还提供了 dismiss 方法,可在不运行析构函数的情况下释放内部变量。这有助于实现具有回滚机制的事务类 API。例如,解析器可利用其在失败时逆转状态:

use std::mem::DropGuard;
use std::num::ParseIntError;

// 尝试解析所有字符串并推入 nums。若任一解析失败,nums 保持不变。
fn parse_all(nums: &mut Vec<u32>, strings: &[&str]) -> Result<(), ParseIntError> {
    let len = nums.len();
    let mut nums = DropGuard::new(nums, move |nums| {
        nums.truncate(len); // 1. 失败时重置 vec
    });

    for s in strings {
        nums.push(s.parse()?); // 2. 若 ? 返回错误,则回滚
    }

    DropGuard::dismiss(nums); // 3. 解析成功,取消守护
    Ok(())
}

conjure_zst:构造零大小类型

随着不安全代码准则的演进,Rust 1.100 引入了 std::mem::conjure_zst。这是一种专门用于创建零大小类型(ZST)值的方法,替代了以往使用 ()、MaybeUninit::uninit().assume_init() 等技巧的做法。

对于没有大小的 inhabited 类型,其唯一可能的值是“无”。因此,该函数被标记为 unsafe。例如,PyO3 中的 Python<'py> 是一个代表持有 Python GIL 的 ZST 令牌。从空中构造此令牌可能违反保持锁的安全前提,故需显式声明不安全。

Cargo:报告未使用的依赖

未使用或仅限特定平台使用的构建依赖会拖慢编译速度。尽管 rustc 有 unused_crate_dependencies lint,但在多构建目标共享依赖时易产生误报。Cargo 现已集成此功能,能更准确地报告未使用的依赖:

warning: unused dependency `tracing-subscriber`
  --> Cargo.toml:23:1
   |
23 | tracing-subscriber.workspace = true
   | ^^^^^^^^^^^^^^^^^^
   |
   = note: `cargo::unused_dependencies` is set to `warn` by default
help: consider removing the dependency on `tracing-subscriber`

注意:该警告仅在构建可能使用依赖表条目的每个目标时出现。例如,cargo check --bin foo 不会显示未使用的 [dependencies] 警告。开发依赖也不会触发此警告,因为无法确保所有开发构建目标均已编译。此功能属于 Cargo 新的 linting 系统,可通过 [lints.cargo] 配置。

Cargo:减少缓存碰撞

不同构建配置(如 --features)可能导致 target/debug 中出现库或二进制文件的多个副本。此前因平台限制,构建配置哈希有时未能应用于文件名,导致额外的重建或错误的二进制文件引用。这在 Git worktrees 共享 build-dir 时尤为明显。

新版 Cargo 调整了目录结构,按构建步骤而非文件类型组织,并将配置哈希移至父目录,从而一致地应用哈希。这是 2025 年构建目录布局项目的里程碑,为未来的缓存垃圾回收、跨工作区缓存去重等功能奠定基础。此内部更改可能会影响依赖特定路径结构的脚本或测试,建议参考 cargo#17287 进行适配。

Cargo:最低发布年龄(依赖冷却期)

恶意软件包通常在发布后短时间内被发现。Rust 1.100 稳定了 Cargo 的 min-publish-age 功能,允许用户在依赖解析时跳过最近发布的版本,即“依赖冷却期”。可在 .cargo/config.toml 中配置:

[registry]
global-min-publish-age = "3 days"

执行 cargo update 时,Cargo 将保留较新版本并提示:

$ cargo update
    Updating crates.io index
     Locking 2 packages to highest compatible version as of min-publish-age
      Adding cc v1.11.0 (available: v1.18.0, published 3 hours ago)
      Adding clap 4.6.7 (available: 4.6.9, published 2 days ago)

如需立即更新特定包,可覆盖检查:

$ CARGO_RESOLVER_INCOMPATIBLE_PUBLISH_AGE=allow cargo update clap --precise 4.6.9
    Updating crates.io index
    Updating clap 4.6.7 -> clap 4.6.9 (published 2 days ago, minimum age 3 days)

需注意:
- 此功能依赖注册表记录的发布时间戳,缺失时间戳的版本不会被保留。
- cargo install 默认忽略此设置,但可通过指定版本号绕过。
- 冷却期可降低供应链攻击风险,但不能替代常规的依赖审查。

其他稳定化的 API

本版本还稳定了大量标准库接口,包括但不限于:

  • impl PartialEq<Cow<'_, [U]>> for Vec<T, A>
  • impl PartialEq<Cow<'_, [U]>> for &[T]
  • impl PartialEq<Cow<'_, [U]>> for &mut [T]
  • std::alloc::Allocator, Global, System 及相关 impl
  • Box::new_in, Box::from_raw_in, Box::into_raw_with_allocator 等 Box 分配器相关方法
  • Vec::new_in, Vec::with_capacity_in, Vec::from_parts_in 等 Vec 分配器相关方法
  • Child::main_thread_handle
  • impl Default for std::sync::Once
  • bool::toggle
  • Box::take, Box::map, Rc::map, Arc::map
  • impl AsRef<T> for !, impl AsMut<T> for !
  • core::mem::DropGuard, core::mem::conjure_zst
  • UnsafeCell::replace, as_ref_unchecked, as_mut_unchecked
  • str::trim_prefix, str::trim_suffix
  • [T]::trim_prefix, [T]::trim_suffix
  • Path::trim_prefix
  • Vec::from_fn
  • os::windows::process::CommandExt::show_window

评论 0

0/500

评论需审核后展示,请文明发言

💬
还没有评论,来说两句

相关阅读