blob: ab978a68769b34c12ca83e676f2c70413656b1fd [file] [log] [blame] [view] [edit]
# `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:
```rust
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.*