pub and pub(crate) in the core

This document describes our use of the pub and pub(crate) visibility modifiers in the core.

TL;DR: The core crate has the following rule: All non-private items are marked pub(crate) unless they are re-exported from the root. Read on for an explanation of why.

The core has a somewhat unique architecture - throughout its module structure, there are many pieces of functionality which are either private to the module or public only to the rest of the crate, but there are also items which need to be exported as part of the core‘s public API. The canonical way of handling this situation in Rust is through “re-exports” - in the root, we write something like pub use crate::foo::bar::do_thing;, which has the effect of exporting do_thing even if it’s not publicly available via the path crate::foo::bar::do_thing.

This works, but has two major downsides. First, there‘s no way, when looking at an item declaration, to know whether it’s marked pub because it‘s intended to be used by other modules in the crate, or because it’s going to be re-exported publicly. Second, there‘s no way to enforce that we don’t accidentally use some item which is not re-exported in the API of one that is. So long as both are pub, the compiler can‘t tell that one is re-exported and the other isn’t. E.g., consider this code:

pub struct Foo;

pub fn takes_foo(foo: Foo) -> { ... }

If takes_foo is re-exported, but Foo is not, then there‘s no way for a caller to actually use this function since they can’t construct a Foo.

To get around these issues, we introduce the following rule:

All non-private items are marked pub(crate) unless they are re-exported from the root.

This addresses both problems. First, it makes it clear from the definition site whether an item is re-exported or not. Second, it makes it so that using a non-re-exported item in a re-exported one will result in a compiler error.

NOTE: This rule is violated in one place: the ip::types module. See the documentation in that module for an explanation of why.