Fix tracing::instrument async block coverage - #158276
Conversation
|
Some changes occurred in coverage instrumentation. cc @Zalathar Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
|
r? @nnethercote rustbot has assigned @nnethercote. Use Why was this reviewer chosen?The reviewer was selected based on:
|
This comment has been minimized.
This comment has been minimized.
Attempt to tighten up const-eval based eligibility checks to prevent us
from discarding too many regions.
Using tracing::instrument code such as:
```rust
#[tracing::instrument]
pub async fn fetch(id: u64) -> Result<String, Error> {
let row = db_get(id).await?;
Ok(row.name)
}
```
Often results in functions with no coverage counters.
Using the following MRE:
```rust
use tracing::instrument;
pub async fn plain_async_branch(value: u8) -> &'static str {
if value.is_multiple_of(2) {
"plain even"
} else {
"plain odd"
}
}
pub fn instrumented_sync_branch(value: u8) -> &'static str {
if value.is_multiple_of(2) {
"sync even"
} else {
"sync odd"
}
}
pub async fn instrumented_async_branch(value: u8) -> &'static str {
if value.is_multiple_of(2) {
"async even"
} else {
"async odd"
}
}
mod tests {
use super::*;
#[tokio::test]
async fn plain_async_branch_reports_coverage() {
assert_eq!(plain_async_branch(2).await, "plain even");
assert_eq!(plain_async_branch(3).await, "plain odd");
}
#[test]
fn instrumented_sync_branch_reports_coverage() {
assert_eq!(instrumented_sync_branch(2), "sync even");
assert_eq!(instrumented_sync_branch(3), "sync odd");
}
#[tokio::test]
async fn instrumented_async_branch_reports_coverage() {
assert_eq!(instrumented_async_branch(2).await, "async even");
assert_eq!(instrumented_async_branch(3).await, "async odd");
}
}
```
We find that `instrumented_async_branch` is always uncovered. An
investigation lead me to `is_eligible_for_coverage` in
`rustc_mir_transform` as being the cause of filtering it out.
After that I ended up taking the very scientific approach of searching const in
https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html
and seeing the note for constness picking `is_const_fn ||
is_const_trait_impl`. (I did also try `hir_body_const_context` but that
seemed to not work for me as things that can potentially be const folded
show up?).
Now with this change I see that the region isn't marked as ineligible
but somewhere further along in processing it gets removed. This last
point is why this PR is still in it's draft state as there still seems
to be something afoot.
6ccf282 to
e741c23
Compare
|
A job failed! Check out the build log: (web) (plain enhanced) (plain) Click to see the possible cause of the failure (guessed by this bot) |
|
This is a small and simple change and it seems reasonable. But I will defer to someone who knows a lot more about this code than I do. r? @Zalathar |
|
|
| if tcx.is_const_fn(def_id) || tcx.is_const_trait_impl(def_id.to_def_id()) { | ||
| trace!("InstrumentCoverage skipped for {def_id:?} (const context eval)"); |
There was a problem hiding this comment.
Going from “selectively allow” to ”selectively reject” feels like the wrong approach here.
It's hard to be confident that this change would be correct today, and would remain correct in the future.
There was a problem hiding this comment.
Okay, so my current aim is all fn-likes that aren't in a const eval context. With a focus on giving the current place where coverage is missing. Do you have a suggestion on roughly what I should be using in TyCtx to achieve that? Or if another approach should be taken
Fixes #131119 (or tries to...)
Using tracing::instrument code such as:
Often results in functions with no coverage counters.
Using the following MRE:
We find that
instrumented_async_branchis always uncovered. An investigation lead me tois_eligible_for_coverageinrustc_mir_transformas being the cause of filtering it out.After that I ended up taking the very scientific approach of searching const in https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html and seeing the note for constness picking
is_const_fn || is_const_trait_impl. (I did also tryhir_body_const_contextbut that seemed to not work for me as things that can potentially be const folded show up?).Now with this change I see that the region isn't marked as ineligible but somewhere further along in processing it gets removed. This last point is why this PR is still in it's
draft state as there still seems to be something afootremoved draft state as I need some input or guidance 😅 .