2411rust,1.81,1.82

1.81.0稳定版

core::error::错误

1.81稳定了核心中的Error特征,允许在#![no_std]库中使用特征.这样在相同错误特征上,可标准化更广泛的Rust生态系统,而不管库的环境.

新的排序实现

都已按新算法更新了标准库中的稳定不稳定排序实现,从而改进了它们的运行时性能和编译时间.

此外,两个新的排序算法都试检测Ord的阻止产生有意义排序结果错误实现,且现在此时会恐慌而不是返回有效随机排列的数据.

遇见这些恐慌的用户,应该审计他们的排序实现,以确保它们满足PartialOrdOrd记录的要求.

#[expect(lint)]

1.81稳定了一个新的期望检查级,它允许显式说明应有的检查,否则,则发出警告.此操作的期望用例是无论是因为检查实现错误,还是正在重构,同时想知道何时不再需要检查,来临时使检查静音.

如,如果你正在移动代码基以符合Clippy检查(如undocumented_unsafe_blocks)强制的新限制,则你可在转换时使用#[expect(clippy::undocumented_unsafe_blocks)],确保一旦记录了所有不安全的块,就可选择拒绝检查来它.

Clippy还有两个检查来强制使用此功能,并帮助移动现有属性:

1,clippy::allow_attributes在支持#[expect]或移动#[allow]属性到#[expect]时,限制允许属性.

2,clippy::allow_attributes_without_reason要求#[allow]属性的原因.

检查原因

更改检查级一般事出有因.如,如果在不支持浮点的环境中,运行代码,你可用Clippy#![deny(clippy::float_arithmetic)]来检查.

但是,如果项的新开发者看到此检查触发,他们需要查找(想)拒绝中解释加它的原因的评论.在Rust1.81中,可直接在编译器消息通知他们:

错误:检测到浮点运算:
-->src/lib.rs:4:5

|
4|a+b

|^^^^^

|

=帮助:有关更多信息,请访问https://rustlang.github.io/rustclippy/master/index.html#float_arithmetic

=注意:不支持硬件浮点数

注意:在此处定义检查

-->src/lib.rs:1:9

|
1|#![deny(clippy::float_arithmetic,reason="不支持硬件浮点数")]

|^^^^^^^^^^^^^^^^^^^^^^^^

稳定的API

cpp 复制代码
core::error
hint::assert_unchecked
fs::exists
AtomicBool::fetch_not
Duration::abs_diff
IoSlice::advance
IoSlice::advance_slices
IoSliceMut::advance
IoSliceMut::advance_slices
PanicHookInfo
PanicInfo::message
PanicMessage

这些API现在在环境中是稳定的:

cpp 复制代码
char::from_u32_unchecked (function)
char::from_u32_unchecked (method)
CStr::count_bytes
CStr::from_ptr

兼容说明

分割恐慌勾挂和恐慌处理器参数

已重命名std::panic::PanicInfostd::panic::PanicHookInfo.继续按别名使用旧名,但从Rust1.82.0开始会导致弃用警告.

但是,core::panic::PanicInfo将不变,因为现在这是个不同类型.

