In responses to the latest modules RFC there is some push back against automatically loaded modules, so I’d like to propose a refinement to the autoloading idea.
Only modules that are used are loaded.
(where use means either explicit mod
as it is currently, and/or appearing in any use
path in the project).
This means that a stray file on disk won’t be automatically included in the project. There has to be at least one use
somewhere that refers to it in order for the file to be included in compilation. If you rely on hiding a module by commenting out mod foo
, you can do the same by commenting out use foo
. #[cfg] mod foo
is satisfied by #[cfg] use foo
.
Changes from current behavior:
- You don’t need
mod foo
if there is anyuse foo
oruse foo::bar
statement. For new users it will appear as if all modules exist, and are ready to use. This is very close to behavior of other languages havinginclude
/require
. - If a module only has
impl
, and no items from it are used explicitly, you’ll need touse
it explicitly (or keep amod
).
Advantages:
- Untracked/unfinished/garbage files aren’t surprisingly included in the project
- Source code still describes its own module hierarchy, and it’s still possible to comment out a module by editing project’s source code.
- Removes confusion between relative
mod foo
and absoluteuse path::to::foo
, both having confusingly similar effect to novice users.
Downsides:
- Relative
mod foo
becomes absoluteuse path::to::foo
oruse self::foo
- Visibility of modules is not explicit (it’s
pub(crate)
by default, and other proposed mechanisms for exporting may be needed). - unused import lint may need rethinking