Rust 即使在存在`&;的情况下,我是否可以强制将生存期参数设置为较短的生存期(合理);mut T`?

Rust 即使在存在`&;的情况下,我是否可以强制将生存期参数设置为较短的生存期(合理);mut T`?,rust,lifetime,Rust,Lifetime,我正试图用生锈的父指针制作一棵树。节点结构上的一个方法给了我生存期问题。下面是一个简单的示例,其中明确地编写了生命周期,以便我能够理解它们: 使用core::mem::transmute; pub结构LogNode LogNode(self:&'a mut LogNode{ LogNode(部分(自身)) } pub fn蜕变的孩子{ 不安全{ LogNode(一些( transmute::,&'a mut LogNode。如果我将可变引用更改为共享引用,那么听起来可变引用是一个问题,因为&mu

我正试图用生锈的父指针制作一棵树。节点结构上的一个方法给了我生存期问题。下面是一个简单的示例,其中明确地编写了生命周期,以便我能够理解它们:

使用core::mem::transmute;
pub结构LogNode LogNode(self:&'a mut LogNode{
LogNode(部分(自身))
}
pub fn蜕变的孩子{
不安全{
LogNode(一些(
transmute::,&'a mut LogNode
。如果我将可变引用更改为共享引用,那么听起来可变引用是一个问题,因为
&mut T T
T
上是不变的(而
&T
是协变的)。我猜
LogNode
中的可变引用冒泡,使
LogNode
自身在其生存期参数中保持不变

但我不明白为什么这是真的,直觉上它感觉使用
LogNode是完美的。答案是#3:
child
不能在安全的锈迹中实现,而
transmuted\u child
是不可靠的。下面是一个使用
transmuted\u child
的程序(没有其他
不安全的
代码)要导致SEG故障,请执行以下操作:

fn oops(arg: &mut LogNode<'static>) {
    let mut short = LogNode(None);
    let mut child = arg.transmuted_child();
    if let Some(ref mut arg) = child.0 {
        arg.0 = Some(&mut short);
    }
}

fn main() {
    let mut node = LogNode(None);
    oops(&mut node);
    println!("{:?}", node);
}

fn oops(arg:&mut LogNode要理解为什么不可变版本有效,而可变版本不可靠(如所述),我们必须讨论

Rust通常没有子类型。值通常具有唯一的类型。但是,Rust有子类型的一个地方是使用寿命。如果
'a:'b
(读
'a
'b
长),然后,例如,
&'at
&'bt
的一个子类型,直觉上是因为更长的生命周期可以被视为更短的生命周期

方差是子类型传播的方式。如果
A
B
的子类型,并且我们有一个泛型
Foo
Foo
可能是
Foo
的子类型,反之亦然,或者两者都不是。在第一种情况下,如果子类型的方向保持不变,
Foo
T而言是协变的
。在第二种情况下,当方向反转时,它被称为逆变,在第三种情况下,它被称为不变

对于这种情况,相关类型是
&'at
&'a mut
。两者在
'a
中都是协变的(因此寿命较长的引用可以强制为寿命较短的引用)。
&'a T
T
中是协变的,但
&'a mut
T
中是不变的

fn evil_feeder(pet: &mut Animal) {
    let spike: Dog = ...;

    // `pet` is an Animal, and Dog is a subtype of Animal,
    // so this should be fine, right..?
    *pet = spike;
}

fn main() {
    let mut mr_snuggles: Cat = ...;
    evil_feeder(&mut mr_snuggles);  // Replaces mr_snuggles with a Dog
    mr_snuggles.meow();             // OH NO, MEOWING DOG!
}
这一点的原因在Nomicon(上面链接)中有解释,因此我将向您展示其中给出的(稍微简化的)示例。Trentcl的代码是一个工作示例,说明了如果
&一个mut T
T
中是协变的,会出现什么问题

fn evil_feeder(pet: &mut Animal) {
    let spike: Dog = ...;

    // `pet` is an Animal, and Dog is a subtype of Animal,
    // so this should be fine, right..?
    *pet = spike;
}

fn main() {
    let mut mr_snuggles: Cat = ...;
    evil_feeder(&mut mr_snuggles);  // Replaces mr_snuggles with a Dog
    mr_snuggles.meow();             // OH NO, MEOWING DOG!
}

那么为什么不可变版本的
child
有效,而可变版本无效呢?在不可变版本中,
LogNode
包含对
LogNode
的不可变引用,因此通过生存期和类型参数中的协方差,
LogNode
在其生存期参数中是协变的。如果
'a:'b
,则en
LogNode


我们有
self:&'a LogNode
)因此,由于
LogNode
是协变的,
LogNode
。此外,不可变引用中的协变再次允许
&一个LogNode
'n
中是不协变的。这里的方差归结为
和n个mut LogNode
的方差,不能强制为
&一个mut LogNodeI接受Trentc的答案,因为它帮助我认识到如何解决我的问题,但是你的回答也非常有用!谢谢你用我的代码解释。