你如何结合生锈的生命?

时间:2014-09-05 01:29:21

标签: rust

此代码:

struct Foo<'a> {
  value: Option<&'a int>,
  parent: Option<&'a Foo<'a>>
}

impl<'a> Foo<'a> {
  fn bar<'a, 'b, 'c: 'a + 'b>(&'a self, other:&'b int) -> Foo<'c> {
    return Foo { value: Some(other), parent: Some(self) };
  }
}

fn main() {
  let e = 100i;
  {
    let f = Foo { value: None, parent: None };
    let g:Foo;
    {
       g = f.bar(&e);
    }
    // <--- g should be valid here
  }
  // 'a of f is now expired, so g should not be valid here.

  let f2 = Foo { value: None, parent: None };
  {
    let e2 = 100i;
    let g:Foo;
    {
       g = f2.bar(&e2);
    }
    // <--- g should be valid here
  }
  // 'b of e2 is now expired, so g should not be valid here.
}

无法使用错误进行编译:

<anon>:8:30: 8:35 error: cannot infer an appropriate lifetime due to conflicting requirements
<anon>:8     return Foo { value: Some(other), parent: Some(self) };
                                      ^~~~~
<anon>:7:3: 9:4 note: consider using an explicit lifetime parameter as shown: fn bar<'a, 'b>(&'a self, other: &'b int) -> Foo<'b>
<anon>:7   fn bar<'a, 'b, 'c: 'a + 'b>(&'a self, other:&'b int) -> Foo<'c> {
<anon>:8     return Foo { value: Some(other), parent: Some(self) };
<anon>:9   }

(游戏围栏:http://is.gd/vAvNFi

这显然是一个人为的例子,但这是我偶尔要做的事情。

因此...

1)你如何结合一生? (即返回一个生命周期至少为“a”或“b”的Foo,它的寿命更短)

2)有没有办法将测试写入资产生命周期编译失败? (例如,尝试编译以错误方式使用该函数的#[test],并以生命周期错误失败)

2 个答案:

答案 0 :(得分:9)

边界'c: 'a + 'b表示'c至少与'a一样长,只要'b。但是,在这种情况下,Foo值的有效时间最短为'a'b:只要引用后面的数据超出范围,整个Foo必须失效。 (这表示对'c有效的数据在'a'b union 中有效。)

更具体地说,'b = 'static,然后'c: 'a + 'static表示'c也必须是'static,因此返回值为Foo<'static>。这显然是不对的,因为它会将有限的'a self引用“升级”为永久持续的引用。

这里的正确行为是生命周期的交集:Foo仅在两个函数参数都有效时才有效。交叉操作只是用相同的名称标记引用:

fn bar<'a>(&'a self, other: &'a int) -> Foo<'a>

答案 1 :(得分:4)

删除bar上的所有时间参数,然后使用'a中的impl有效期参数。

impl<'a> Foo<'a> {
  fn bar(&'a self, other:&'a int) -> Foo<'a> {                  // '
    return Foo { value: Some(other), parent: Some(self) };
  }
}
编译器会将

'a推断为所有引用有效的最小生命周期。