It's always bugged me that --emit metadata
produces different output depending on what else is being emitted - that is, check builds vs pipelined builds.
I've run into this in a very concrete way while trying to implement manual, brute-force pipelining to increase build parallelism for a non-Cargo build system. That is, separately invoke rustc --emit metadata
to produce inputs for dependent libraries, and rustc --emit link
for the final link.
(Yes, this is strictly less efficient than a pipelined build as the frontend work is duplicated. I have the limitation that I can't get intermediate results until the action is complete, but the problem I'm solving is that there isn't enough parallelism available to fill all the cores so the duplicate work shouldn't matter.)
This nearly works except that rustc crashes with:
error: internal compiler error: compiler/rustc_mir/src/monomorphize/collector.rs:826:9: no MIR available for DefId(18:3 ~ bar[8787]::bar)
I can work around this with -Zalways-encode-mir=yes
, but of course that's unstable.
So back to the original question: what if we had --emit check
to generate minimal metadata suitable for check builds, and make --emit metadata
unconditionally produce full mir-enabled metadata?
This would be backwards compatible (with old invokers not knowing about check
getting a perf hit from metadata
, but no functional loss). Forwards compatibility would require cargo check
to see if rustc
supports --emit check
(perhaps streamlined by adding rustc --print emits
?).
And it would also restore the property that artifacts produced by --emit
are independent of the other artifacts, so that invoking rustc once or multiple times is just a performance difference, not a functional one.
Or is there some other solution I've overlooked? Another option would be to keep the existing behaviour and stabilize -Zalways-emit-mir
, but I feel that's less clean (but definitely simpler to implement).