In Towards a second edition of the compiler, @jntrnr proposed laziness in the compiler:
Laziness
One of the ways that incremental compilation hopes to gain performance is by not redoing work we don’t need to do. We can apply this philosophy to the first compile as well. We shouldn’t build something we don’t need in the output artifact.
Lazy whole-program compilation
Currently, a compilation unit is the crate. This means that for a first compile of a project, all dependencies are fetched and fully compiled before the main crate is compiled. This ignores the fact that it’s possible (and highly likely) a lot of code being built is never used by your project.
Instead, we could approach compilation as whole-program (sometimes called whole-world) with a focus on only building the code that we need to. We could lazily pull in the definitions from dependencies as we use them rather than always building them.
Tree-shaking
Much of rustc’s optimization comes from LLVM, leaving it to do tasks like dead code elimination. We can avoid LLVM doing work it doesn’t need to by shaking our own trees and removing all dead code before handing off the code to LLVM for codegen.
Frontend laziness
Modern compilers aren’t just start-to-finish codegen machines. Often compilers also have to do double duty as ways to drive IDE experiences like goto-def, code completion, and refactoring. To do this efficiently, a compiler needs to be both be able to efficiently recover from user error (as often the code is incomplete when being typed in the IDE), and able to respond to user requests on the order of milliseconds. The latter of these two requires a type-checker that’s more incremental and lazy, recalculating the minimum amount to be able to answer the query at hand.
One technique used by some powerful scripting engines is to parse only enough to get a function’s signature and to know the start and end of its body. While I doubt doing this by itself would grant significant gains, as parsing is not often the dominating time in compilation, it could be coupled with techniques like whole-program compilation (above) to prevent doing even unnecessary parsing.
The current plan for incremental compilation is to cover the frontend to accommodate this case. I believe this can be coupled with a lazy approach to maximize our potential for IDEs.
I wonder what happened afterwards.
Rust is known for its slow compilation speed as of this writing. I think a big reason is the ease to import external crates using Cargo—users usually only need to write a few hundred lines of code and import some popular crates to make the compiler compile hundreds of thousands of lines of code. So, not fully compiling code that are not used by the user's crate (or more aggressively, the binary) should drastically improve the overall compilation time.
Based on my limited knowledge, this would probably be feasible at some intermediate representation level.
To be clear, I am not being rigorous here, and I am simply trying bringing up this topic. I look forward to your more insightful discussions below .