原因是这些类不同角色:std::panic::PanicHookInfostd环境中恐慌勾挂的参数(恐慌可有任意负载),而core::panic::PanicInfo是在非标准(#![no_std])环境中#[panic_handler]的参数(其中恐慌总是带格式化的消息).

分离这些类允许为这些类添加更多有用的方法,如std::panic::PanicHookInfo::payload_as_str()core::panic::PanicInfo::message().

extern"C"函数中中止未抓的恐慌

这完成了从1.71开始的期望跨ABI边界展开时(在其他-展开变量)添加了特有的"C展开"ABI转换.从1.81开始,非展开ABI(如,"C")现在会在未抓的展开中止,从而解决长期健壮性问题.

依赖展开的程序应,转而使用-展开后缀的ABI变量.

已更改WASI0.1目标命名

使用wasm32wasi目标(以WASI0.1为目标)现在发出编译器警告,并要求用户切换wasm32wasip1目标.两个目标是相同的,只是重命名了wasm32wasi,更改WASI目标,是为了在2025年1月删除wasm32wasi.

修复CVE-2024-43402

现在,在窗口上,调用批处理文件时,如果有窗口会忽略和去掉的尾空格或句点,则std::process::Command正确转义参数.

1.82.0稳定版

货物信息

Cargo现在有一个信息子命令来显示注册表中包的信息.

如,以下是可见的cargo info cc:

cpp 复制代码
cc #build-dependencies

版本:1.1.23(最新1.1.30)

许可:MITApache-2.0
Rust版本:1.63

文档:https://docs.rs/cc

主页:https://github.com/rustlang/ccrs

仓库:https://github.com/rustlang/ccrs
crates.io:https://crates.io/crates/cc/1.1.23

特征:

作业服务器=[]

并行=[dep:libc,dep:jobserver]

注意:要查看如何依赖CC,请运行cargo tree --invert --package cc@1.1.23

默认,如果有,cargo-info描述本地Cargo.lock中的包版本.如见,它也会指示何时有更新的版本,而cargo info cc@1.1.30会报告它.

促进苹果

64ARM上的macOS现在是第1层

Mac,Catalyst目标现在是第2层

精确捕捉使用<..>语法

Rust现在支持在某些impl Trait约束内,用use<..>语法来控制抓哪些泛型生命期参数.

Rust中的返回位置实现特征(RPIT)类型抓某些泛型参数.它允许在隐藏类型中使用该泛型参数.这反之又会影响借用检查.

Rust2021更早版本中,除非在暗类型按语法形式提及这些生命期参数,否则不会在裸函数和固有实现函数和方法按暗类型生命期参数.

如,这是个错误:

cpp 复制代码
//@版本`:2021`
fn f(x: &()) -> impl Sized { x }

有了新的use<..>语法,可按错误中的建议解决它,方法是写:

cpp 复制代码
fn f(x: &()) -> impl Sized + use<'_> { x }

以前,正确修复此类错误需要定义一个虚特征(一般叫),并如下使用它:

cpp 复制代码
trait Captures<T: ?Sized> {}
impl<T: ?Sized, U: ?Sized> Captures<T> for U {}

fn f(x: &()) -> impl Sized + Captures<&'_ ()> { x }

现在不再需要它.

有个经常使用的叫"超期技巧"的不太正确但更方便的方法来解决它.编译器甚至之前建议这样做.该技巧如下:

cpp 复制代码
fn f(x: &()) -> impl Sized + '_ { x }

在此简单用例时,如在RFC3498中解释,该技巧完全等价于+use<'_>.但是,实际情况下,这会过度约束返回的类型的约束,从而导致问题.

如,考虑以下Rust编译器中真实案例代码:

cpp 复制代码
struct Ctx<'cx>(&'cx u8);
fn f<'cx, 'a>(
    cx: Ctx<'cx>,
    x: &'a u8,
) -> impl Iterator<Item = &'a u8> + 'cx {
    core::iter::once_with(move || {
        eprintln!("LOG: {}", cx.0);
        x
    })
    //~^错误,生命期可能不够长
}

无法删除+'cx,因为在隐藏类型中用生命期,因此必须抓它.也不能添加'a:'cx约束,因为这些生命期实际上无关,且一般'a不一定比'cx活得更久.

但是,如果写成+use<'cx,'a>,这工作并有正确的约束.

今天稳定的东西还有一些限制.用<..>语法当前不能出现在特征特征实现中(但注意,默认已抓了域内生命期参数),且它必须列举所有域内的泛型类型参数.期望未来取消这些限制.

注意,在Rust2024中,上述示例无需用用<..>语法(或技巧)就"正常"工作.这是因为在新版本中,暗类型自动抓域内所有生命期参数.

这是个更好的默认值.在Rust2024中,用<..>语法是选出该默认值的重要方式.

创建原始指针本地语法

不安全代码有时必须处理可能挂起,可能未对齐或可能指向无效数据指针.此常见情况repr(packed)结构.

此时,要避免创建引用,因为这会导致未定义行为.即不要用一般的&&mut符号,因为它们会创建一个引用,即使立即按原始指针转换引用,也太晚了,无法避免未定义行为.

几年来,std::ptr::addr_of!std::ptr::addr_of_mut!宏用于该目的.现在该为此操作提供适当的本地语法了:addr_of!(expr)变为&raw const expr,而addr_of_mut!(expr)变为&raw mut expr.如:

