Is variance recursive with respect to T?

I'm trying to understand lifetime variance in rust and stumbled across this topic Why &mut T is not covariant with T?.

The answer was that if that would be possible you could create dangling reference

fn foo<'a, 'b>(r: &'a mut &'b i32) {
    let x = 1;
    *r = &x;
}

But in this example lifetime of x isn't subtype of 'b(it lives longer) so it shouldn't be possible to create dangling reference.
Aren't rules checked recursively? Saying that if T is &'b U then assigned value lifetime should be covariant in 'b. So something like the example wouldn't work.

If not - why? Do I misunderstand something?

Can't explain it nearly as good as Quine Dot can:

x doesn't live longer than 'b, it is dropped when foo returns. So when you call *r after foo(r), you'd have use-after-free.

1 Like

Don't confuse the lifetime(s) of a type (those '_ things) with the liveness of values.


Here's a page on how variance composes, (e.g. recursively) though tbh once I'm beyond simple cases I prefer to just write a test case to make sure.[1]


  1. Granted, what's simple varies with experience. ↩ī¸Ž

I really don't get what you are trying to say here. If the code you posted were allowed, it absolutely, positively, certainly, 100% would create a dangling reference. The variable x lives only until the end of the function body, whereas the lifetime parameter 'b denotes an arbitrarily long lifetime that's chosen by the caller (e.g. it can be 'static).

This has nothing to do with recursion. This is the literal definition of the invariance of a single level of mutable reference. &mut T<'b> is invariant in 'b. That's it, that's the rule, and it's enough to determine that the code snippet above is not allowed.

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.