Skip to content

Which functions are "reachable", and therefore subject to monomorphization-time checks, is optimization-dependent #122814

Open
@RalfJung

Description

@RalfJung

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):

//! This used to fail in optimized builds but pass in unoptimized builds. The reason is that in
//! optimized builds, `f` gets marked as cross-crate-inlineable, so the functions it calls become
//! reachable, and therefore `g` becomes a collection root. But in unoptimized builds, `g` is no
//! root, and the call to `g` disappears in an early `SimplifyCfg` before "mentioned items" are
//! gathered, so we never reach `g`.
#![crate_type = "lib"]

struct Fail<T>(T);
impl<T> Fail<T> {
    const C: () = panic!(); //~ERROR: evaluation of `Fail::<i32>::C` failed
}

pub fn f() {
    loop {}; g()
}

#[inline(never)]
fn g() {
    h::<i32>()
}

// Make sure we only use the faulty const in a generic function, or
// else it gets evaluated by some MIR pass.
fn h<T>() {
    Fail::<T>::C;
}

The symptom here is the opposite of #107503: cargo build succeeds but cargo 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:

  • Making the set of collection roots opt-level-independent. This is what I tried in a303df0. It caused a ~2% slowdown on some benchmarks; it's hard to get the full picture as we only benchmarked it together with the rest of recursively evaluate the constants in everything that is 'mentioned' #122568. There may be ways to reduce this cost.
  • Make sure g is considered "mentioned" in f. This requires either collecting (some of) the mentioned items very early during MIR building, or making SimplifyCfg 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-const-evalArea: Constant evaluation, covers all const contexts (static, const fn, ...)A-monomorphizationArea: MonomorphizationC-bugCategory: This is a bug.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions