Skip to content

Do not generate coverage records for compile-time-only functions - #161808

Open
fs-rachel wants to merge 3 commits into
rust-lang:mainfrom
fs-rachel:no-coverage-for-always-const-intrinsics
Open

Do not generate coverage records for compile-time-only functions#161808
fs-rachel wants to merge 3 commits into
rust-lang:mainfrom
fs-rachel:no-coverage-for-always-const-intrinsics

Conversation

@fs-rachel

@fs-rachel fs-rachel commented Aug 26, 2026

Copy link
Copy Markdown
Contributor

These functions (which are generally, though not exclusively, intrinsics) should always
resolve to a definite value at compile time, and so should never be called at runtime.
We ensure that these functions never reach codegen using a check in compute_symbol_name
in compiler/rustc_symbol_mangling/src/lib.rs.

However, when generating coverage, prepare_covfun_records_for_unused_functions will
detect them as unused functions (since every call has been replaced by a constant by
this point) and try to generate dummy coverage records. This will trip the above check;
to avoid that, skip generating coverage for such functions.

This is necessary to correctly generate coverage data for core.

@rustbot

rustbot commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in coverage instrumentation.

cc @Zalathar

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Aug 26, 2026
@rustbot

rustbot commented Aug 26, 2026

Copy link
Copy Markdown
Collaborator

r? @mu001999

rustbot has assigned @mu001999.
They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

Why was this reviewer chosen?

The reviewer was selected based on:

  • Owners of files modified in this PR: compiler, mir, mir-opt
  • compiler, mir, mir-opt expanded to 75 candidates
  • Random selection from 18 candidates

@mu001999

Copy link
Copy Markdown
Member

@rustbot reroll

@rustbot rustbot assigned dingxiangfei2009 and unassigned mu001999 Aug 26, 2026
@fmease

fmease commented Aug 26, 2026

Copy link
Copy Markdown
Member

Could you add a regression test and link to the corresponding GH issue if there's one (I think I saw one report earlier but I'm on mobile rn)1? Thanks!

Footnotes

  1. Ah, I was mistaken. I saw https://github.com/rust-lang/rust/issues/161770 which is only related.

@Zalathar

Copy link
Copy Markdown
Member

I'm not familiar with intrinsics, but if something is not supposed to ever exist at runtime then it makes sense to not consider it “unused”.

Comment on lines +56 to +60
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
if tcx.constness(def_id) == (Constness::Const { always: true }) {
return false;
}
}

@Zalathar Zalathar Aug 26, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing two query-cache lookups for tcx.def_kind(def_id) (above and here), we should call it once and stash the result in a local variable.

View changes since the review

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Style-wise, I think this condition would be a little clearer as:

if matches!(def_kind, DefKind::Fn | DefKind::AssocFn)
    && matches!(tcx.constness(def_id), Constness::Const { always: true })
{
    return false;
}

@fs-rachel fs-rachel Aug 26, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That does look a lot nicer, I've incorporated that in the new version of the PR.

Though ideally it should match the check in compute_symbol_name, which IMHO looks a lot less intuitive with that change

Current:

    if let DefKind::Fn | DefKind::AssocFn = def_kind {
        debug_assert!(tcx.constness(instance.def_id()) != hir::Constness::Const { always: true });
    }

Applying that change and running ./x fmt:

    if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
        debug_assert!(!matches!(
            tcx.constness(instance.def_id()),
            hir::Constness::Const { always: true }
        ));
    }

What are your thoughts if I split the difference like this?

    if matches!(def_kind, DefKind::Fn | DefKind::AssocFn) {
        debug_assert!(tcx.constness(instance.def_id()) != hir::Constness::Const { always: true });
    }

@fs-rachel

Copy link
Copy Markdown
Contributor Author

Could you add a regression test [...] Thanks!

Done! I was worried it would be difficult because actually generating coverage for core is non-trivial (our fork has a whole pile of infrastructure for it). But on looking at the existing tests, I realized you can just whack the relevant attribute on a random function, so I did that instead.

@fs-rachel

Copy link
Copy Markdown
Contributor Author

Also I rewrote the comment + commit message to hopefully be clearer about how this all fits together

@fs-rachel fs-rachel changed the title Do not try to generate coverage records for "always-const" instrinsics Do not generate coverage records for compile-time-only functions Aug 26, 2026
@rust-log-analyzer

This comment has been minimized.

@Zalathar

Copy link
Copy Markdown
Member

Wow, that clippy suggestion is awful. I guess we can ignore the lint at the function level.

This test intentionally fails on this commit, and will be fixed by
the following commit
These functions (which are generally, though not exclusively, intrinsics) should always
resolve to a definite value at compile time, and so should never be called at runtime.
We ensure that these functions never reach codegen using a check in `compute_symbol_name`
in `compiler/rustc_symbol_mangling/src/lib.rs`.

However, when generating coverage, `prepare_covfun_records_for_unused_functions` will
detect them as unused functions (since every call has been replaced by a constant by
this point) and try to generate dummy coverage records. This will trip the above check;
to avoid that, skip generating coverage for such functions.

This is necessary to correctly generate coverage data for `core`.
@fs-rachel
fs-rachel force-pushed the no-coverage-for-always-const-intrinsics branch from 6a26779 to 23019ce Compare August 26, 2026 14:43
@fs-rachel

Copy link
Copy Markdown
Contributor Author

Realized the test only needs //@ build-pass, not //@ run-pass

jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 27, 2026
…ouwer

Change `is_eligible_for_coverage` from a hook to a query

- Inspired by seeing rust-lang#161808 add more eligibility conditions
---

This check is called from a few different places when coverage is enabled, so we should probably let the query system take care of memoizing results and tracking dependencies.

(It was made a hook in rust-lang#122322, but I didn't have strong reasons for making it a hook and not a query, other than it being relatively small and simple.)

There should be no user-visible change to compiler behaviour.
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 27, 2026
…ouwer

Change `is_eligible_for_coverage` from a hook to a query

- Inspired by seeing rust-lang#161808 add more eligibility conditions
---

This check is called from a few different places when coverage is enabled, so we should probably let the query system take care of memoizing results and tracking dependencies.

(It was made a hook in rust-lang#122322, but I didn't have strong reasons for making it a hook and not a query, other than it being relatively small and simple.)

There should be no user-visible change to compiler behaviour.
jhpratt added a commit to jhpratt/rust that referenced this pull request Aug 27, 2026
…ouwer

Change `is_eligible_for_coverage` from a hook to a query

- Inspired by seeing rust-lang#161808 add more eligibility conditions
---

This check is called from a few different places when coverage is enabled, so we should probably let the query system take care of memoizing results and tracking dependencies.

(It was made a hook in rust-lang#122322, but I didn't have strong reasons for making it a hook and not a query, other than it being relatively small and simple.)

There should be no user-visible change to compiler behaviour.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants