Implied bounds on nested references + variance = soundness hole · Issue #25860 · rust-lang/rust (original) (raw)
The combination of variance and implied bounds for nested references opens a hole in the current type system:
static UNIT: &'static &'static () = &&();
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
fn bad<'a, T>(x: &'a T) -> &'static T { let f: fn(&'static &'a (), &'a T) -> &'static T = foo; f(UNIT, x) }
This hole has been fixed in #129021 for non-higher-ranked function pointers. The underlying issue still persists.
static UNIT: &'static &'static () = &&();
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T, _: &()) -> &'a T { v }
fn bad<'a, T>(x: &'a T) -> &'static T { let f: fn(_, &'a T, &()) -> &'static T = foo; f(UNIT, x, &()) }
fn main() {}
Update from @pnkfelix :
While the test as written above is rejected by Rust today (with the error message for line 6 saying "in type &'static &'a ()
, reference has a longer lifetime than the data it references"), that is just an artifact of the original source code (with its explicit type signature) running up against one new WF-check.
The fundamental issue persists, since one can today write instead:
static UNIT: &'static &'static () = &&();
fn foo<'a, 'b, T>(_: &'a &'b (), v: &'b T) -> &'a T { v }
fn bad<'a, T>(x: &'a T) -> &'static T { let f: fn(_, &'a T) -> &'static T = foo; f(UNIT, x) }
(and this way, still get the bad behaving fn bad
, by just side-stepping one of the explicit type declarations.)