Rust团队发布了新版本的Rust,即1.59.0。Rust是一种编程语言,它使每个人都能建立可靠和高效的软件。
今天的发布正值普京的军队突然入侵乌克兰,吸引了全世界的注意力。在讨论新的Rust版本的细节之前,我们要声明,我们与乌克兰人民站在一起,并对所有受这场冲突影响的人表示支持。
如果你已经通过rustup安装了以前的Rust版本,你可以用1.59.0获得。
rustup update stable
如果你还没有,你可以从我们网站的相应页面获得rustup,并在GitHub上查看1.59.0的详细发布说明。
1.59.0稳定版中的内容
内联汇编
Rust语言现在支持内联汇编。这使得许多需要对其执行进行非常低级的控制,或者需要访问专门的机器指令的应用程序成为可能。
例如,在为x86-64目标编译时,你现在可以写。
use std::arch::asm;
// Multiply x by 6 using shifts and adds
let mut x: u64 = 4;
unsafe {
asm!(
"mov {tmp}, {x}",
"shl {tmp}, 1",
"shl {x}, 2",
"add {x}, {tmp}",
x = inout(reg) x,
tmp = out(reg) _,
);
}
assert_eq!(x, 4 * 6);
在asm! 和global_asm!宏中用于命名寄存器的格式字符串语法与Rust格式字符串中使用的相同,所以对于Rust程序员来说,应该感到非常熟悉。
汇编语言和内联汇编可用的指令根据目标架构的不同而不同。今天,稳定的Rust编译器支持以下架构的内联汇编。
- x86和x86-64
- ARM
- AArch64
- RISC-V
你可以在Rust By Example中看到更多内联汇编的例子,并在参考文献中找到更详细的文档。
去结构化赋值
你现在可以使用元组、切片和结构模式作为赋值的左手边。
let (a, b, c, d, e);
(a, b) = (1, 2);
[c, .., d, _] = [1, 2, 3, 4, 5];
Struct { e, .. } = Struct { e: 5, f: 3 };
assert_eq!([1, 2, 1, 4, 5], [a, b, c, d, e]);
这使得赋值与let 绑定更加一致,后者长期以来一直支持同样的东西。请注意,不允许使用运算符(如+= )进行重构赋值。
构造泛型的缺省值和交织
泛型类型现在可以为它们的常量泛型指定默认值。例如,你现在可以这样写。
struct ArrayStorage<T, const N: usize = 2> {
arr: [T; N],
}
impl<T> ArrayStorage<T> {
fn new(a: T, b: T) -> ArrayStorage<T> {
ArrayStorage {
arr: [a, b],
}
}
}
以前,类型参数被要求放在所有常量参数之前。 这一限制已经被放宽,你现在可以将它们交织起来。
fn cartesian_product<
T, const N: usize,
U, const M: usize,
V, F
>(a: [T; N], b: [U; M], f: F) -> [[V; N]; M]
where
F: FnMut(&T, &U) -> V
{
// ...
}
未来的不兼容警告
有时Rust编译器中的错误会导致它接受不应该被接受的代码。这方面的一个例子是在安全代码中允许借用打包的结构域。
虽然这种情况很少发生,但当你的项目所使用的crate中的代码将不再被允许时,它可能是相当具有破坏性的。事实上,你可能不会注意到,直到你的项目莫名其妙地停止构建
现在,当一个依赖关系将被未来的Rust版本所拒绝时,Cargo会向你发出警告。在运行cargo build 或cargo check ,你可能会看到。
warning: the following packages contain code that will be rejected by a future version of Rust: old_dep v0.1.0
note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 1`
你可以运行警告中提到的cargo report 命令来查看将被拒绝的代码的完整报告。这让你有时间在它破坏你的构建之前升级你的依赖关系。
创建剥离的二进制文件
从你发布的二进制文件中剥离不必要的信息(如调试信息),使其更小,这通常是有用的。
虽然在创建二进制文件后一直可以手动操作,但现在 cargo 和 rustc 支持在二进制文件链接时进行剥离。要启用这个功能,请在你的Cargo.toml 中添加以下内容。
[profile.release]
strip = "debuginfo"
这将导致调试信息从发布的二进制文件中被剥离。你也可以提供"symbols" 或只提供true 来剥离所有支持的符号信息。
标准库通常带有调试符号和行级调试信息,所以在没有启用调试符号的情况下生成的Rust二进制文件仍然默认包括标准库的调试信息。使用strip选项可以删除这些额外的信息,产生更小的Rust二进制文件。
更多细节请参见Cargo的文档。
默认关闭增量编译
1.59.0版本默认关闭了增量编译(除非通过环境变量明确要求:RUSTC_FORCE_INCREMENTAL=1 )。这减轻了一个已知错误的影响,#94124,它可能会在开启增量编译时导致反序列化错误(和恐慌)。
对#94124的具体修复已经落地,目前在1.60测试版中,将在六周后发货。我们目前还没有意识到其他问题会促使我们决定在1.60稳定版中禁用增量编译,如果没有出现这些问题,1.60稳定版很可能会再次重新启用增量编译。在测试版和夜间版中,增量编译仍然是默认开启的。
一如既往,我们鼓励用户在夜间和测试版频道上进行测试,并报告你发现的问题:特别是对于增量错误,这是确保Rust团队能够判断是否存在故障以及影响到多少用户的最好方法。
稳定的API
以下方法和特性的实现现在已经稳定了。
std::thread::available_parallelismResult::copiedResult::clonedarch::asm!arch::global_asm!ops::ControlFlow::is_breakops::ControlFlow::is_continueTryFrom<char> for u8char::TryFromCharError实施Clone,Debug,Display,PartialEq,Copy,Eq。Erroriter::zipNonZeroU8::is_power_of_twoNonZeroU16::is_power_of_twoNonZeroU32::is_power_of_twoNonZeroU64::is_power_of_twoNonZeroU128::is_power_of_twoDoubleEndedIterator for ToLowercaseDoubleEndedIterator for ToUppercaseTryFrom<&mut [T]> for [T; N]UnwindSafe for OnceRefUnwindSafe for Once- armv8 neon intrinsics for aarch64
以下之前稳定的函数现在是const 。
mem::MaybeUninit::as_ptrmem::MaybeUninit::assume_initmem::MaybeUninit::assume_init_refffi::CStr::from_bytes_with_nul_unchecked
其他变化
在Rust 1.59.0版本中还有其他变化。请查看Rust、Cargo和Clippy的变化。
1.59.0的贡献者
很多人一起创造了Rust 1.59.0,没有你们,我们不可能做到,谢谢你们!"。