为什么nomicon布局章节&Vec<&'static str>不能在预期<vec和'a str>的地方使用?



https://doc.rust-lang.org/nomicon/vec-layout.html

我不明白Vec什么时候定义为

pub struct Vec<T> {
ptr: *mut T,
cap: usize,
len: usize,
}

并引用:

事实上,这将编译。不幸的是,这是不正确的。首先,编译器会给我们太严格的方差。因此,&Vec<&'static str>不能用于预期&Vec<&'a str>的位置。更重要的是,它会向丢弃检查器提供不正确的所有权信息,因为它会保守地假设我们不拥有任何t类型的值。

我试过下面的代码(游乐场(,但它有效。

pub struct TestVec<T> {
raw: *mut T,
len: usize,
cap: usize,
}
impl<T> TestVec<T> {
pub fn new()->Self {
TestVec { raw: std::mem::MaybeUninit::uninit().as_mut_ptr(), len:0, cap:0}
}
}
fn test1(a: &TestVec<&str>) {
}
fn test() {
let v:TestVec<&'static str> = TestVec::new();
test1(&v);
}
fn main() {
test();
}

我哪里错了?或者有任何示例代码吗?

这句话是关于类型方差的,这是一个关于类型之间关系的棘手概念,实际上是一种特殊的子类型。

你的例子不包含差异。它被降级为:

fn test1<'x, 'y>(a: &'x TestVec<&'y str>)

当使用v: TestVec<&'static str>调用此函数时,'x的生存期解析为v的生存期,'y'static。这里没有类型差异,只有泛型。

但考虑一下另一个需要方差的例子:

fn test2<'x>(a: &TestVec<&'x str>, b: &TestVec<&'x str>) {}
fn test_variance<'a>() {
let v1:TestVec<&'static str> = TestVec::new();
let v2:TestVec<&'a str> = TestVec::new();
test2(&v1, &v2);
}

现在编译器应该将'x求解为'a'static的最短生存期,因为存在差异,应该只是'a。但是TestVec中的*mut T导致了这个错误:

cannot infer an appropriate lifetime for lifetime parameter 'a in function call due to conflicting requirement
...
= note: expected `&TestVec<&str>`
found `&TestVec<&'static str>`

然后,正如Nomicon所解释的,将*mut T更改为*const T使其再次工作。

相关内容

最新更新