upvote
> Because Rust commits to the traditional compilation model and pipleine (which I think is overall a good thing, or at least, a good thing to support), it does a lot of work that will eventually be thrown away. Consider this example: I have a library with a function foo that returns a simple 42. I have a binary which calls foo from that library and prints the result. Now imagine the library is a hundred thousand lines of unrelated code to what the binary needs, but is useful for other people. Because compilation works in the "produce libraries, produce binary, link them all together" style model, you have to compile the entire library with all of that code, when all you need is really one function. That intermediate work is useful, and I'm picking an example that's deliberately extreme, of course.

I feel extremely validated reading this! I've had a pet theory for a while that compile times would be drastically reduced if every single item in a crate were implicitly under a cargo feature flag and then they only got enabled if they were imported (and used in non-dead code). I know that making something like that work isn't anywhere close to as simple as I'm describing it, and there are probably a million edge cases, but I've long felt that the ergonomics of Cargo features basically making it too annoying to expose everything conditionally (and then transitively expose all of the features from all of the direct dependencies as well so that things depending on your library could also only conditionally enable them) is secretly the reason that people think Rust compile times are slow, and seeing someone who has way more direct knowledge than me of how all of it works under the hood give a similar take makes me more confident that I might have been on to something all along.

reply
Yes, this idea is sort of similar, just like, more complicated in a sense than the clean design, which is what Zig does.

Incidentally, you might want to look at gc-sections, which Rust already does. As well as https://rust-lang.github.io/rust-project-goals/2025h2/relink... which is kinda related.

The sort of key here is understanding that "produce a library" means that every public item is "used" in the sense of "do we need to compile it." The real trick is to do demand-driven compilation starting from the actual final program's needs, and this is inherently at odds with the idea of producing standalone libraries and combining them into the final artifact.

reply
Makes sense! I think what's most surprising to me about the library compilation model is that for the most part, it doesn't seem like it's actually that useful to how Rust does things by default. Without something like sccache, the intermediate libraries aren't going to be reused across all of my projects, so unless I'm compiling multiple binaries in the same project, I'm not really getting much out of having the entire library sitting there in my target directory rather than just the subset that I'm using. I'm guessing this is related to what you mean by potentially being able to do something differently if there were more time before 1.0?
reply
I think that there is a general desire to work with the system, and since that is how other systems languages have generally done it, doing it the same way feels good. You don't necessarily want to innovate on everything all at once.

It is true that for various reasons, Rust can't take as much advantage as say, C can.

> I'm guessing this is related to what you mean by potentially being able to do something differently if there were more time before 1.0?

I mean more traditional language design things, but sure, this too.

reply
Interesting. My perception for why other systems languages generally compile things to libraries is that they tend to use dynamic linking from a single instance of libraries on a system. I would have expected that when static linking is the default, the argument for having standalone intermediate libraries is much weaker, since the deviation from the other systems languages has already been decided. Maybe I'm missing something about how choosing static linking by default but still supporting dynamic linking requires still having a library as the output always.
reply
> My perception for why other systems languages generally compile things to libraries is that they tend to use dynamic linking from a single instance of libraries on a system.

This is both true and not the whole story. In C, the file (okay if you want to get REALLY technical it's not the file but I'm talking about 99.9% of computers and not some old mainframe platforms) is the compilation unit. You pass a .c in, you get a .o (or whatever for your platform) out. Producing a final binary is where the static vs dynamic choice really comes into play, but you end up with these intermediate artifacts because that is how the language is defined.

> I would have expected that when static linking is the default, the argument for having standalone intermediate libraries is much weaker,

It is weaker, sure. But that doesn't mean there aren't other advantages. For example, you can more easily parallelize a large workload by breaking it up into multiple intermediate libraries, and compiling those simultaneously, whereas doing it all in one compilation/translation unit requires compiler support for said parallelization. Especially if you're already writing a batch compiler, this is a much easier win than rearchitecting the whole thing.

reply
> The real trick is to do demand-driven compilation starting from the actual final program's needs

this is not so far off from hint-mostly-unused, no?

reply
hint-mostly-unused defers codegen of a crate's functions until compiling a dependent crate where those functions are actually called. Therefore, unused functions will not need to be codegen'd.

The downside is that functions which are called from multiple dependent crates will need to be codegen'd in each of their dependents, so this can increase compile times if the crate is not "mostly unused."

So it's not quite as powerful as full demand-driven compilation, because of how Rust separates the compilation process into separate crates.

reply
In my understanding, it's similar, yeah. I don't know enough about how hint-mostly-unused works internally to really speak to the specific differences here.
reply