Skip to content
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

Coverage instrumentation sometimes thinks the negation operator isn't executable #115468

Closed
Zalathar opened this issue Sep 2, 2023 · 5 comments · Fixed by #118198
Closed

Coverage instrumentation sometimes thinks the negation operator isn't executable #115468

Zalathar opened this issue Sep 2, 2023 · 5 comments · Fixed by #118198
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@Zalathar
Copy link
Contributor

Zalathar commented Sep 2, 2023

#111752 introduced this behaviour in coverage reports:

   LL|       |    if
   LL|       |        !
   LL|      1|        is_true
   LL|      0|    {

Notice that the line with ! no longer has a coverage count, even though it should have the same count as is_true.


This is caused by the fact that MIR building specifically handles if ! by flipping the then/else arms, so the original condition expression (containing !) does not have its span represented by any statement in MIR.

@rustbot rustbot added needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-bug Category: This is a bug. labels Sep 2, 2023
@Zalathar
Copy link
Contributor Author

Zalathar commented Sep 2, 2023

(This issue is based on my original notes at #111752 (comment).)

@Zalathar
Copy link
Contributor Author

Zalathar commented Sep 4, 2023

This seems to be the result of if !cond { a } else { b } being lowered as though it were if cond { b } else { a }.

When that happens, the ! operation no longer exists as a MIR node, so InstrumentCoverage can’t see it normally, and doesn’t have special-case handling to look back at HIR and see that this has happened.

For now, it’s probably not worth trying to add another special case, since the difference is hardly noticeable most of the time. It might be worth revisiting this if we ever implement deeper coverage integration into HIR-to-MIR lowering.

@Zalathar
Copy link
Contributor Author

Zalathar commented Sep 4, 2023

@rustbot label -needs-triage

@rustbot rustbot removed the needs-triage This issue may need triage. Remove it if it has been sufficiently triaged. label Sep 4, 2023
@Zalathar
Copy link
Contributor Author

@rustbot label +T-compiler

@rustbot rustbot added the T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. label Nov 22, 2023
@Zalathar
Copy link
Contributor Author

As I continue to investigate branch coverage, this has become more of a concern.

When the user writes if !cond, I want the branch region to cover all of !cond (not just cond), and I want its true/false arms to reflect the value of !cond (rather than the value of cond).

workingjubilee added a commit to workingjubilee/rustc that referenced this issue Dec 9, 2023
coverage: Use `SpanMarker` to improve coverage spans for `if !` expressions

Coverage instrumentation works by extracting source code spans from MIR. However, some kinds of syntax are effectively erased during MIR building, so their spans don't necessarily exist anywhere in MIR, making them invisible to the coverage instrumentor (unless we resort to various heuristics and hacks to recover them).

This PR introduces `CoverageKind::SpanMarker`, which is a new variant of `StatementKind::Coverage`. Its sole purpose is to represent spans that would otherwise not appear in MIR, so that the coverage instrumentor can extract them.

When coverage is enabled, the MIR builder can insert these dummy statements as needed, to improve the accuracy of spans used by coverage mappings.

Fixes rust-lang#115468.

---

`@rustbot` label +A-code-coverage
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Dec 9, 2023
coverage: Use `SpanMarker` to improve coverage spans for `if !` expressions

Coverage instrumentation works by extracting source code spans from MIR. However, some kinds of syntax are effectively erased during MIR building, so their spans don't necessarily exist anywhere in MIR, making them invisible to the coverage instrumentor (unless we resort to various heuristics and hacks to recover them).

This PR introduces `CoverageKind::SpanMarker`, which is a new variant of `StatementKind::Coverage`. Its sole purpose is to represent spans that would otherwise not appear in MIR, so that the coverage instrumentor can extract them.

When coverage is enabled, the MIR builder can insert these dummy statements as needed, to improve the accuracy of spans used by coverage mappings.

Fixes rust-lang#115468.

---

``@rustbot`` label +A-code-coverage
workingjubilee added a commit to workingjubilee/rustc that referenced this issue Dec 9, 2023
coverage: Use `SpanMarker` to improve coverage spans for `if !` expressions

Coverage instrumentation works by extracting source code spans from MIR. However, some kinds of syntax are effectively erased during MIR building, so their spans don't necessarily exist anywhere in MIR, making them invisible to the coverage instrumentor (unless we resort to various heuristics and hacks to recover them).

This PR introduces `CoverageKind::SpanMarker`, which is a new variant of `StatementKind::Coverage`. Its sole purpose is to represent spans that would otherwise not appear in MIR, so that the coverage instrumentor can extract them.

When coverage is enabled, the MIR builder can insert these dummy statements as needed, to improve the accuracy of spans used by coverage mappings.

Fixes rust-lang#115468.

---

```@rustbot``` label +A-code-coverage
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Dec 9, 2023
Rollup merge of rust-lang#118198 - Zalathar:if-not, r=cjgillot

coverage: Use `SpanMarker` to improve coverage spans for `if !` expressions

Coverage instrumentation works by extracting source code spans from MIR. However, some kinds of syntax are effectively erased during MIR building, so their spans don't necessarily exist anywhere in MIR, making them invisible to the coverage instrumentor (unless we resort to various heuristics and hacks to recover them).

This PR introduces `CoverageKind::SpanMarker`, which is a new variant of `StatementKind::Coverage`. Its sole purpose is to represent spans that would otherwise not appear in MIR, so that the coverage instrumentor can extract them.

When coverage is enabled, the MIR builder can insert these dummy statements as needed, to improve the accuracy of spans used by coverage mappings.

Fixes rust-lang#115468.

---

```@rustbot``` label +A-code-coverage
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-code-coverage Area: Source-based code coverage (-Cinstrument-coverage) C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants