Principles for using 'mod' vs 'pub mod'

  1. When I first started with Rust, I tended to just use pub mod everywhere as it was “easier”

  2. I’m now shifting to a style where I use mod everywhere, with pub use for anything I need to export.

  3. I don’t know if this is the right style (or if I’m going overboard). Is there a number of “standard mod vs pub mod” styles I can pick from?

“style” is really just whatever you want it to be, or, even better, whatever is the best.
Here are some examples for either:

  • pub mod:
    • When you want to distinguish between self (In module terms) and my_module,
pub mod has_derived_a {
    struct DerivedA;
    impl super::Trait for DerivedA {}
    //Some more items relating to `a`
pub mod has_derived_b {
    struct DerivedB;
    impl super::Trait for DerivedB {}
    //Some more items
pub trait Trait {}
  • pub use:
    • When you want to use my_module's members as my own, but have them in a separate file
    • When you want to rename a member:
mod foo {
    struct Bar<T> {z: PhantomData<T>}
pub use foo::Bar as Cont;
1 Like

I strongly believe that pub mod is overrused. By keeping most modules private and using pub use to expose a flatter heirarchy (a.k.a. the facade pattern), you:

  • Make the public API easier to learn and use.
  • Make it easier to move things to other places while refactoring without breaking the public API.

Some people look at std and see how nested its public API is and think that’s how their crate should look. But std is different. std has the scope of fifty crates. (and in fact it still makes plenty of use of the facade pattern; the public module tree you see is only the tip of the iceburg!)

That said, sometimes a pub mod is useful as a documentation page. The way it’s used for disambiguation in crates like bzip2 is also reasonable.

I also like to have a pub mod for a collection so it can contain types with general names like IntoIter.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.