-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Which functions are "reachable", and therefore subject to monomorphization-time checks, is optimization-dependent #122814
Comments
The second approach is insufficient to resolve this issue. Consider the example below or anything else that takes advantage of the fact that reachability is a static conservative over-approximation of the actual mono item collection. #![crate_type = "lib"]
#![feature(inline_const)]
pub fn f() -> fn() {
loop {}; const { g::<()>() }
}
const fn g<T>() -> fn() {
match std::mem::size_of::<T>() {
0 => ga as fn(),
_ => gb as fn(),
}
}
#[inline(never)]
fn ga() {
}
#[inline(never)]
fn gb() {
if false { const { 1 / 0 }; }
} |
Ah, I see. We'd have to walk the mentioned items of constants we encounter as well, then.
Can a similar example be constructed based on all trait impl fn being considered reachable?
|
All trait impls being reachable seems like a non-issue, because they are only used to seed an initial set of items. At this stage of computation there is no optimization level dependency yet. |
@tmiasko can you turn your example above into a testcase that actually demonstrates opt-dependent behavior? I tried and failed. |
collector: always consider all monomorphic functions to be 'mentioned' This would fix rust-lang#122814. But it's probably not going to be cheap... Ideally we'd avoid building the optimized MIR for these new roots, and only request `mir_drops_elaborated_and_const_checked` -- but that MIR is often getting stolen so I don't see a way to do that. TODO before landing: - [ ] Figure out if there is a testcase [here](rust-lang#122814 (comment)). r? `@oli-obk` `@tmiasko`
Sure, I edited the comment by adding an erroneous constant to |
Thanks! I played around with this a bit, here's a variant that avoids #![crate_type = "lib"]
#![feature(inline_const)]
// Will be `inline` with optimizations, so then `g::<()>` becomes reachable.
// At the same time `g` is not "mentioned" in `f` since it never appears in its MIR!
// This fundamentally is an issue caused by reachability walking the HIR and collection being based on MIR.
pub fn f() {
loop {}; const { g::<()>() }
}
// When this comes reachable (for any `T`), so does `hidden_root`.
// And `gb` is monomorphic so it can become a root!
const fn g<T>() {
match std::mem::size_of::<T>() {
0 => (),
_ => hidden_root(),
}
}
#[inline(never)]
const fn hidden_root() {
fail::<()>();
}
#[inline(never)]
const fn fail<T>() {
// Hiding this in a generic fn so that it doesn't get evaluated by
// MIR passes.
const { panic!(); }
} |
I think the second approach can still be salvaged. The key property we need is that everything that EDIT: It's probably a bad plan as it makes it harder to do things like #122301, which rely on not doing "mentioned items" things with |
So the status here is that I have a draft of the first approach described in the OP in #122862 but perf is not looking great. Not terrible, either, but a 4% regression for some primary benchmarks is unfortunate. The solution is likely to find a way to encode |
This is a variant of #107503, but with a different underlying cause and hence not fixed by #122568. @tmiasko provided this magnificent example (comments by me, they may be wrong):
The symptom here is the opposite of #107503:
cargo build
succeeds butcargo build --release
fails. This is because more things become roots in optimized builds and therefore we evaluate more things.I can think of two ways of fixing this:
g
is considered "mentioned" inf
. This requires either collecting (some of) the mentioned items very early during MIR building, or makingSimplifyCfg
preserved unreachable blocks. This likely has lower perf impact, but it means we'd still miss const-eval failures reachable from dead private monomorphic functions.The text was updated successfully, but these errors were encountered: