PhantomData fields should be public by convention


#1

Motivation:

PhantomData is essentially a variance (and marker traits) annotation. It affects the ways in which the consumers of a type may use it (it’s effectively part of the API).

Proposal:

I think we should have a lint where, if a private field has type PhantomData, we suggest making that field public instead. Given that PhantomData is a ZST with no information content, this doesn’t really provide any kind of additional capability to users of the type. It merely makes the field show up in rustdoc, so that readers of the documentation can learn how the type will behave, and highlights that it is part of the public API contract. If the field is public, then changing its type will seem like a semver-breaking change, which is good and right, because changing variance or marker traits is a semver-breaking change.

Complications:

If the given field was the only private field in the struct, making it public would allow users to construct it and exhaustively pattern match on it, which they couldn’t before, which is clearly bad. The lint should take this into account and suggest adding a separate private dummy field (probably of type ()) in these cases. I don’t know how common this is though? My sense is that in most of the cases where you have a reason to use PhantomData, you also have another field which is private and contains, usually, a raw pointer.


#2

There are changes one can make that don’t affect marker traits and variance but which would break users of a public field (e.g., renaming the field, combining or splitting multiple PhantomData fields, moving the PhantomData into another type that’s contained in the type that previously held the PhantomData). I’d rather not close the door to such changes just to work around a rustdoc limitation.

I’d rather have the relevant information properly displayed in the API docs. That’s not just more convenient for users (reverse engineering it from PhantomData fields can be challenging), it also covers all the myriad cases where non-PhantomData fields have variance and marker trait implications (e.g., anything with a mutable reference is invariant, regardless of whether PhantomData is involved).


#3

Don’t these arguments apply to every use of the parameters inside of the type? You should expect to look at the source if you want to learn the variance of a struct, not just rustdoc (unless rustdoc changes to document that somehow automatically).


#4

Yeah I agree actually never mind this thread.