Rust 为什么链接生存期只与可变引用有关?
几天前,有人对包含借用数据本身的类型的可变引用的链接生存期有问题。问题在于提供对该类型的引用时,其借用的生存期与该类型内借用的数据相同。 我试图重现这个问题:Rust 为什么链接生存期只与可变引用有关?,rust,reference,covariance,lifetime,Rust,Reference,Covariance,Lifetime,几天前,有人对包含借用数据本身的类型的可变引用的链接生存期有问题。问题在于提供对该类型的引用时,其借用的生存期与该类型内借用的数据相同。 我试图重现这个问题: struct VecRef<'a>(&'a Vec<u8>); struct VecRefRef<'a>(&'a mut VecRef<'a>); fn main() { let v = vec![8u8, 9, 10]; let mut ref_v =
struct VecRef<'a>(&'a Vec<u8>);
struct VecRefRef<'a>(&'a mut VecRef<'a>);
fn main() {
let v = vec![8u8, 9, 10];
let mut ref_v = VecRef(&v);
create(&mut ref_v);
}
fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
VecRefRef(r);
}
生存期'b
类似于'b
,因此违反了vecreref
中的约束
我将可变引用的生存期与VecRef
中借用的数据联系起来,将可变引用引用到VecRef
create()
内部的可变引用r
的生存期为VecRef
警告:我所说的是我所没有的专业水平。鉴于这篇文章的篇幅,我可能错了很多次
TL;DR:顶级值的生存期是协变的。引用值的生存期是不变的
介绍问题
通过替换VecRefI,您可以显著简化示例。在create函数主体内,拾取的生命周期将在2-3的范围内,因为从提供的混凝土生命周期集合中,它将是唯一与约束匹配的生命周期。因此,它将是所创建向量的生命周期'a请注意,您必须使用语法'b:'a
来表示生命周期'a
将比'b更长。
-它不应该是“…表示生命周期'b
将比'a
更长”?读取可防止'b
增长,因为如果要从外部指针中提取内部指针,则可以在'a
过期后读取你能详细解释一下吗?@soupyboonics我想我错了。让我再打给你。@soupyboonics对不起,我好像忘了你的问题。我记得我调查过,认为我错了,但我记不起细节了。我会注意到&'static&'b
可以转换为&'static&'static
,这表明您是对的,但我认为这不正确。相反,可能存在一种隐含的假设,即'b:'a
;将&'a&'b
转换为&'a&'static
失败。
fn create<'a>(r: &'a mut VecRef<'a>) {
VecRefRef(r);
}
struct VecRef<'a>(&'a Vec<u8>);
struct VecRefRef<'a>(&'a VecRef<'a>); // now an immutable reference
fn main() {
let v = vec![8u8, 9, 10];
let mut ref_v = VecRef(&v);
create(&mut ref_v);
}
fn create<'b, 'a>(r: &'b mut VecRef<'a>) {
VecRefRef(r);
}
fn identity<'a, T>(val: &'a T) -> &'a T { val }
fn main() {
let v = vec![8u8, 9, 10]; // 1 |-lifetime of `v`
let mut ref_v = VecRef(&v); // 2 | |-lifetime of `ref_v`
create(&mut ref_v); // 3 | |
}
fn create<'a>(r: &'a mut VecRef<'a>)
struct VecRefRef<'a, 'b: 'a>(&'a mut VecRef<'b>);
fn create<'a, 'b>(r: &'a mut VecRef<'b>)
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a>(reference: &'a mut &'a mut ()) {
use_same_ref_ref(reference);
}
let mut val = ();
let mut reference = &mut val;
let ref_ref = &mut reference;
use_ref_ref(ref_ref);
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b: 'a>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b ()) {
use_same_ref_ref(reference);
}
let new_ref = reference;
let new_ref_ref = ref_ref;
let ref_ref: &'x mut &'a mut i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b mut i32 = ref_ref;
*new_ref_ref = &mut new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a mut i32 = *ref_ref;
// Oops, we have an &'a mut i32 pointer to a dropped value!
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
&'a mut &'b mut () → &'c mut &'c mut ()
&'a mut &'b mut () → &'b mut &'b mut ()
'a: 'b
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a>(reference: &'a mut &'a mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a, 'b: 'a>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
fn use_same_ref_ref<'c>(reference: &'c &'c mut ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a &'b mut ()) {
use_same_ref_ref(reference);
}
let ref_ref: &'x mut &'a mut i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b mut i32 = ref_ref;
*new_ref_ref = &mut new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a mut i32 = *ref_ref;
// Oops, we have an &'a mut i32 pointer to a dropped value!
fn use_same_ref_ref<'c>(reference: &'c mut &'c ()) {}
fn use_ref_ref<'a, 'b>(reference: &'a mut &'b ()) {
use_same_ref_ref(reference);
}
let ref_ref: &'x mut &'a i32 = ...;
{
// Has lifetime 'b, which is smaller than 'a
let new_val: i32 = 123;
// Shrink 'a to 'b
let new_ref_ref: &'x mut &'b i32 = ref_ref;
*new_ref_ref = &new_val;
}
// new_ref_ref is out of scope, so ref_ref is usable again
let ref_ref: &'a i32 = *ref_ref;
// Oops, we have an &'a i32 pointer to a dropped value!
fn use_same_ref_ref<'c>(reference: &'c mut &'c mut ()) {}
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
let mut val = ();
let mut reference = &mut val;
let ref_ref = &mut reference;
use_ref_ref(ref_ref);
fn use_ref_ref<'a: 'b, 'b>(reference: &'a mut &'b mut ()) {
use_same_ref_ref(reference);
}
let reference = &mut val;