Open RalfJung opened 2 years ago
So what would be a way to fix it? The only option I can think of right now is to perform some kind of "fake monomorphization" with --emit=metadata
, to ensure that we actually evaluate all the constants that will be evaluated in a proper build, but skipping all the actual generation of LLVM IR.
Tangential question: is there an official guarantee as to what cargo check
is supposed to catch?
Tangential question: is there an official guarantee as to what
cargo check
is supposed to catch?
I think, almost everyone expect it to catch everything as actual compilation would. This is a whole point of it: check compilation errors without generating code.
https://github.com/rust-lang/rust/issues/49292 is a related but different issue -- this one here is about errors due to const-eval running only during monomorphization (which check
doesn't run); https://github.com/rust-lang/rust/issues/49292 is about errors that show up pre-monomorphization but that are emitted by lint passes which are not run during check
.
To fix this, we have to at least do something like a "mentioned item" monomorphizing traversal of the collector (also see https://github.com/rust-lang/rust/pull/122568). Fundamentally there's no way to avoid having to touch the same function multiple times, since it might be instantiated with different types implementing a trait and their associated consts may behave differently.
So the regression for check times is likely going to be gigantic. It will be up to the compiler team to decide if they want to take that or not. (RFC 3477 puts this choice into t-compiler jurisdiction. It even mentions not doing any kind of monomorphization during check builds -- for performance reasons -- as a motivation for why we are okay with check builds passing when full builds fail.)
I think this issue will likely remain open at least until we decide to have "slow" and "fast" check builds. But it's still useful to have this as a central tracking location.
I did an implementation experiment in https://github.com/rust-lang/rust/pull/122744 (to be able to measure the regression). Some work needs to happen before we can even do the experiment:
So the information to do this is simply not present because we don't store the MIR of things in rmeta files, or something like that? To to make this approach work I think we'd have to (a) make "mentioned items" traversal work without full MIR (based on Oli's proposal of a separate query that just returns the mentioned items), and then (b) do a mentioned items traversal of everything (rather than the usual used items traversal) in a check build.
Consider the following code:
When I do a check-build of this (
rustc --emit=metadata
), it works fine. But when I do a full build (rustc --emit=link
), it fails:This is a post-monomorphization error. It is a long-known problem but I could not find an issue tracking it.
It seems worth tracking as it is rather surprising, so if we can find a way to fix it, that would be great. It also leads to issues with Miri such as https://github.com/rust-lang/miri/issues/2423.
All that said, currently this is intended behavior. This RFC gives some relevant background:
This is related to https://github.com/rust-lang/rust/issues/49292 but not the same -- that issue is about lints that arise pre-monomorphization, during MIR passes that are skipped in check builds. This here is about errors that appear even later during compilation.