Description
Forked off from #10396 comment
Consider this code:
pub struct Foo<'a, 'b> { foo: &'a &'b int }
#[cfg(works)]
pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<&'a &'b ()>) { let _y = x.foo; }
#[cfg(not(works))]
pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; }
fn main() {}
I spoke with @eddyb and pointed him at regions-variance-covariant-use-contravariant.rs to illustrate that we do infer 'a <= 'b
from the existence of &'a &'b T
.
The fact that the code above does not compile as-is is interesting. I cannot tell if that is actually related to #10396 or not. (That's why I am filing this separate ticket.)
In particular, the constraints are generated by immediate occurrences of &'a &'b T
, but not by occurrences of Foo<'a,'b>
(despite Foo
having a field of type &'a &'b T
within it).
There are a couple different approaches to resolving this. The one with least user impact is probably to make occurrences of Foo<'a,'b>
(when defined as above) also generate the constraint 'a <= 'b.
For completeness (and to save others the trouble of running rustc themselves on the above test case) here is the compile failure you get today if you attempt to compile the code above without --cfg works
:
/tmp/lifetime.rs:6:66: 6:68 error: in type `&'a &'b int`, pointer has a longer lifetime than the data it references
/tmp/lifetime.rs:6 pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; }
^~
/tmp/lifetime.rs:6:60: 6:79 note: the pointer is valid for the lifetime &'a as defined on the block at 6:59
/tmp/lifetime.rs:6 pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; }
^~~~~~~~~~~~~~~~~~~
/tmp/lifetime.rs:6:60: 6:79 note: but the referenced data is only valid for the lifetime &'b as defined on the block at 6:59
/tmp/lifetime.rs:6 pub fn foo<'a, 'b>(x: Foo<'a, 'b>, _o: Option<& & ()>) { let _y = x.foo; }
^~~~~~~~~~~~~~~~~~~
error: aborting due to previous error