【独家】Rust 1.70.0:详解新版本的亮点与变化
语言更新:
放宽了 asm! 操作数的排序规则。
在 Rust 1.70.0 的版本更新中,对于 asm!
操作数的排序规则进行了放宽。具体的更改可以在这个 PR链接[1] 中查看。在之前的版本中,asm!
宏的操作数需要按照严格的顺序进行排序,这在某些情况下可能会导致使用上的不便。在新的版本中,这个规则被放宽,提高了 asm!
宏的灵活性和易用性。
允许宏展开的 format_args 调用使用捕获。
在 Rust 1.70.0 的更新中,允许宏展开的 format_args
调用使用捕获。这个更新主要是关于 Rust 的宏系统。
在 Rust 中,宏(macro)是一种在编译时进行代码扩展的方式。format_args
是一个内建的宏,它可以接受一系列参数,并将它们格式化为一个字符串。
"允许宏展开的 format_args
调用使用捕获" 这个更新的含义是,当 format_args
宏在其宏体中使用变量时,这些变量现在可以是外部作用域中的变量,这就是所谓的 "捕获"。这意味着 format_args
宏现在可以访问并使用其外部环境中的变量,这在以前可能是不允许的。
这个更新可能会使得使用 format_args
宏更加灵活和强大,因为它可以更好地与其周围的代码环境交互。
对有歧义的全局重新导出进行了 lint 检查。
这是关于 Rust 的一个 Pull Request,标题为 "Lint ambiguous glob re-exports",由 jieyouxu 提出,目标是解决问题 #107563。
这个 Pull Request 试图解决的问题是,当两个名称被特定地重新导出时,即不是来自全局导出,我们目前已经发出错误信息。这个 PR 试图对涉及全局导出的模糊重新导出发出默认拒绝的警告。
在讨论过程中,petrochenkov 建议将此诊断从硬错误更改为默认拒绝的警告,以便我们可以通过 crater 运行它并查看结果。jieyouxu 对此进行了修改,并将其变成了默认拒绝的警告。
最终,这个 Pull Request 被合并到了 Rust 的主分支中。
对 let _ = expr 位置的表达式进行了 const 和 unsafe 检查。
在 Rust 中,"let _ = expr" 是一种忽略表达式的结果的常见方式。这种形式的声明通常用于你不关心表达式的结果,但仍希望表达式被执行的情况,例如,当表达式有副作用(如打印输出或修改全局状态)时。
"const" 和 "unsafe" 是 Rust 的两个关键字。"const" 用于定义常量或常量函数,而 "unsafe" 用于标记不受 Rust 常规安全检查约束的代码块。
这个 PR #102256[2] 主要解决了在 let _ = expr
位置的表达式进行 const
和 unsafe
检查的问题。
在 Rust 中,let _ = expr
是一种常见的用法,用于忽略表达式的结果。然而,这种用法在某些情况下可能会导致问题。例如,如果 expr
是一个 const
或 unsafe
表达式,那么在 let _ = expr
的位置,这个表达式可能会被忽略,导致 const
或 unsafe
的检查被跳过。
为了解决这个问题,这个 PR 引入了一个新的 PlaceMention
语句,专门用于处理那些既不引入绑定也不指定类型的匹配。这样,即使在 let _ = expr
的位置,expr
的 const
和 unsafe
检查也能被正确地执行。
这个改动对于 Rust 的安全性检查有重要的意义,因为它确保了 const
和 unsafe
的检查不会因为 let _ = expr
的用法而被忽略。
在 Rust 中,PlaceMention
是一个内部的编译器概念,用于表示一个位置(Place)在代码中的使用方式。这个位置可以是一个变量、一个字段、一个数组元素等等。
在 Rust 中,`PlaceMention`[3] 是编译器内部 StatementKind
枚举的一种变体。StatementKind
枚举表示 MIR(中间表示)中可以出现的各种语句。PlaceMention
用于保留与通配符绑定匹配的 scrutinee 的痕迹。这对于 let _ = PLACE;
这样的绑定特别有用,这些绑定解构为单个 PlaceMention(PLACE)
。
在运行时,PlaceMention
计算给定的位置,但然后丢弃它而不进行加载。如果位置不指向活动内存,那么这是未定义行为。
这里 "Scrutinee" 是一个术语,通常用于描述在模式匹配中被检查的表达式(即,待匹配对象)。例如,在 match
语句中,我们会说 "match 表达式是 scrutinee"。在这种情况下,"scrutinee 的痕迹" 可能是指在模式匹配过程中保留 scrutinee 的某种信息或状态。
在 let _ = PLACE;
这样的语句中,PLACE
就是 scrutinee,PlaceMention
用于保留 scrutinee 的痕迹,即使它被通配符 _
绑定并且其值被丢弃。这可能对于某些类型的分析或优化是有用的,例如,确定 scrutinee 是否被使用,或者在哪里被使用。
编译器更新:
扩展了 -Cdebuginfo 的新选项和命名别名,为只需要行号信息的情况提供了更小的 debuginfo(-Cdebuginfo=line-tables-only),这可能最终成为 -Cdebuginfo=1 的默认级别。
这个 PR[4] 扩展了 -Cdebuginfo
的新选项和命名别名。原来的 -Cdebuginfo=1
选项并不仅仅是行表,由于向后兼容性问题,无法改变这一点。这个 PR 对此进行了澄清,并添加了一个只发出行表的选项。此外,还添加了一个只发出行信息指令的选项,这对于一些目标(如 nvptx)是必需的。现在的 debuginfo 选项应该与 clang 的 debuginfo 选项行为类似。
新的选项和别名包括:
0
或none
: 没有任何调试信息(默认)。line-directives-only
: 仅有行信息指令。对于 nvptx* 目标,这将启用性能分析[5]。对于其他用例,line-tables-only
是更好、更兼容的选择。line-tables-only
: 仅有行表。生成最小量的调试信息,用于带有文件名/行号信息的回溯,但不包括其他任何信息,即没有变量或函数参数信息。1
或limited
: 没有类型或变量级别信息的调试信息。2
或full
: 完整的调试信息。
这些选项和别名提供了更多的灵活性,以便开发者可以根据他们的需求选择适当的调试信息级别。 这些改变已经通过了 FCP,并且帮助解决了 #109311 和 #104968 的问题
对 Box::new 进行了 unused_allocation
lint 。
这个 PR #104363[6] 对 Box::new
进行了 unused_allocation
lint。在此之前,这个 lint 只针对 box 语法,这种语法可能永远不会稳定,所以这个 lint 的用处非常有限。现在,这个 lint 对 Box::new
也有效,这意味着像下面这样的代码将会触发 lint:
Box::new([1, 2, 3]).len();
f(&Box::new(1)); // where f : &i32 -> ()
而首先将 box 存储在变量中的代码则不会触发 lint:
let boxed = Box::new([1, 2, 3]); // no lint
boxed.len();
这个改变可能会影响到大量的用户,因为它扩大了 lint 的范围。但是,这个 PR 已经被合并,所以这个改变已经在 Rust 1.70.0 中生效。
在 const eval 中提前检测到了无法实例化的类型。
在这个 PR[7] 中,Rust 1.70.0 版本在 const eval(常量求值)中提前检测到了无法实例化的类型。这是一个破坏性的改变,因为一些在 const eval 期间的未定义行为(UB)现在被检测到,而不是被默默地忽略。用户可以通过 -Zextra-const-ub-checks
标志或者在他们的代码上运行 miri(默认设置该标志)来看到这个和可能导致未来破坏的其他 UB。
具体来说,现在我们在 const eval 期间拒绝以下代码:
#[derive(Copy, Clone)]
pub struct ChildStdin {
inner: AnonPipe,
}
#[derive(Copy, Clone)]
enum AnonPipe {}
const FOO: () = {
union Foo {
a: ChildStdin,
b: (),
}
// rust_errors error[E0080]: evaluation of constant value failed
let x = unsafe { Foo { b: () }.a };
};
在以前,这段代码会被接受,现在则报错。
将 LLD 作为 {arm,thumb}v4t-none-eabi
的默认链接器。
这个更新是关于 Rust 1.70.0 版本中的一项改动。在这个改动中,LLD 链接器被设定为 {arm,thumb}v4t-none-eabi
目标的默认链接器。LLD 是 LLVM 项目的一部分,是一个高性能的通用链接器。
在 LLVM 16 的更新中,LLD 获得了对 ARMv4t 的支持。因此,Rust 项目决定将其设为 {arm,thumb}v4t-none-eabi
目标的默认链接器,这样用户就不需要安装外部链接器了。这个改动已经被合并到 Rust 语言的主分支中。
这个改动的目的是为了提高 Rust 在 {arm,thumb}v4t-none-eabi
目标上的构建效率和便利性。在这之前,用户可能需要手动安装并配置外部链接器来构建这个目标。现在,由于 LLD 已经成为默认链接器,用户可以更方便地进行构建。
添加了
loongarch64-unknown-linux-gnu
的第三方目标。 关于loongarch64-unknown-linux-gnu
的添加,这是一个针对龙芯架构的Linux GNU系统的Rust编译器和标准库的支持。这意味着Rust现在可以在这种特定的硬件和操作系统配置上运行和编译代码。这个改动包括了对Rust编译器的修改,以及对标准库的一些调整,以确保它们可以在这种系统上正确工作。这是Rust对更多硬件和操作系统的支持的一部分。添加了 i586-pc-nto-qnx700(QNX Neutrino RTOS,版本 7.0)的第三方目标。
“注意:QNX Neutrino RTOS 是黑莓 QNX 系统,据悉,哪吒汽车与黑莓公司建立合作关系 哪吒S将搭黑莓QNX系统。这意味着 QNX 平台正在准备构建 Rust 工具链支持。 关于
i586-pc-nto-qnx700
的添加,这是针对QNX Neutrino RTOS版本7.0的x86 32位目标的Rust编译器和标准库的支持。这意味着Rust现在可以在这种特定的硬件和操作系统配置上运行和编译代码。这个改动包括了对Rust编译器的修改,以及对标准库的一些调整,以确保它们可以在这种系统上正确工作。这是Rust对更多硬件和操作系统的支持的一部分。
插入了对指针解引用的对齐检查作为调试断言,这可以在运行时捕获未定义的行为,并可能导致现有代码失败。