Description
I think the Subtyping and Variance section could be improved by some changes for simplicity and clarity. Here are a few initial thoughts. If any of these seem worth pursuing, I'm eager to take a stab at addressing them!
Main metaphor is confusing
The class-based subtyping of Animals and Cats/Dogs feels backwards. Indeed, the section itself even notes:
This is a large source of confusion, because it seems backwards to many
Some of the confusion noted by the author of issue 124 might be resolved with a metaphor whose relationships are closer analogs to Rust's lifetime relationships. For example, we could frame lifetime relationships in terms of privilege levels:
- An account with admin-level privileges to a computer is the most permissive, similar to the static lifetime which has a longer lifetime (or similar to some long-lived lifetime).
- A account with only user-level privileges is more restrictive, similar to some lifetime
'a
which has a shorter lifetime.
The early examples of the section might look something like this:
trait User {
fn login();
}
trait Admin: User {
fn change_system_time();
}
...
fn login(account: User) {
account.login();
}
...
let a: Admin = ...;
login(a); // ERROR: expected Admin, found User
Dog subtype is confusing
Dog is presented as a "sibling" to Cat; that is, the only relationship between the two is that they are both subtypes of Animal. However, when it comes to lifetimes, 'a
and 'b
will always be related by a hierarchical relationship. Either 'a
is more long-lived than 'b
, or, if they live for the same amount of time, they're really just the same lifetime.
Circling back to the privilege level analogy, Dog could be replaced by an account with guest-level privileges.
This section wasn't quite accurate - see comments below.
Type lifetimes should be explicitly called out
One source of confusion for me, similar to the one raised in this comment, was that the section talks about variances over some type T
. However, type T
implictly has a lifetime, and the variance we're concerned with is really variances over this lifetime. This concept is never explicitly mentioned. I think a comment about this near the start of the Variance section would help.
Justification of rules feels inverted
If we look at our table of variances, we see that &mut T is invariant over T. As it turns out, this completely fixes the issue!
The quoted text implies that the problematic code snippet is fixed by referencing the variance table. This feels like the reverse framing of the true issue. It's more that the problematic code snippet is an example of a class of problems that necessitates the variance rule.