Use-cases for modules not implicitly included in the build


In the pub(restrict) thread there’s a tangential discussion about including all Rust files in the build, vs including only used/referenced vs including only explicit mod.

I have two cases that would be affected, one small, and one huge:

Moving code from bin to lib

The ideal is to keep binary minimal and keep all core functionality in the lib in the project. In practice the boundary is not so clear and shifts as the project grows. With explicit modules I’m able to easily remove modules from one and attach them to the other without moving files around.

If I understand the current proposal to include all files implicitly, it’d be a breaking change for my projects, since I’d have to reorganize files under bin and lib, and move files around instead of moving mod declarations.

Splitting one hardcoded backend into interchangeable multiple backends

I’m writing an app that encodes videos and currently supports only one type of video codec. I’m extending it to support multiple codecs (the problem would be the same if a CRUD webapp added support for multiple databases, or network client for both streaming and buffering interfaces, etc.). For this I duplicated existing backend’s module structure, with multiple files, and did basic find’n’replace on them. I’m going to gradually replace function bodies in the new backend and evolve the interface of both backends as I go along.

So I half of my project works, compiles, is used, and has tests, and half of the project is unused, unfinished mess. The important thing is I need to work on both backends at the same time, since they need to have the same interface (and the interface will likely change).

If Rust included all files implicitly, my project would not compile, and I could not run tests while I refactor it.

  • Source control doesn’t fix it. I want to work on both old and new backend at the same time, so I want ability to compile the project while there are broken files even under source control. At best I’d have to cherry-pick interface changes from the feature brach to a stable branch, switch branches and run tests, and switch back. That’s a lot of extra steps added to a workflow that used to “just work”.

  • Commenting out unfinished modules is tedious, because the backend uses multiple files. Commenting out all code breaks IDEs and source control. “Commenting out” with #[cfg(bogus)] seems like an inelegant “trick” just to keep the project compiling.

AFAIK vast majority of other module systems (imports comparison) do not have this problem (Go is the only exception I know of).

Both cases would work just fine for me if implicit modules were compiled only if they were used (if there was any reference to them), and unused/unreferenced files were ignored. This is what I’m used to from JS and PHP, where this aspect of modules works great.

[lang-team-minutes] the module system and inverting the meaning of public