Modules proposal for 2017-06-08

High-level plan

  • Focus on highest-impact changes, leaving room for further revisions later on
  • In particular, this likely means not doing anything with the relative/absolute path issues until we have experience with other changes
  • Split up into separate RFCs where possible
  • Make extern crate optional - any dependency named in the Cargo.toml would be accessible to use.
  • Make foo.rs with foo/ work like foo/mod.rs (and deprecate latter)
  • I wouldn’t mind this if you didn’t deprecate the latter
  • although I’d really prefer foo/self.rs, if I were designing it from scratch
  • Part of the objection is that if you have {foo,bar,baz}/mod.rs (or self.rs) open, they all have the same basename in an editor.
  • Revamp module declarations and privacy (aka, the big change)

Revamping module declarations and privacy

Observations about the current system:
  • Tight coupling between namespacing and file structure:
  • Namespacing — Rust path to the Rust item: foo::bar::Baz;
  • File structure — file system path to file containing the item: src/foo/bar.rs
  • Users often don’t want these two things to be coupled together:
  • Today, they can create multiple modules in one file with mod foo { }
  • But to separate a module into multiple files, they have to “facade” with pub use.
  • This seems like what people want very often, which is why facading is so common.

Better solution: 
  • anonymous modules 
  • expressing module structure purely through filesystem
  • item-centric privacy

Anonymous modules

  • mod { /* stuff here */ }
  • If you write _foo.rs, it’s treated automatically as an anonymous module:
src/iter
   mod.rs
   _map.rs // Defines `struct Map`, exposed as `iter::Map`
   _filter.rs // Defines `struct Filter`, exposed as `iter::Filter`
   ..etc
  • This acts as a privacy boundary but doesn’t affect the API hierarchy — all non-private items are pub used by the parent module automatically.
mod foo {
  mod {
    pub struct Foo; // this is available as foo::Foo
    // Cannot reference Bar::field
  }
  
  mod {
    // available as foo::Bar
    pub struct Bar {
      field: u32, // only visible within this anonymous module
    }
    
    impl Bar {
      // same as private -- only available within this anon module
      // this works *exactly* as if the `mod` declaration was a proper module, just
      // one that doesn't have an externally-accessible path, and with