rust-lang / rust

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

link-dead-code does not include symbols for unused inlined functions #45174

Open malbarbo opened 7 years ago

malbarbo commented 7 years ago

Consider a file x.rs:

#[inline]
fn gggg() {}
fn main() {}

The symbol gggg is not included in the compiled binary (tested with rustc -C link-dead-code x.rs && nm x | grep gggg). If the inline attribute is removed, the symbol is included.

michaelwoerister commented 7 years ago

This is currently expected behavior as the compiler never generates any code for #[inline] functions unless they are referenced somewhere.

malbarbo commented 7 years ago

But this seems contrary to the intent of the link-dead-code (improve coverage accuracy, see https://github.com/rust-lang/rust/pull/31368)

michaelwoerister commented 7 years ago

Yes, I can see how that would make sense when you are interested in code coverage.

@rust-lang/dev-tools @rust-lang/compiler Do we have compiler options that are targeted specifically towards code coverage? Or should we just produce code for unused inline functions if -C link-dead-code is specified?

alexcrichton commented 7 years ago

@michaelwoerister AFAIK we don't have many other options for code coverage, we're definitely long overdue for a flag for "I'd like to generate code coverage", but there's lots of hairy problems about implementing such a flag (e.g. inline functions today, generics, etc)

fitzgen commented 7 years ago

If we don't want to extend the meaning of link-dead-code, perhaps it makes sense to add something equivalent to gcc's/clang's -fkeep-inline-functions flag?

I don't feel like the smaller emit-unused-inline-functions-in-the-binary feature needs to be blocked on a more general code coverage mode.

michaelwoerister commented 7 years ago

Yeah, adding a targeted flag instead of changing the meaning of -C link-dead-code seems to preferable to me.

steveklabnik commented 5 years ago

Triage: I'm not aware of any changes or additions here.

tgnottingham commented 1 year ago

As of rustc 1.72.0, the original repro, verbatim, doesn't reproduce the issue.

These cases still do:

While these cases do not:

However, if the function is instead marked #[inline(always)], the issue reproduces in all cases, including the original one.


For the #[inline(always)] issue (without the involvement of -C opt-level > 0 or -C lto=thin), the problem is that the mono item is never placed in any CGU. The reason is in part that MonoItem::instantiation_mode returns LocalCopy for the item, despite the presence of -C link-dead-code. place_mono_items doesn't place it because its instantiation mode LocalCopy, and because nothing else calls it.

It would be tempting to have MonoItem::instantiation_mode not return LocalCopy if -C link-dead-code was used, but this would cause #[inline(always)] functions to not always be inlined, and comments like https://github.com/rust-lang/rust/pull/76896#issuecomment-758097233 make me wonder if that's a problem. On the other hand, I wonder if -C link-dead-code fundamentally relies on inlining not happening to work as desired.