I would like to present an evolution of ideas presented in the comment to the second module proposal. This proposal tries to incorporate ideas from other posts (and respective comments) and to find a reasonable compromise on some issues. It still has some holes in the reasoning and description, but I hope it will help with the further discussion of the topic.
Other proposals and discussions
- Revisiting Rust’s modules
 - Revisiting Rust’s modules, part 2
 - Revisiting modules, take 3
 - pre-RFC: inline mod
 - pre-RFC: from crate use item
 
Abstract model
We can model module system as a way to construct a directed graph (possibly with cycles, see open questions) with two types of nodes: item and module. “Item” type covers not only usual visible items: structs, traits, functions and others, but also “invisible” as well, e.g. impl blocks or trait implementations, which should be linked to the graph to be usable. “Module” type essentially just a way to organize access paths to the items from the given “module” node. (e.g. from the root represented by lib.rs, which will be named as “crate” from here) Note that one item can be accessed through different paths. (e.g. crate::foo::bar::zoo::Item and crate::prelude::Item)
Edges have only one type. All nodes and edges should be organised in a such way that all “item” nodes should be reachable from the “crate” node.
Nodes and edges can be marked as “exported”. Root node is always marked as “exported”. All “exported” nodes and edges should form a connected graph (note: not tree), which will be called “exported” graph.
We can link external “exported” graphs from our graph by creating edges to its nodes.
In the code
To represent the graph described earlier we will need the following tools:
- 
use path::to::node;– main tool for creation of edges (linking). Path is relative to the module in which it’s used. If needed will attempt to create nodes and edges by following files and directories on the file system. Absolute paths represented using reserved node namecratewhich represents “root” node. (usuallylib.rs, but can be overwritten byCargo.toml) So absolute import will look likeuse crate::foo::bar;. - 
from cratename import path::to::node;– create an edge to an external “exported” graph from crate listed in theCargo.tomldependencies section with absolute path inside of it.path::to::nodeshould go over nodes and edges marked as “exported”. - 
export path::to::node;– linknodeto the current module and mark it as “exported”. Node can be marked as exported more than once.pathandtostay unchanged. (so if they were not marked as “exported” they stay unexported) Edgecurrent_module -> nodemarked as “exported”. 
While it’s enough to have tools described earlier it’s certainly inconvenient to use just them. Thus we need additional tools usable inside mod.rs and lib.rs:
- 
use(auto) [self];– will desugar intouse {foo, bar, ...};wherefoo.rs,bar.rsand others are files in the same directory. - 
use(auto) foo;– will link modules defined in the files insidefoosubdirectory, which should not containmod.rs. - 
use(inline) [self];– will link all public items inside modules defined by the files in the same directory, but will not link those modules. So “module” node defined by thefoo.rswill not be reachable from the root, but all public items inside it will be linked to the current “module” node. - 
use(inline) foo;– “inline” files insidefoosubdirectory, which should not containmod.rs. - 
export(auto/inline) [self, foo];– behaves exactly likeuses, but additionally marks linked nodes and respective edges as “exported”. - 
import crate_name;– link root node of external crate. (analogue ofimport crate_name import self;) 
Dangling “exported” node (i.e. node without path from crate node passing through nodes only marked as “exported”) will trigger a warning while compiling, as it will not be accessible for user of the crate.
We can “export” nodes (items and modules) imported from another crate too, so this is a correct code: import foo;
Privacy
Only items marked as pub can be marked as exported, otherwise it will result in the compilation error. pub implies pub(crate). Stricter privacy constrains can be placed on items which will limit edges creation and referring through paths.
Common patterns
Some common library patterns and how they will look under this proposal. (section will be updated based on discussion)
Facade
export(inline); fully covers this use-case and additionally allows more flexible directory structure. E.g. using features example from the first @aturon post we can write:
export(inline) {self, flatten, map, select};
Here flatten, map and select are subdirectories which contain flatten.rs, flatten_stream.rs, map.rs, etc. lib.rs will contain export future;
Prelude
We have crate with the following items (all path points marked as “exported”): foo::t:Item1, foo::t2::Item2, bar::Item3. For convenience we want to expose them through prelude, so users could import them as from my_crate import prelude::*;. To implement it in lib.rs we need to use export prelude; and in prelude/mod.rs:
export crate::foo::t1::Item1;
export crate::foo::t2::Item2;
export crate::bar::Item3;
Or if we really want to abuse multi-line:
export crate::{
   bar::Item3,
   foo::{
      t1::Item1,
      t2::Item2,
   }
}
Re-factoring single file into folder
For example we have foo.rs containing Item1 and Item2 which became too large. We want to create a folder foo with the code for those items. We can just move foo.rs to foo/foo.rs, create file foo/bar.rs and copy Item2 code to it. Now inside lib.rs if we had export foo::{Item1, Item2}, we can change it to export(inline) foo, or to export foo::{foo::Item1, bar::item2}.
Simple crate
lib.rs:
export foo;
foo.rs:
export Item;
pub struct Item;
bar/mod.rs:
export(auto);
bar/zoo.rs
// Will not be accessible as crate::bar::zoo::Item in the exported graph
use crate::foo::Item;
pub struct Zoo;
Item will be accessible through from simple_crate import foo::Item; and Zoo through from simple_crate import bar::zoo::Item;
Pros and cons
Pros
- Clear design with relatively small number of rules
 - Explicit implicitness of using folders and files for defining modules.
 - Flexibility, allows fully explicit or highly implicit approaches
 - Intuitively covers common use-cases
 - Easier to teach
 - Solves “automatic promotion of key items” problem
 - No conflict between simultaneous 
lib.rsandmain.rs 
Cons
- New keywords
 - Significant breakage compared to the current system
 - 
autoandinlinewill certainly be most common, which will encourage implicitness across ecosystem - In depth explanation can be a bit tricky due to the more complex model
 
QA
Why “from foo import bar” and not “from foo use bar”?
We already breaking use pattern with the introduction of from keyword, so the only reason to keep use is for backward compatibility. Meanwhile introduction of export keyword makes import feel quite natural, while also allowing convenient shortcuts like import cratename; instead of from cratename import/use self;. And of course it will feel very familiar to people coming from Python, which one of the main sources of Rust grow.
Don’t we place too much functionality on use keyword?
Probably yes, in this proposal use and by extent export can be use for two things: linking source files from file system and creation of “shortcut” links. Initially I thought about using mod (plus mod(auto) and mod(inline)) for linking files and convenience combination export mod(auto/inline) [foo] for exporting stuff, while using use keyword only for “shortcut” edges creation. I like such design a bit more as we explicitly define two types of edges on module graph, with mod edges required to form a tree, it simplifies some things conceptually, but makes it a bit harder to learn. (beginners confusion between mod and use which we witness today) But looking at a general direction of other proposals, I’ve decided to remove mod as well. Although this decision can change based on discussion.
Open questions
- How to correctly define 
supernodes in the given model. - Rules regarding “bad practices” of using 
autoandinline. - Can we do without restriction on 
mod.rsfor directories linked throughuse(auto/inline) foo? - Change keyword usage to be more backward compatible?
 - 
crate::foo::barvs::foo::bar - Should we keep 
modkeyword for example for inline modules? - Should we explicitly forbid creation of cycles in the module graph or should we allow it?