Rust 团队很高兴地宣布 Rust 新版本 1.45.0。Rust 是一门赋予每个人构建可靠且高效软件能力的编程语言。
如果你之前通过 rustup 安装了 Rust 的其他版本,获取 Rust 1.45.0 非常简单,只需执行
$ rustup update stable
如果你还没有安装,可以从我们网站的相应页面获取 rustup,并在 GitHub 上查看 1.45.0 的详细发行说明。
1.45.0 稳定版有哪些内容
Rust 1.45.0 有两个值得关注的重要变化:一个修复了整数和浮点数之间转换时存在的长期不健全性问题,另一个则稳定了使得一个更流行的 web 框架能在 stable Rust 上运行所需的最后一个特性。
修复类型转换中的不健全性问题
问题 10184 最初于 2013 年 10 月提出,比 Rust 1.0 早一年半。您可能知道,rustc 使用 LLVM 作为编译器后端。当你编写这样的代码时
Rust 1.44.0 及更早版本的 Rust 编译器会生成如下所示的 LLVM-IR
define i8 @_ZN10playground4cast17h1bdf307357423fcfE(float %x) unnamed_addr #0 {
start:
%0 = fptoui float %x to i8
ret i8 %0
}
那个 fptoui 实现了类型转换,它是 “floating point to unsigned integer”(浮点数转无符号整数)的缩写。
但这里有个问题。根据文档
‘fptoui’ 指令将其浮点操作数转换为最接近的(向零舍入)无符号整数值。如果该值不能存入 ty2 中,结果将是一个 poison value(毒值)。
现在,除非你经常深入研究编译器内部,否则可能不太理解那意味着什么。它充满了术语,但有一个更简单的解释:如果你将一个很大的浮点数转换为一个很小的整数,你会得到未定义行为。
这意味着,例如,这段代码的行为并非良好定义
在 Rust 1.44.0 上,我的机器恰好打印出 "x: 0"。但它可能打印任何东西,或者做任何事情:这是未定义行为。然而,这段代码块中并没有使用 unsafe 关键字。这就是我们所说的“健全性”(soundness)错误,也就是说,这是一个编译器行为错误导致的 bug。我们在问题追踪器上将这些 bug 标记为 I-unsound,并非常重视它们。
然而,这个 bug 花了很长时间才解决。原因是当时非常不清楚正确的解决方案是什么。
最终决定按以下方式处理
as将执行“饱和转换”(saturating cast)。- 如果你想跳过检查,将添加一个新的
unsafe类型转换方法。
这与数组访问非常相似,例如
array[i]会检查以确保array至少有i + 1个元素。- 你可以使用
unsafe { array.get_unchecked(i) }来跳过检查。
那么,什么是饱和转换?让我们看一个稍微修改过的例子
这将打印出
too_big_casted = 255
too_small_casted = 0
not_a_number_casted = 0
也就是说,过大的数字会变成可能的最大值。过小的数字会变成可能得最小值(即零)。NaN 产生零。
新的不安全类型转换 API 是
let x: f32 = 1.0;
let y: u8 = unsafe ;
但一如既往,你应该只在万不得已时才使用这种方法。就像数组访问一样,编译器通常可以优化掉这些检查,当编译器能够证明安全性时,安全版本和不安全版本是等效的。
在表达式、模式和语句中稳定函数式过程宏
在 Rust 1.30.0 中,我们稳定了“item 位置的函数式过程宏”。例如,gnome-class crate
Gnome-class 是 Rust 的一个过程宏。在宏内部,我们定义了一个尽可能类似 Rust 的微型语言,它包含扩展,允许你定义 GObject 子类、它们的属性、信号、接口实现以及 GObject 的其他特性。目标是让你无需编写不安全代码。
看起来像这样
gobject_gen!
“item 位置”这个说法有点术语化,但基本上它的意思是,你只能在代码的特定位置调用 gobject_gen!。
Rust 1.45.0 增加了在三个新位置调用过程宏的能力
// imagine we have a procedural macro named "mac"
mac!; // item position, this was what was stable before
// but these three are new:
能够在更多地方使用宏很有趣,但许多 Rustaceans 长期以来一直等待这个特性还有另一个原因:Rocket。Rocket 最初于 2016 年 12 月发布,是一个流行的 Rust web 框架,常被认为是 Rust 生态系统中最好的东西之一。这是其即将发布的版本中的“hello world”示例
extern crate rocket;
直到今天,Rocket 依赖于 nightly-only 特性来兑现其灵活性和人体工程学的承诺。实际上,从项目主页上可以看到,Rocket 当前版本中的上述示例需要 proc_macro_hygiene 特性才能编译。然而,正如你从特性名称中可能猜到的那样,今天它已进入稳定版!这个 issue 记录了 Rocket 中 nightly-only 特性的历史。现在,它们都已完成!
Rocket 的下一个版本仍在开发中,但发布后,很多人会非常高兴 :)
库变更
在 Rust 1.45.0 中,以下 API 已稳定
Arc::as_ptrBTreeMap::remove_entryRc::as_ptrrc::Weak::as_ptrrc::Weak::from_rawrc::Weak::into_rawstr::strip_prefixstr::strip_suffixsync::Weak::as_ptrsync::Weak::from_rawsync::Weak::into_rawchar::UNICODE_VERSIONSpan::resolved_atSpan::located_atSpan::mixed_siteunix::process::CommandExt::arg0
此外,你可以使用 char 配合范围(ranges)来遍历码点
for ch in 'a'..='z'
println!;
// Prints "abcdefghijklmnopqrstuvwxyz"
有关完整的变更列表,请参阅完整的发行说明。
其他变更
Rust 1.45.0 版本还有其他变更:查看 Rust、Cargo 和 Clippy 的变更。
1.45.0 贡献者
许多人共同努力促成了 Rust 1.45.0。没有你们所有人的贡献,这一切是不可能完成的。感谢大家!