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 any use foo or use 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 having include/require.
- If a module only has
impl, and no items from it are used explicitly, you’ll need to use it explicitly (or keep a mod).
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 absolute use path::to::foo, both having confusingly similar effect to novice users.
Downsides:
- Relative
mod foo becomes absolute use path::to::foo or use 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