cpp 复制代码
#[repr(packed)]
struct Packed {
    not_aligned_field: i32,
}
fn main() {
    let p = Packed { not_aligned_field: 1_82 };
    //这是未定义行为!编译器拒绝它.`let ptr=&p.not_aligned_fieldas*const i32;`这是创建指针的旧方法.
    let ptr = std::ptr::addr_of!(p.not_aligned_field);
    //这就是新的方式.
    let ptr = &raw const p.not_aligned_field;
    //访问指针不变.注意,因为指针未对齐,`'val=*ptr'`是未定义行为!
    let val = unsafe { ptr.read_unaligned() };
}

本地语法更清楚地表明,按位置式解释这些符号的操作数式.还避免了在创建指针时使用"的地址"术语.

指针不仅是个地址,因此Rust正在摆脱像重申了指针地址错误等价性"的地址"此术语.

带不安全的安全对象

Rust代码可用外部代码函数和静态数据.在块中提供,这些外部项类型签名.历史上,块中的所有项用起来都是不安全的,但不必在自身编写不安全.

但是,如果块中的签名错误,则使用该项会导致未定义行为.那是写块的人的错,还是用该项的人的错?

已决定编写块的人,负责确保其中包含的所有签名都是正确的,因此现在允许编写不安全的:

cpp 复制代码
unsafe extern {
    pub safe static TAU: f64;
    pub safe fn sqrt(x: f64) -> f64;
    pub unsafe fn strlen(p: *const u8) -> usize;
}

一个好处是,可按安全使用标记不安全的块中的项.在上例中,可无需使用不安全,就调用sqrt或读取TAU.

不安全保守假设无安全不安全标记的项.

在未来发布中,鼓励与检查一起,使用不安全.从Rust2024开始,会要求不安全 外.

不安全属性

一些Rust属性,如no_mangle,可用来在没有不安全块时,导致未定义行为.如果这是普通代码,会要求在不安全的{}块中放置它们,但当前,属性还没有类似的语法.

为了反映这些属性可能会破坏Rust的安全保证,它们现在是"不安全的",应该如下:

cpp 复制代码
#[unsafe(no_mangle)]
pub fn my_global_function() { }

当前仍接受该属性的旧形式(没有不安全),但可能会在未来反对它,且在Rust2024中将是个硬性错误.

这会影响以下属性:

cpp 复制代码
no_mangle
link_section
export_name

在匹配模式中省略空类型

现在可以省略按值匹配空(又名无人区)类型的模式:

cpp 复制代码
use std::convert::Infallible;
pub fn unwrap_without_panic<T>(x: Result<T, Infallible>) -> T {
    let Ok(x) = x; //`'Err'`情况不需要出现
    x
}

这适合空类型,如无变量枚举 Void{},或带可见空字段且无#[non_exhaustive]属性的结构和枚举.它与尽管当前仍不稳定的永不!类型结合使用时也特别有用.

有时,必须写空模式.因为未初化值和不安全代码,如果通过引用,指针或联字段访问空类型,则禁止省略模式:

cpp 复制代码
pub fn unwrap_ref_without_panic<T>(x: &Result<T, Infallible>) -> &T {
    match x {
        Ok(x) => x,
        //因为引用,不能省略此分支
        Err(infallible) => match *infallible {},
    }
}

为了避免干扰想支持多个Rust版本的,有空模式的匹配项,尽管可删除它们,但尚未按"不可达"警告报告.

浮点非数语义和

对(f32f64类型)浮点值的运算,是出了名的微妙.原因之一是有用来表示0.0/0.0的结果的NaN(非数)值.

非数值之所以微妙,是因为有多个可能非数值.非数值有一个(可用f.is_sign_positive()检查)符号和一个(可用f.to_bits()提取的)负载.

但是,==完全忽略非数值符号和负载(总是返回).尽管在跨硬件架构标准化浮点运算的行为方面非常成功,但非数何时为正或负及其确切负载的细节架构而异.

更复杂的是,当保证精确数字结果不变时,Rust及其LLVM后端优化浮点运算,但这些优化可改变生成的非数值.

如,f*1.0可优化为仅f.但是,如果f非数,则会改变结果的确切位模式!

在该版本中,标准化了Rust非数值的行为方式的一组规则.它不是完全确定性的,即(0.0/0.0).is_sign_positive()等操作的结果可能会因硬件架构,优化级和周围代码而异.

为了可移植,代码应避免使用to_bits,且应使用f.signum()==1.0而不是f.is_sign_positive().

