Standalone types to represent variance

Currently if you want to express your type’s variance with respect to generic parameter, perhaps with a generic lifetime parameter 'a, you have to include a PhantomData field with something like &'a T, fn(&'a T), or fn(T) -> T. These are pretty “magical” and require a fair amount of reasoning to determine why they're correct.

Why doesn't Rust just have (say) PhantomCovariant<T>, PhantomContravariant<T>, and PhantomInvariant<T>, so that you could replace e.g. PhantomData<fn(T) -> T> with the much clearer PhantomInvariant<T>? (These would simply be defined in terms of PhantomData.) This would be more explicit, less magical.

Rust used to have them but they were removed according to RFC 738. The stated rationale is that they were confusing, and PhantomData was more general because it can help with Send + Sync too:

Even better, the user doesn’t really have to understand the terms covariance, invariance, or contravariance, but simply to accurately model the kind of data that the type system should pretend is present.

Other uses for phantom data. It turns out that phantom data is an important concept for other compiler analyses. One example is the OIBIT analysis, which decides whether certain traits (like Send and Sync) are implemented by recursively examining the fields of structs and enums. OIBIT should treat phantom data the same as normal fields.

(OIBIT is the old name for what we now call auto traits.)

I personally think this was a mistake, because while PhantomData is easier to write in simple cases, in complex ones it’s hard to think of the right phantom type to insert to get all otherwise-implied properties correct.

actually they are coming, and on nightly, you can use them with #![feature(phantom_variance_markers)]. the current implementation has these same names you suggested, and more with lifetimes parameters:

1 Like

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.