rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
97.95k stars 12.68k forks source link

Unreachable post-monomorphization error triggered by `-C link-dead-code` #131793

Open joshlf opened 1 week ago

joshlf commented 1 week ago

I have the following code:

#![allow(dead_code)]

trait Foo {
    fn baz() {
        const { panic!() }
    }
}

impl Foo for () {}

If I build normally (using cargo build), it succeeds. If I build passing RUSTFLAGS='-C link-dead-code', Rust attempts to monomorphize Foo::baz and fails despite Foo::baz never being used:

error[E0080]: evaluation of `<() as Foo>::baz::{constant#0}` failed
 --> src/lib.rs:5:17
  |
5 |         const { panic!() }
  |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', src/lib.rs:5:17
  |
  = note: this error originates in the macro `$crate::panic::panic_2021` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)

note: erroneous constant encountered
 --> src/lib.rs:5:9
  |
5 |         const { panic!() }
  |         ^^^^^^^^^^^^^^^^^^

note: the above error was encountered while instantiating `fn <() as Foo>::baz`

Post-monomorphization errors (PMEs) are often used to detect error conditions at compile time that cannot be encoded in the type system proper. We do this in zerocopy 0.8 in certain APIs to ban dynamically-sized types whose trailing element type is zero-sized.

cargo fuzz builds using -C link-dead-code, and so it has been causing build failures for our users. In our specific case, it's possible to work around this because (for entirely coincidental reasons) the issue is only triggered by deprecated APIs that we can likely just remove. However, it's only luck that this hasn't caused more serious breakage for us.

I'm not sure what the right thing to do here is. From our perspective, having -C link-dead-code be more permissive would be good, but I understand why that might not be desirable for other users.

Miscellaneous

Cargo version 1.81.0.

the8472 commented 6 days ago

122301 might be of interest here. Basically: by introducing a generic you can delay the instantiation of the const until it's used with some concrete T. This isn't a guaranteed language property yet but it seems like opinions are leaning towards that way.