I feel dumb for having browsed the marker section of the Rust documentation and the Wikipedia articles about subtyping and variance multiple times without it improving my understanding of the lifetimes subtyping relation.
I think I'm just used to the "typical OOP-style" subtying relations like "Cat <: Animal" meaning "Cat is a subtype of Animal" where "S is a subtype of T" means "any term S can be safely used in a context where a term of type T is expected". So far so good.
But how does this apply to lifetimes? The way it is defined right now in Rust is apparently(*)
(#1) 'a <: 'b <=> lifetime a is no longer than lifetime b.
And you might think "Of course that's what it means!" possibly because <: looks similar to the less than operator or possibly because "sub" makes you think of subsets and a shorter lifespan is certainly a subset of a longer lifespan. But is 'a really a subtype of 'b if 'a is no longer than 'b? Let's try to apply Wikipedia's definition of the subtype relation:
(#2) 'a <: 'b <=> lifetime a can be safely used in a context where lifetime b is expected.
The problem I have is that I'm not able to reconcile this. How do you get from #2 to #1? Because to me, this seems like a contradiction... If you expect something to be alive for at least b and you have something with a lifetime a that's shorter than b, you obviously cannot use it in that context where something with a lifetime b is required, can you? Is it just me or did we get the subtyping relation for lifetimes wrong?
Edit: (*) According to Ms2ger in the #rust
IRC channel this is the case. It also fits with the documentation on the contravariant lifetime marker which is used in the Items
iterator.
Edit2: The ContravariantLifetime and CovariantLifetime markers have been removed. We now have PhantomData
as a replacement in the marker module.
a <: b <=> lifetime b is no longer than lifetime a
. – Lipcombep1
outlives the region corresponding top2
, then it is sound to use a value of type*p1
where we expect one of type*p2
" – Lipcombe