Yeah I was really surprised to see a significant post on this with no mention of the hilarious dangers of variance, sharing, and overwrite-ability.<p>In Rust it ends up actually being pretty clean because mutability is inherited. Generic values are covariant because (as you note), they&#x27;re by definition unshared. &amp;T is covariant in T because you can&#x27;t mutate T through an &amp;. &amp;mut T is invariant in T because you <i>can</i> mutate through it.<p>This therefore enables one to pass &amp;Collection&lt;T&gt; where &amp;Collection&lt;U&gt; is expected if T is a subtype of U, because we know the collection only supports &quot;read only&quot; operations. It&#x27;s been a while since I&#x27;ve used C++ and never really touched const stuff, but if it works like Rust, that means a `Vector&lt;T&gt; &amp;const` could be soundly covariant. It wouldn&#x27;t work if you could get `T*`&#x27;s out of a `Vector&lt;T&gt; &amp;const`.<p>That said, we don&#x27;t have OOP-style inheritance in Rust, so variance only applies to lifetimes. This allows you to pass an &amp;LongLived where an &amp;ShortLived is expected.<p>I give a basic rundown here: <a href="https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;nomicon&#x2F;subtyping.html" rel="nofollow">https:&#x2F;&#x2F;doc.rust-lang.org&#x2F;nightly&#x2F;nomicon&#x2F;subtyping.html</a><p>Note that I deviate from the academic standard and simply use &quot;variance&quot; for covariance, because the academic terms are dumb and confusing (so many Rust devs, even with PL backgrounds, were constantly getting confused when we used that terminology). Also you don&#x27;t really need to care about contravariance anyway because it&#x27;s also dumb and confusing (as this post notes).