How do you combine rust life?

This code:

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.
}

      

Can't compile with error:

<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   }

      

(playpen: http://is.gd/vAvNFi )

This is obviously a contrived example, but this is what I want to do sometimes.

So...

1) How do you combine life time? (i.e. return a Foo that has a lifetime of at least a or b, which is ever shorter)

2) Is there a way to write tests for resource compilation failure? (for example, try to compile # [test] that uses the function incorrectly and did not execute a lifetime error)

+3


source to share


2 answers


The scores 'c: 'a + 'b

mean that 'c

at least as long as 'a

and as long as 'b

. However, in this case, the value is Foo

valid for the shortest of 'a

and 'b

: as soon as the data behind any link is out of bounds, everything Foo

should be invalidated. (This indicates that the data valid for 'c

is valid in the union 'a

and 'b

.)

In more concrete terms, say 'b = 'static

then 'c: 'a + 'static

means that 'c

it should also be 'static

, so the return value will be Foo<'static>

. This is clearly not the case, as this will be an "update" of a limited directory 'a

self

for a duration that lasts forever.



The correct behavior here is the intersection of lifetimes: Foo

only valid if both function parameters are valid. The intersection operation is simply a designation for links of the same name:

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

      

+8


source


Remove all limetime parameters from bar

and use the 'a

lifetime from parameter instead impl

.

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

      



'a

will be output by the compiler as the smallest lifetime in which all references are valid.

+3


source







All Articles