Visibility modifiers: pub(super) vs. super

Honestly, I find the whole pub(modifier) somewhat odd but not bad or important enough to change. I personally think pub mod ... and crate mod ... read better, but, there is nothing particularly wrong with pub(modifier) mod .... either. If pressed, and we were voting on which syntax to use in the beginning, I’d vote for the <visibiilty specifier> mod ... rather than the pub (<visibility modifier>) mod .... syntax. But, since it was implemented the way it was, I don’t really think spending any significant effort on changing it is worth much. The “Juice isn’t worth the squeeze” so to speak.

I find a lot of these syntax arguments to be similar. Argue about it before it is implemented. Once it is implemented, changing it, or bike-shedding on it again is not very valuable.

EDIT: The “weirdness” of pub(modifier) mod ... also depends on how one reads pub. Does pub mean public or publish? If the latter it can be read as:

pub : “publish default/globally”

pub(crate) : “publish to crate”

pub(super): “publish to the super module”

etc. So, if one reads pub as “publish” then pub(modifier) makes more sense with the default modifier being “public/global”. Maybe if we just started teaching/documenting/etc. that pub mean “publish” rather than “public” and kept things as they are? But, again, I don’t think there is anything particularly wrong with the status quo.

EDIT 2: The more I think about it, it is the lack of symmetry/consistency that feels a little wrong (but again, not much of an issue). If we wanted to make it more consistent have it be (and teach/document it as such):

  • pub means “publish/publicize”
  • lack of visibility specifier is short-hand for pub(priv) pub(self)
  • pub by itself is actually short-hand for pub(extern)

The “real/full/explicit” visibility specifiers are:

  • pub(extern) - publicize external to crate (globally/public) - alias/short-hand pub
  • pub(crate) - publicize to the entire crate
  • pub(super) - publicize to the super module
  • pub(self) - publicize within the module the struct etc exists (i.e. private)
  • pub(priv) - do not publicize (private) - alias/short-hand, lack of specifier/blank
  • pub(in <module::path>) - publicize within module::path

So, if someone wanted to use explicit visibility modifiers always, they could at their option use pub(priv) pub(self) instead of lack of a visibility modifier to mean private and pub(extern) instead of just pub to mean public globally/externally to the crate. In addition, sticking with this and teaching it this way, would make it easier to add additional visibility modifiers in the future (for example, pub(friend) (see for example, Revisit Orphan Rules), without disrupting keyword reservations or the grammar. If this is the road that would be pursued, then, getting rid of crate mod ... as an alias for pub(crate) mod .... should probably happen.

EDIT 3: Re-reading, https://doc.rust-lang.org/reference/visibility-and-privacy.html, it becomes clear to me that what I’ve expressed above is kind of the intent of pub (that it should be be read as “publish/publicize” rather than “public”), but, the documentation as written seems to push reading it as “public” instead based on the wording chosen in the explanation. The more I look at this, the more I just think it is a documentation and symmetry problem. Update the documentation to make clear that pub means “publish/publicize” and add the pub(extern) and explanation of that, for symmetry, and get rid of crate ... instead of pub(crate) ... (so as not to break symmetry) and all should be good.

So, stop saying “public vs private” when talking about “pub”, and instead talk about “publicizing/publishing externally/globally” vs “publicizing to crate” vs “publicizing to super module” etc. If that is the language used in documentation, etc. everything should be much more clear.

12 Likes