To give some practical examples beyond @2e71828's explanation: Variance can be different for each lifetime. E.g. `fn(&'a u8) -> &'b u8`

is covariant in `'b`

and contravariant in `'a`

. And variance applies to lifetime variables as well as type variables. E.g. `&'a T`

is covariant in `'a`

and covariant in `T`

, whereas `&'a mut T`

is covariant in `'a`

but invariant in `T`

.

As I explored further in the post I’ve already linked above, variance of type variables ultimately affects variance of lifetimes. The type `Box<&'a Foo>`

is covariant in `'a`

; which can be determined by looking at the variance of `Box<T>`

and `&'b S`

(here `T`

, `S`

, and `'b`

are type/lifetime *variables*).

`Box<&'a Foo>`

is composed by: plugging in `'a`

for `'b`

and `Foo`

for `S`

in `&'b S`

, and then pluggin the resulting `&'a Foo`

for `T`

in `Box<T>`

. So the lifetime `'b`

is appearing in the first/only (“`T`

”) type argument of `Box<T>`

, and then inside of that in the first/only (“`'b`

”) lifetime argument of `&'b S`

. The variance of these arguments, i.e. fact that `Box<T>`

is covariant in `T`

and `&'b S`

is covariant in `'b`

, combine to let us derive that `Box<&'a Foo>`

is covariant in `'a`

.

You could try to apply similar reasoning to infer e.g. that `&'a mut &'b mut u8`

is covariant in `'a`

and invariant in `'b`

.

The reason why this reasoning/deduction works becomes clear if you expand the definition of variance in each case.

“`Box<T>`

is covariant in `T`

” means that for every subtype `U`

of `V`

, `Box<U>`

is a subtype of `Box<V>`

and “`&'b S`

is covariant in `'b`

” means that for every lifetime `'x`

that outlives `'y`

, and every type `S`

, `&'x S`

is a subtype of `&'y S`

.

Now, “`Box<&'a Foo>`

is covariant in `'a`

” means that for every lifetime `'l`

that outlives `'m`

, `Box<&'l Foo>`

is a subtype of `Box<&'m Foo>`

. We can *prove* that this is the case based on the previous two statements, by instantiating type variables and lifetime variables:

`U`

:= `&'l Foo`

`V`

:= `&'m Foo`

`'x`

:= `'l`

`'y`

:= `'m`

`S`

:= `Foo`

**Note:** What do I mean by “instantiating”? Replacing the variables with these above instantiations, and we can infer

- from “
`Box<T>`

is covariant in `T`

”, that
- if
`U`

is a subtype of `V`

, then `Box<U>`

is a subtype of `Box<V>`

, thus in particular:
- if
`&'l Foo`

is a subtype of `&'m Foo`

, `Box<&'l Foo>`

is a subtype of `Box<&'m Foo>`

,

- from “
`&'b S`

is covariant in `'b`

”, that
- if
`'x`

outlives `'y`

, then `&'x S`

is a subtype of `&'y S`

, thus in particular:
- if
`'l`

outlives `'m`

, then `&'l Foo`

is a subtype of `&'m Foo`

.

Putting things together, “`Box<T>`

is covariant in `T`

” gives us the desired relation `Box<&'l Foo>`

is a subtype of `Box<&'m Foo>`

, **provided that** `&'l Foo`

is a subtype of `&'m Foo`

. And `&'l Foo`

is a subtype of `&'m Foo`

from the fact that “`&'b S`

is covariant in `'b`

”, **provided that** `'l`

outlives `'m`

.

This chain of implications shows indeed that for every lifetime `'l`

that outlives `'m`

, `Box<&'l Foo>`

is a subtype of `Box<&'m Foo>`

.