Revisiting Rust’s modules, part 2


I’ve personally tabled the idea, in part because it would be a much more disruptive change to existing code. By contrast, the proposal in this thread, while requiring some breakage in the next checkpoint, has a very straightfoward, easily automatable fix.

In addition, there’s the possibility of something like being an anonymous module (or also the inline modules thread). So we may be able to recover that idea in a less disruptive, more orthogonal way.

At the moment, my personal focus is to try to find a relatively conservative option that (1) solves some of the more prominent issues in the module system and (2) lays a good foundation for future work like anonymous modules.


Please do not adopt JS’s use/from; it’s grotesque. Adopt Python’s from/use.


I mostly like this proposal, except for deprecating mod. I would like to keep a way to have submodules defined in the parent modules file, or explicitly specify the path of a module. But I’m fine with inferring module structure from directory structure by default.


I had several thoughts on (read: qualms about) the previous proposal.

My thoughts on this one are roughly: ship it. Lots of good discussion up thread about the trade offs but I think this neatly solves the specific teaching/learning model concerns I have with today’s module system as well as sidestepping those raised by the previous proposal.

Edit: except the no-private-modules part.


If modules are pub(crate) by default, then modules with _ e.g. can be used to make it private.


Is this discussion over? Where can I find the conclusion? It’s so sad to see that “directories as module” has been abandoned. I really desperately wanted it…


Here’s the final accepted proposal:


Things have advanced slightly since then, with a bunch of discussion in this thread: The Great Module Adventure Continues

The final version is described in this comment: The Great Module Adventure Continues

The tracking issue is here, with links to the PRs that have been merged so far:



Speaking about trust to the RFC process, in this particular case:

  • There was a somewhat controversial RFC (not too much in the last version), that RFC was accepted.
  • Then there was a decision to change the rules significantly from the accepted version (extern prelude, standard crates in the prelude, all that).
  • That decision is hidden somewhere deep in the internals thread and never went through RFC process and community feedback.

To clarify, I more or less like where import/crate use went in the result (except for the edition breakage, to which I’m partly to blame because I didn’t have enough time to implement the import resolution fallback), just pointing to the process issue.

I think even mini-RFC updating the formal text in place and “synchronizing RFCs and reality” would be a big improvement.


Ah right, I was looking at the date on the proposal and things weren’t quite adding up with when I remembered discussions happening, but it said “merged” and had an open implementation issue, so I went with it. I guess the key change in the target syntax is adding external crates to prelude so you don’t have to use them, or prefix with :: in items unless they are locally shadowed. As far as transition, am I correct that crate-relative use paths without crate:: are being deprecated much harder than they were before? Anything I’m missing?


It seems final proposal is talking only about crate and path stuffs. When I see some articles, there was intention to remove implicit module definition by file, but it seems disappeared now. Is that declined or just deferred?


The change being pursued as far as how the file system relates to the module structure is more conservative now. You still need explicit mod declarations, but you can put them in instead of having to move your code to foo/ when you add submodules to foo.


It seems what I was thinking is slightly different.

My intention is making only directories to define modules, and files don’t. In this way, directory structure still reflect module structure, therefore, there’s no penalty on navigability. Actually this can provide better navigability by splitting one giant .rs file into multiple pieces (which shows actual structure better) without pub use everywhere or duplicated namespace/symbol names. For example,


And is

pub fn foo() {}

Then you get only qux::bar::foo() instead of qux::bar::foo::foo(). In my opinion, too much efforts needed to build this kind of module structure with pub use or just I have to everything in one big giant .rs file. In either way, really doesn’t help navigability.

As I don’t know well about history, I am not sure whether this kind of design already been addressed or not. Someone please let me know why if this design has been excluded.


Is it just me, but isn’t using the crate keyword in place of a module path make it ambiguous to the reader?

use crate::foo;
use something::bar;

The syntax of this makes it look like crate is an external module, not a keyword. Is this addressed currently?


How is that different from self and super in paths today?


In this respect, crate functions similarly to super.

use crate::foo; // refer to module from crate root
use super::bar; // refer to parent module

That is, distinguishing the keyword from an external module is a code highlighting exercise.


There is- you no longer know which file may contain a definition (or re-export of the definition), and must search whole directories instead.

The design you want was decided against at some point, though there were also a lot of ideas around making re-exports easier that would get you part of the way there.

This is intentional. “All paths start with a crate name,” where crate is the name of the current crate. (It can’t be the actual name because there can be more than one crate with the same name and they often depend on each other- e.g. in a binary crate depending on a library crate of the same name.)


About 2 weeks ago, I learned that impl code can be split into other modules. Since that, I think current module system is great and satisfying.