Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Modules, Visibility, and Re-exports

Rule

Keep modules private by default, expose focused facades, and give each local item one intended public path.

Why

Small public surfaces protect invariants and let implementations move without breaking callers.

Do

  • Keep implementation modules private unless their path is part of the API.
  • Use pub(crate) for real internal boundaries and pub(super) for tight parent-child collaboration.
  • Re-export the public concepts callers should name from the crate root or a focused facade.
  • Choose either a facade path or a public module path as canonical for each local item.
  • Use #[doc(inline)] when a re-export from a public module or another crate should appear at the facade path.
  • Follow struct design for field visibility and naming/imports for preludes.

Avoid

  • Do not expose deep module paths accidentally.
  • Do not use pub when pub(crate) is enough.
  • Do not re-export every internal type from the crate root.
  • Do not expose the same local item through multiple accidental public paths.
  • Do not let implementation churn define public module structure.

Public API Notes

Published libraries treat every intended pub path as compatibility surface. Binary crates normally need only private or pub(crate) boundaries.

Example

#![allow(unused)]
fn main() {
// lib.rs
mod client;
mod error;
mod request;

pub use client::Client;
pub use error::ClientError;
pub use request::Request;
}

Exceptions

  • Use pub mod when the module is an intentional stable namespace.
  • Keep an additional public path only for documented compatibility or a deliberate ergonomic alias.