@SimonSapin in C and C++ you can have circular dependencies between translation units, but this does not imply that the whole language can be used in the circular dependent parts of the translation units. In fact, if the interface of two dependent TUs depend on each other, there is actually very little that you can do there: e.g. types can only be used behind pointers, templates/inline functions and member functions cannot easily have circular dependencies because they must be implemented in headers, etc. In many cases (not all) circular dependencies in C and C++ are at least problematic and often require workarounds.
Rust has ways of expressing similar things. It might be easier or harder to do than in C or C++ (depending on the case), but I think it is worth pointing out that splitting code into TUs in C and C++ is not always easy either. Books have been written about how to build large C and C++ applications such that their builds do scale, idioms have been discovered (PIMPL wasn’t a thing 20 years ago), etc.
IMO the main difference is cultural. The C and C++ communities actively dealt with the problem instead of living with the hopes that the compilers would become infinitely better some day. Maybe because the C and C++ communities are not really tightly connected to their compiler developers.
The Rust community is tightly connected to the Rust compiler developers, and I think this is for the better, but if the compiler developer say that “incremental compilation/parallel code gen/distributed builds/…” will fix all of Rust’s compile-time problems then people just say “Rust compiles slowly because it is a young language” and live with it instead of actively exploring how the language can be used to improve compilation times.
I think it would be more helpful to use this close relationship with compiler developers to come up with strategies/guidelines that make code compile fast today. As the compiler gets better over time, some of these strategies might become deprecated, or who knows, some might even get language support. Otherwise it gives the impression that either you can live with long compile-times, or you can’t use Rust today - maybe in N years, maybe never, who knows. But this impression is wrong, there are many many things one can do to improve Rust’s compile-times today, and if somebody has a compile-time problem, we should have a resource that we can point at them to tell them: these are all the things you can do to make your code compile fast.
@masonk
The system should just make the creation of small and efficient TUs the easiest and most obvious thing to do.
I agree. But this is a hard problem. It is way easier to provide “system” support for it if the users have already discovered the idioms / pattern that work for this. This is basically what happened with C++ modules. They are just a way of enforcing what users of really large builds were already doing (linking TUs hierarchically instead linearly at the end, using compilation firewalls, using PCHs, not using macros in ways that PCHs break, etc.).
The crate is both a unit of compilation and a unit of distribution
I think this is a crates.io issue. There are many crates that are split into sub-crates, where these sub-crates (or some of them at least) are not intended to be used by anybody in isolation. However, crates.io forces you to publish each of these sub-crates as a standalone crate. I’d like to be able to publish a workspace as a single crate.io “crate”, and have it include all the crates in my workspace, without “publishing” those independently. Obviously these sub-crates would still be uploaded to crates.io, but maybe they could be “hidden” or somehow marked as not intended for distribution, or…