Recap as of 2017-06-05

Problems we (might) want to solve

  • Mental model issues
  • Distinctions between extern crate, mod, use and pub use often hard for newcomers
  • Paths are sometimes absolute, sometimes relative
  • The top-level namespaces mixes in crate names from external crates, and the contents of the current crate
  • Makes moving code from a library out to an external crate annoying
  • mod.rs is a bit weird and confusing; it makes refactoring more painful than it should be
  • The privacy system can be very confusing and hard to navigate
  • The default rules about who can see private items are, to many, not intuitive and hard to remember
  • The mixture of privacy and re-exports can make it pretty hard to know how exposed a particular item is
  • pub(restricted) helps
  • It’s confusing than an inline mod { .. } declaration doesn’t automatically inherit the bindings from the outer scope (equivalent to use super::*)
  • Tedium/redundancy issues
  • extern crate is redundant with Cargo.toml
  • mod declarations are often redundant with the file system

Observations on the current module system

  • Coupling
  • Ties together three things:
  • Files
  • Namespacing
  • Privacy
  • However, the coupling is incomplete; there are various escape hatches that let you break the connections between these three things, and that’s part of where confusion arises.
  • Use-cases for features
  • pub use
  • Re-exporting upstream types (when you don’t want your clients to have to deal directly with one of your public dependencies)
  • Using a submodule for organization and/or privacy, but not for namespacing
  • preludes, or otherwise making access more convenient
  • Crucially, these are re-exporting items already publicly accessible from a different path

Tricky use-cases we (may) want to retain

  • Attributes on extern crate declarations
  • macro_use
  • Are there others?
  • Attributes on mod declarations
  • Privacy
  • #[cfg]
  • Uses of modules that couple files and privacy, but don’t couple public namespacing
  • e.g., define a submodule for building out a type and a bunch of operations on it with privacy, but then re-export that type in super
  • Of course, these still affect “internal” namespacing, which also leads to multiple paths being usable inside a module to reach the same item.
  • Privacy between modules of a crate
  • This means, for example, that having a totally orthogonal “public item hierarchy” through explicit export statements is not clearly workable

How to get the coupling we want, and avoid the ones we don’t

  • Definitely want to couple files and privacy
  • “Coupling” filesystem and namespacing doesn’t have to be totally 1-1 correspondence
  • Just need the ability to easily predict the API hierarchy from running tree
  • (and not the other way around)

One idea:
  • if you leave off mod.rs then the submodules are pub use self::sub::* and are themselves private