但是,精心选择这些规则,仍允许在Rust代码中实现高级数据表示技术,如非数装箱.

更多细节,见文档.

确定非数值的语义后,该版本还允许在const fn中使用浮点运算.

因此,像(0.0/0.0).is_sign_positive()此操作(在Rust1.83中是常稳定)在编译时和运行时时可能会产生不同结果.这不是漏洞,代码不能依赖总是产生完全相同结果const fn.

作为汇编立即数的常数

汇编操作数,现在无需先在寄存器保存它们,而按立即数用整数.如,实现一个syscall手动:

cpp 复制代码
const WRITE_SYSCALL: c_int = 0x01; //`syscall1`是`'写'`,
const STDOUT_HANDLE: c_int = 0x01; //`'stdout'`有文件句柄1
const MSG: &str = "Hello, world!\n";
let written: usize;
//签名:`ssize_t write(int fd, const void buf[], size_t count)`
unsafe {
    core::arch::asm!(
         "mov rax, {SYSCALL} "//`rax`保存系统调用号,
        "mov rdi, {OUTPUT} " //`"rdi`为`"fd"`(第一个参数)",
        "mov rdx, {LEN} "    //`rdx`为`"count"`(第三个参数)",
        "syscall        "    //调用`syscall`",
        "mov {written}, rax "//保存返回值",
        SYSCALL = const WRITE_SYSCALL,
        OUTPUT = const STDOUT_HANDLE,
        LEN = const MSG.len(),
        in("rsi") MSG.as_ptr(), //`rsi`是`'buf*'`(第二个参数)
        written = out(reg) written,
    );
}
assert_eq!(written, MSG.len());

输出:

世界你好!
玩耍地方链接.

上面代码中,如LEN=const MSG.len()之类的语句使用带MSG.len()值的立即数填充LEN格式限定符.可在生成的汇编中看到(值为14):

cpp 复制代码
lea     rsi, [rip + .L__unnamed_3]
mov     rax, 1    //`rax`保存系统调用号,
mov     rdi, 1    //`"rdi`为`"fd"`(第一个参数)",
mov     rdx, 14   //`rdx`为`"count"`(第三个参数)",
syscall //调用`syscall`"
mov     rax, rax  //"保存返回值"

更多细节,见引用.

安全地处理不安全的静态数据

现在允许以下代码:

cpp 复制代码
static mut STATIC_MUT: Type = Type::new();
extern "C" {
    static EXTERN_STATIC: Type;
}
fn main() {
     let static_mut_ptr = &raw mut STATIC_MUT;
     let extern_static_ptr = &raw const EXTERN_STATIC;
}

式环境中,STATIC_MUTEXTERN_STATIC放置.以前,编译器的检查安全不知道原引用符号实际上并不会影响操作数的位置,而是按读写指针对待它.

但是,实际上没有不安全因子,因为它只是创建一个指针.

放松会导致问题,如果拒绝unused_unsafe检查,现在会按未使用报告一些不安全的块,但现在仅在旧版本上用它们.

如果想支持多个版本Rust,与该示例一样,请用#[allow(unused_unsafe)]注解这些不安全的块:

cpp 复制代码
 static mut STATIC_MUT: Type = Type::new();
 fn main() {
+    #[allow(unused_unsafe)]
     let static_mut_ptr = unsafe { std::ptr::addr_of_mut!(STATIC_MUT) };
 }

稳定的API

