据我所知,在Rust中,T: 'a
表示“任何提供的类型参数T
的所有生存期都必须超过'a
”。
pub struct A<'a, T: 'a> {
field: &'a T
}
这是大多数情况下自然想要的。
我偶然发现了一种情况,我需要表达“任何提供的类型参数T
的所有生存期必须准确 'a
”(即,既不过期也不被'a
终止)。
pub struct A<'a, T<'a>> { // imaginary syntax
field: &'a T
}
有没有一种表达方式?
[请注意,我可以通过为单个T
编写专门的代码来轻松实现此目的,因为这样一来,我可以为'a
的任何给定值指定确切的寿命T
:
pub struct AForB<'a> {
field: &'a B<'a>
}
pub struct B<'a> {
other: &'a str
}
pub struct AForC<'a> {
field: &'a C<'a>
}
pub struct C<'a> {
other: &'a i32
}
但是对于泛型,Rust似乎只允许我将其表示为“生存期”关系(至少使用我知道的任何语法),这等效于已编写:
pub struct AForB<'a, 'b: 'a> {
field: &'a B<'b>
}
pub struct B<'a> {
other: &'a str
}
pub struct AForC<'a, 'b: 'a> {
field: &'a C<'b>
}
pub struct C<'a> {
other: &'a i32
}
以上内容当然可以编译,但是在我的情况下是不正确的。从某种意义上说,“不正确”与所使用的数据存储的语义不匹配,因此在这些定义下,借用检查器将接受不正确的代码。
要使结构在T
上协变而在'a
上不变,您会这样做:
use std::marker::PhantomData;
use std::cell::Cell;
struct A<'a, T: 'a> {
field: &'a T,
_phantom: PhantomData<Cell<&'a ()>>
}
fn test_invariance<'a, T>(a: A<'static, T>) -> A<'a, T> {
a // compiler error, A is invariant over 'a, can't coerce 'static into 'a
}
进一步阅读: