2311rust,到38版本更新
1.35.0
稳定版
此版本亮点
是分别为Box<dyn FnOnce>
,Box<dyn FnMut>
和Box<dyn Fn>
实现了FnOnce,FnMut
和Fn
闭包特征.
此外,现在可按不安全的函数指针
转换闭包
.现在也可无参
调用dbg!
.
为Box<dyn Fn*>
实现Fn*
装饰特征.
以前,如果要调用在盒子闭包中存储
的函数,因为Box<dyn FnOnce>
等实例没有
实现相应的Fn*
特征,则必须使用FnBox
.
此版本中,可使用盒子
函数.
以下代码
现在可工作了:
fn foo(x: Box<dyn Fn(u8) -> u8>) -> Vec<u8> {
vec![1, 2, 3, 4].into_iter().map(x).collect()
}
此外,现在可直接调用Box<dyn FnOnce>
对象:
fn foo(x: Box<dyn FnOnce()>) {
x()
}
强制闭包
为不安全的fn
指针
从Rust1.19.0
开始,可把未从环境中抓的闭包
转换为函数指针
.如,可编写:
fn twice(x: u8, f: fn(u8) -> u8) -> u8 {
f(f(x))
}
fn main() {
assert_eq!(42, twice(0, |x| x + 21));
}
但是,并未扩展到不安全
函数指针.有了该版本
的Rust
,现在可以这样做了.如:
//安全不变量是传递的"`不安全 fn"`指针的不变量.
unsafe fn call_unsafe_fn_ptr(f: unsafe fn()) {
f()
}
fn main() {
//安全性:没有不变量.装饰静态禁止不安全.
unsafe {
call_unsafe_fn_ptr(|| {
dbg!();
});
}
}
无参调用dbg!()
该宏
允许用环境
快速检查
某些式的值.如,运行时:
fn main() {
let mut x = 0;
if dbg!(x == 1) {
x += 1;
}
dbg!(x);
}
...会看见:
[src/main.rs:4] x == 1 = false
[src/main.rs:8] x = 0
如上,调用call_unsafe_fn_ptr
高级函数,现在也可不传递参数调用dbg!
.在跟踪
应用选取
分支时非常有用
.如,用:
fn main() {
let condition = true;
if condition {
dbg!();
}
}
...你会看到:
[src/main.rs:5]
稳定库
复制浮点数
的A
符号到B
符号上
本版本中,已添加copysign
新方法到f32
和f64
浮点原语类型
中:
f32::copysign
f64::copysign
即,可用它复制A数字
的符号
到B
数字上.如:
fn main() {
assert_eq!(3.5_f32.copysign(-0.42), -3.5);
}
检查Range
是否包含值
Rust1.35.0
在Range
类型上包含了一些新创建
方法:
Range::contains
RangeFrom::contains
RangeTo::contains
RangeInclusive::contains
RangeToInclusive::contains
现在,可轻松检查
给定值是否在某个域
内.如,可编写:
fn main() {
if (0..=10).contains(&5) {
println!("Five is included in zero to ten.");
}
}
把借用的RefCell
值映射并拆分为两部分
现在可为借入数据
的不同组件,映射并拆分多个借用值
,来借用RefCell
值:
Ref::map_split
RefMut::map_split
通过闭包替换RefCell
的值
在RefCell
上replace_with
的方便方法
:
RefCell::replace_with
有了它,可舒适映射和替换
单元格的当前值
,并因取回旧值
.
按地址(而不是值)哈希处理指针或引用
引入了:
ptr::hash
此函数
取原始指针
并哈希处理它.使用ptr::hash
,可避免哈希引用值
,而是哈希地址
.
复制Option<&T>
的内容
从Rust1.0.0
开始,Option<&T>
的Option::cloned
方法和Option<&mutT>
就允许你在Some(_)
时克隆内容.
然而,克隆
有时很贵,而opt.cloned()
方法没有提供提示.
在该版本的Rust
中:
对Option<&T>
和Option<&mut;T>
,引入了Option::copied
.
opt.copied()
的功能与opt.cloned()
的功能相同.但是,调用该方法需要T:Copy
.使用
此方法,可确保在T
不再实现Copy
时,代码
停止编译.
更改Clippy
Clippy
添加了一个新的drop_bounds
检查.把绑定的T:Drop
添加到泛型
函数时,会触发此检查
.如:
fn foo<T: Drop>(x: T) {}
绑定T:Drop
几乎总是个错误
,因为它排除了有很简单
胶水的u8
等类型.此外,T:Drop
并没有直接考虑像String
类没有有趣析构器
行为的类型,而是按嵌入类型(如Vec<u8>
)等有有趣
的析构器行为
.
除了drop_bounds
之外,此版本的Clippy
还将lintredundant_closure
拆分为redundant_closure
和redundant_closure_for_method_calls
.
1.36.0
稳定版
在Rust1.36.0
中,稳定了Future
!
稳定了未来
,给重要的crate
,库和生态系统
时间来准备async/.await
.
alloc
是稳定的
在1.36.0
之前,标准库由std,core
和proc_macro
仓库组成.核心仓库
提供了Iterator
和Copy
等核心功能,也可在#![no_std]
环境中用,因为它没有强加要求.
同时,std
仓库提供了Box<T>
和OS
功能等类型
,但要求全局
分配器和其他OS
功能为基础.
从Rust1.36.0
开始,依赖全局
分配器的std
部分,如Vec<T>
,现在可在alloc
仓库中使用.
然后,标准
仓库会重新导出
这些部件.虽然#![no_std]
使用alloc
的二进制文件仍需要每晚的Rust
,#![no_std]
库可在稳定的Rust
中使用alloc
仓库.
同时,普通没有#![no_std]
的二进制文件
,可依赖此仓库.来支持用alloc
支持#![no_std]
.
#![no_std]
extern crate alloc;
use alloc::vec::Vec;
MaybeUninit<T>
而不是mem::uninitialized
已稳定下来MaybeUninit<T>
类型.它不应假设MaybeUninit<T>
是正确初化的T
.
因此,可更安全
地渐进式初化
,并在确定maybe_t:MaybeUninit<T>
包含初化的T
后最终使用.assume_init()
.
因为MaybeUninit<T>
更安全,将弃用mem::uninitialized
函数.
Rust2015
的NLL
如,你现在可编写:
fn main() {
let mut x = 5;
let y = &x;
let z = &mut x; //在`1.31.0`之前禁止这样做.
}
新的HashMap<K,V>
实现
基于SwissTable
设计的hashbrown
中的实现已取代HashMap<K,V>
的实现.虽然接口
相同,但HashMap<K,V>
实现,现在平均速度
更快,内存成本
更低.
新的Cargo
标志已稳定:--offline
.
更改库
dbg!
宏现在支持多个
参数.
此外,多个API
变成常
:
Layout::from_size_align_unchecked
mem::needs_drop
NonNull::dangling
NonNull::cast
新的API
已稳定,包括:
1,task::Waker
和task::Poll
2,VecDeque::rotate_left
和VecDeque::rotate_right
3,Read::read_vectored
和Write::write_vectored
4,Iterator::copied
5,串的BorrowMut<str>
6,str::as_mut_ptr
1.37.0
稳定版
通过类型别名引用枚举变体
现在可用类型别名
来引用
枚举变体.如:
type ByteOption = Option<u8>;
fn increment_or_zero(x: ByteOption) -> u8 {
match x {
ByteOption::Some(y) => y + 1,
ByteOption::None => 0,
}
}
实现中,Self
行为类似类型别名
.因此,现在也可用Self::Variant
来引用
枚举变体:
impl Coin {
fn value_in_cents(&self) -> u8 {
match self {
Self::Penny => 1,
Self::Nickel => 5,
Self::Dime => 10,
Self::Quarter => 25,
}
}
}
Rust
现在允许通过"类型相关解析来引用
枚举变体.
对宏使用未命名的const
项
现在,可用_
创建无名
常量项.如,在rustc
编译器中,发现:
///类型大小断定,第一个参数是类型,第二个参数是期望大小.
#[macro_export]
macro_rules! static_assert_size {
($ty:ty, $size:expr) => {
const _: [(); $size] = [(); ::std::mem::size_of::<$ty>()];
//注意此处的下划线.
}
}
static_assert_size!(Option<Box<String>>, 8); //1.
static_assert_size!(usize, 8); //2.
注意第二个static_assert_size!(..)
:因为使用了无名
常量,可在无名字
冲突时,定义
新项目.
按配置文件优化
rustc
编译器现在通过-C profile-generate
和-C profile-use
标志支持
按配置文件优化(PGO)
.
PGO
允许编译器根据实际工作负载
来优化
代码.工作原理是编译器分两步优化:
1,首先,通过传递-C profile-generate
标志给rustc
来,用编译器
插入的检测
来构建程序
.
然后,对示例数据
运行检测
程序,并写入配置文件.
2,然后,再次
构建程序,这次使用-Cprofile-use
标志收集的分析数据
喂给rustc
.使编译器更好
放置代码,内联
和其他优化.
在[package]
部分中声明键时,如果未传递--bin
标志,cargo run
默认为选二进制文件
.
在枚举上#[repr(align(N))]]
#[repr(align(N))]
属性可用来提高
类型定义的对齐方式
.以前,只允许在结构和联上使用该属性
.现在也可在枚举中定义.
如,Align16
类型期望按16
位对齐,而没有#[repr(align(16))]
的自然对齐
方式将为4
:
#[repr(align(16))]
enum Align16 {
Foo { foo: u32 },
Bar { bar: u32 },
}
在枚举上使用#[repr(align(N))
的语义与定义
有该对齐的包装结构AlignN<T>
然后使用AlignN<MyEnum>
的语义
相同:
#[repr(align(N))]
struct AlignN<T>(T);
更改库
稳定
了许多标准库:
BufReader::buffer和BufWriter::buffer
Cell::from_mut
Cell::as_slice_of_cells
DoubleEndedIterator::nth_back
Option::xor
{i,u}{8,16,32,64,128,size}::reverse_bits and Wrapping::reverse_bits
slice::copy_within