cpp 复制代码
std::thread::Builder::spawn_unchecked
std::str::CharIndices::offset
std::option::Option::is_none_or
[T]::is_sorted
[T]::is_sorted_by
[T]::is_sorted_by_key
Iterator::is_sorted
Iterator::is_sorted_by
Iterator::is_sorted_by_key
std::future::Ready::into_inner
std::iter::repeat_n
impl<T: Clone> DoubleEndedIterator for Take<Repeat<T>>
impl<T: Clone> ExactSizeIterator for Take<Repeat<T>>
impl<T: Clone> ExactSizeIterator for Take<RepeatWith<T>>
impl Default for std::collections::binary_heap::Iter
impl Default for std::collections::btree_map::RangeMut
impl Default for std::collections::btree_map::ValuesMut
impl Default for std::collections::vec_deque::Iter
impl Default for std::collections::vec_deque::IterMut
Rc<T>::new_uninit
Rc<T>::assume_init
Rc<[T]>::new_uninit_slice
Rc<[MaybeUninit<T>]>::assume_init
Arc<T>::new_uninit
Arc<T>::assume_init
Arc<[T]>::new_uninit_slice
Arc<[MaybeUninit<T>]>::assume_init
Box<T>::new_uninit
Box<T>::assume_init
Box<[T]>::new_uninit_slice
Box<[MaybeUninit<T>]>::assume_init
core::arch::x86_64::_bextri_u64
core::arch::x86_64::_bextri_u32
core::arch::x86::_mm_broadcastsi128_si256
core::arch::x86::_mm256_stream_load_si256
core::arch::x86::_tzcnt_u16
core::arch::x86::_mm_extracti_si64
core::arch::x86::_mm_inserti_si64
core::arch::x86::_mm_storeu_si16
core::arch::x86::_mm_storeu_si32
core::arch::x86::_mm_storeu_si64
core::arch::x86::_mm_loadu_si16
core::arch::x86::_mm_loadu_si32
core::arch::wasm32::u8x16_relaxed_swizzle
core::arch::wasm32::i8x16_relaxed_swizzle
core::arch::wasm32::i32x4_relaxed_trunc_f32x4
core::arch::wasm32::u32x4_relaxed_trunc_f32x4
core::arch::wasm32::i32x4_relaxed_trunc_f64x2_zero
core::arch::wasm32::u32x4_relaxed_trunc_f64x2_zero
core::arch::wasm32::f32x4_relaxed_madd
core::arch::wasm32::f32x4_relaxed_nmadd
core::arch::wasm32::f64x2_relaxed_madd
core::arch::wasm32::f64x2_relaxed_nmadd
core::arch::wasm32::i8x16_relaxed_laneselect
core::arch::wasm32::u8x16_relaxed_laneselect
core::arch::wasm32::i16x8_relaxed_laneselect
core::arch::wasm32::u16x8_relaxed_laneselect
core::arch::wasm32::i32x4_relaxed_laneselect
core::arch::wasm32::u32x4_relaxed_laneselect
core::arch::wasm32::i64x2_relaxed_laneselect
core::arch::wasm32::u64x2_relaxed_laneselect
core::arch::wasm32::f32x4_relaxed_min
core::arch::wasm32::f32x4_relaxed_max
core::arch::wasm32::f64x2_relaxed_min
core::arch::wasm32::f64x2_relaxed_max
core::arch::wasm32::i16x8_relaxed_q15mulr
core::arch::wasm32::u16x8_relaxed_q15mulr
core::arch::wasm32::i16x8_relaxed_dot_i8x16_i7x16
core::arch::wasm32::u16x8_relaxed_dot_i8x16_i7x16
core::arch::wasm32::i32x4_relaxed_dot_i8x16_i7x16_add
core::arch::wasm32::u32x4_relaxed_dot_i8x16_i7x16_add

这些API现在在环境中是稳定的:

cpp 复制代码
std::task::Waker::from_raw
std::task::Context::from_waker
std::task::Context::waker
$integer::from_str_radix
std::num::ParseIntError::kind
相关推荐
Rust研习社7 小时前
开源项目里的 deny.toml 是什么?
后端·rust·编程语言
铭毅天下13 小时前
当搜索引擎遇上 Rust——深度解读下一代实时搜索引擎 INFINI Pizza
开发语言·后端·搜索引擎·rust
咸甜适中13 小时前
rust语言学习笔记Trait之Default(默认值)
笔记·学习·rust
容智信息1 天前
AI Agent(智能体)的输出格式应该从 Markdown 转向 HTML吗?
前端·人工智能·rust·编辑器·html·prompt
Rust研习社2 天前
Rust Clippy 实用指南:写出更优雅、安全的 Rust 代码
后端·rust·编程语言
yangyongdehao302 天前
两天用AI+rust撸了一款本地批量去水印软件,30MB,效果能打
ai作画·rust
nudt_qxx2 天前
NVIDIA 正式开源cuda-oxide!Rust 编写 CUDA 内核新范式!
rust
小杍随笔3 天前
【Rust桌面革命:Tauri×Dioxus——架构对决、实战拆解与2026选型杀招】
开发语言·架构·rust
whinc3 天前
Rust技术周刊 2026年第17周
后端·rust