类型约束可能在生命周期中排名更高。这些约束指定了一个约束对于所有生命周期都为真。例如,诸如此
类的约束 for<'a> &'a T: PartialEq<i32> 需要如下实现:
impl<'a> PartialEq<i32> for &'a T {
// ...
}
然后可以用于将一个 &'a T 与任何生命周期进行比较 i32 。
这里只能使用更高级别的约束,因为引用的生命周期比函数上任何可能的生命周期参数都短。
4. 🌟🌟🌟
/* 添加 HRTB 使下面代码正常运行! */
fn call_on_ref_zero<'a, F>(f: F) where F: Fn(&'a i32) {
let zero = 0;
f(&zero);
}
fn main() {
println!("Success!")
}
NLL(非词汇生命周期)(Non-Lexical Lifetime)
在解释 NLL 之前,我们先看一段代码:
fn main() {
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2);
let r3 = &mut s;
println!("{}", r3);
}
根据我们目前的知识,这段代码会因为违反 Rust 中的借用规则而导致错误。
但是,如果您执行 cargo run ,那么一切都没问题,那么这里发生了什么?
编译器在作用域结束之前判断不再使用引用的能力称为 非词法生命周期(简称 NLL )。
有了这种能力,编译器就知道最后一次使用引用是什么时候,并根据这些知识优化借用规则。
let mut u = 0i32;
let mut v = 1i32;
let mut w = 2i32;
// lifetime of `a` = α ∪ β ∪ γ
let mut a = &mut u; // --+ α. lifetime of `&mut u` --+ lexical "lifetime" of `&mut
u`,`&mut u`, `&mut w` and `a`
use(a); // | |
*a = 3; // <-----------------+ |
... // |
a = &mut v; // --+ β. lifetime of `&mut v` |
use(a); // | |
*a = 4; // <-----------------+ |
... // |
a = &mut w; // --+ γ. lifetime of `&mut w` |
use(a); // | |
*a = 5; // <-----------------+ <--------------------------+