结构上的生命周期界限在Rust中是如何工作的?

结构上的生命周期界限在Rust中是如何工作的?,rust,lifetime,Rust,Lifetime,昨天IRC对此进行了一些讨论,这让我隐约感到不满 问题是: 如何在结构上定义生存期以将其内容限制为 只有和“自身”一样长寿的东西 i、 e.自我之类的东西 我最初的反应是:你不能 如果您创建一个structFoo{ a:&'a酒吧, b:酒吧 } fn工厂{ 返回Foo{ a:v1, b:v2 }; } fn main(){/'two(即,'two以'one为边界) foo1有一个' foo2有两个' 现在,我的困惑是: Foo'one,foo1不应包含和'two b;但是,这是可行的 为什

昨天IRC对此进行了一些讨论,这让我隐约感到不满

问题是:

如何在结构上定义生存期以将其内容限制为 只有和“自身”一样长寿的东西

i、 e.
自我
之类的东西

我最初的反应是:你不能

如果您创建一个struct
Foo{
a:&'a酒吧,
b:酒吧
}
fn工厂{
返回Foo{
a:v1,
b:v2
};
}
fn main(){/
'two
(即,
'two
'one
为边界)
  • foo1
    有一个
    '
  • foo2
    有两个
    '
  • 现在,我的困惑是:

    Foo
    'one
    foo1
    不应包含
    和'two b
    ;但是,这是可行的

    为什么?

    我的困惑似乎源于以下两种误解之一:

  • foo1
    的实例实际上是
    Foo

    我不明白为什么会出现这种情况,因为它是在
    工厂制造的
    c
    的生命周期;它是
    'one
    ,而不是
    'two
    。在上面的例子中
    c
    绝对不可能是
    'two
    。生命周期
    'two
    在函数工厂中是不可用的创建了re
    Foo

  • 2) 结构生命周期不起作用,我理解它们如何起作用;例如,在
    Foo
    实例上的
    'a
    生命周期在创建实例后(例如,在移动中?)可能会发生某种变化


    …但我不知道是哪一个。

    引用上的生存期参数是协变的:必要时可以用更短的生存期替换它们

    基本上,您的理解是错误的。当您有一个
    &'one Bar
    时,您不能将引用分配给一个使用寿命较短的值(例如这里的
    'two
    ),否则,当执行离开
    'two
    范围时,引用将悬空。但是,当您有
    &'two Bar
    时,可以将引用分配给具有较长生存期的值(例如
    'one
    'static
    ),因为引用将在引用对象离开范围之前离开范围

    为什么您的程序要编译?编译器不仅使用调用
    工厂
    的信息来选择合适的生存期;
    &a
    的类型是
    &one Bar
    ,而
    &b
    的类型是
    &two Bar
    。因为
    'two
    'one
    之后开始,在
    'one
    之前结束编译器可以
    和“一条
    强制为
    和“两条
    ”。在面向对象的术语中,
    和“一条
    和“两条
    ”(
    和“一条
    和“两条
    的子类型)。就像在Java中一样,您可以将
    字符串
    作为参数传递给需要
    对象
    的函数。Java中类的子类型关系是子类是其父类的子类型,但生命周期的子类型关系是较长的生命周期是较短生命周期的子类型

    这意味着我们已经为
    &a
    &b
    找到了一个通用类型:
    &two-Bar
    。因此,编译器在调用
    工厂
    时推断
    'a
    'two


    请注意,
    foo2
    的类型在赋值时不会改变;值的类型始终是静态的。

    我更新了我的问题,以反映您是对的,我的回答是错误的,但是没有……我仍然不明白为什么这两个实例都要进行foo编辑,以详细说明生命周期之间的子类型关系。
    #[derive(Debug)]
    struct Bar;
    
    #[derive(Debug)]
    struct Foo<'a> {
      a:&'a Bar,
      b:&'a Bar
    }
    
    fn factory<'a>(v1:&'a Bar, v2: &'a Bar) -> Foo<'a> {
      return Foo {
        a: v1,
        b: v2
      };
    }
    
    fn main() { // <---- Let's call this block lifetime 'one
      let a = Bar; 
      let c = &a; // <-- C has lifetime 'one
      { // <------------ Let's call this block lifetime 'two
        let b = Bar;
    
        let mut foo1 = factory(c, c);  
        foo1.b = &b;
    
        let mut foo2 = factory(&b, &b);  
        foo2.a = &a;
    
        println!("{:?}", foo1);
        println!("{:?}", foo2);
      }
    }