Rust 新版解读 | 1.65 | 重点: 泛型关联类型,新绑定语法!
Rust 新版解读 | 1.65 | 重点: 泛型关联类型,新绑定语法!
Rust 1.65 官方 release doc: Announcing Rust 1.65.0 | Rust Blog
通过 rustup 安装的同学可以使用以下命令升级到 1.65 版本:
$ rustup update stable
泛型关联类型 Generic associated types (GATs)
关联类型(associated types)里现在可以加上生命周期、类型、const泛型了,类似于:
trait Foo {
type Bar<'x>;
}
三言两语说不清这个变化的好处,看几个例子来感受一下:
/// 一个类似于 `Iterator` 的 trait ,可以借用 `Self`。
trait LendingIterator {
type Item<'a> where Self: 'a;
fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
}
/// 可以给智能指针类型,比如 `Rc` 和 `Arc` 实现的 trait,来实现指针类型的泛用性
trait PointerFamily {
type Pointer<T>: Deref<Target = T>;
fn new<T>(value: T) -> Self::Pointer<T>;
}
/// 允许借用数组对象,对不需要连续存储数据的固定长度数组类型很有用
trait BorrowArray<T> {
type Array<'x, const N: usize> where Self: 'x;
fn borrow_array<'a, const N: usize>(&'a self) -> Self::Array<'a, N>;
}
泛型关联类型十分通用,能够写出许多之前无法实现的模式。更多的信息可以参考下面的链接:
第一个对上面的例子进行了更深入的讨论,第二个讨论了一些已知的局限性。
更深入的阅读可以在关联类型的 nightly reference 和 原始 RFC(已经过去6.5年了!) 里找到。
let
- else
语法
新的 let
语法,尝试模式匹配,找不到匹配的情况下执行发散的 else
块。
let PATTERN: TYPE = EXPRESSION else {
DIVERGING_CODE;
};
常规的 let
语法仅能使用 irrefutable patterns
,直译为不可反驳的模式,也就是一定要匹配上。一般情况下都是单个变量绑定,也用在解开结构体,元组,数组等复合类型上。原先并不适用条件匹配,比如从枚举里确定枚举值。直到现在我们有了 let
- else
。这是 refutable pattern
,直译为可反驳的模式,能够像常规 let
一样匹配并绑定变量到周围范围内,在模式不匹配的时候执行发送的 else
(可以是 break
, return
, panic!
)。
fn get_count_item(s: &str) -> (u64, &str) {
let mut it = s.split(' ');
let (Some(count_str), Some(item)) = (it.next(), it.next()) else {
panic!("Can't segment count item pair: '{s}'");
};
let Ok(count) = u64::from_str(count_str) else {
panic!("Can't parse integer: '{count_str}'");
};
(count, item)
}
assert_eq!(get_count_item("3 chairs"), (3, "chairs"));
if
- else
和 match
或者 if let
最大不一样的地方是变量绑定的范围,在此之前你需要多写一点重复的代码和一次外层的 let
绑定来完成:
let (count_str, item) = match (it.next(), it.next()) {
(Some(count_str), Some(item)) => (count_str, item),
_ => panic!("Can't segment count item pair: '{s}'"),
};
let count = if let Ok(count) = u64::from_str(count_str) {
count
} else {
panic!("Can't parse integer: '{count_str}'");
};
break
跳出标记过的代码块
块表达式现在可以标记为 break
的目标,来达到提前终止块的目的。这听起来有点像 goto
语法,不过这并不是随意的跳转,只能从块里跳转到块末尾。这在之前已经可以用 loop
块来实现了,你可能大概率见过这种总是只执行一次的 loop
。
1.65 可以直接给块语句添加标记来提前退出了,还可以携带返回值:
let result = 'block: {
do_thing();
if condition_not_met() {
break 'block 1;
}
do_next_thing();
if condition_not_met() {
break 'block 2;
}
do_last_thing();
3
};
Others
其它更新细节,和稳定的API列表,参考原Blog