-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Generating the coverage map #74091
Generating the coverage map #74091
Conversation
79b365d
to
9c4930b
Compare
@tmandry @wesleywiser - I did my own detailed review of the output and tests and made a few important, small improvements to this PR. I don't expect to make any more changes until I get feedback. Thanks! |
9c4930b
to
a0b3457
Compare
I noticed a mistake in the FYI, I also made a temporary change to Thanks! |
Sorry for the delay, it's been a busy few days for me. I'm starting the review so let's go ahead and do @bors try |
⌛ Trying commit 08b006f81ef8377ae1b121f3dfbef22e141f5201 with merge 31e6847482c04e9b90e2b2a8abf75c59af671f5f... |
@wesleywiser @tmandry - FYI, until now, I have only tested on very small, simple programs. Just today I started trying I propose landing the current version--with review comments resolved, but otherwise, as-is--since we already recognize this is not "complete" yet. But (your call), if you prefer, I can make more changes to this PR to get the function-level coverage working on more complex crates. Just so you know, here are two problems I've found so far, when attempting to build the json5format crate:
And just so you are aware, I know the CounterExpression indexes are wrong, but this is by design. The indexes for CounterExpressions need to be recomputed (which also affects the expression operands themselves). This should be a very simple translation, and I know how I plan to do this, but I want to validate the solution before checking it in, but I don't (yet) produce any actual Counter Expressions expressions to validate against. |
Oh, and if I do land this PR "as-is", my next PR would resolve the known issues with larger crates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎉
cc @petrhosek who I think would be interested in taking a look.
src/test/run-make-fulldeps/instrument-coverage/expected_coverage_summary.json
Outdated
Show resolved
Hide resolved
Yeah, computing the hash on HIR will fail when codegenning functions from another crate (either We'll have to find another way to compute a somewhat-stable hash, or include it in crate metadata. In terms of whether to do it now, it seems like an issue from a past PR and this is an experimental feature, so I'd say it's okay to leave as-is and fix in a follow up PR. |
💔 Test failed - checks-azure |
Good thing we "try"d ! MacOS and Windows both failed, but earlier than I expected. I'll need to resolve these issues and we'll need to "try" again I think. |
In that case, I should be able to work around that limitation by adding the hash to the Rust coverage intrinsics injected into the MIR.
SGTM, if ok with Wesley too. Thanks! |
src/ci/azure-pipelines/try.yml
Outdated
@@ -80,3 +80,36 @@ jobs: | |||
# INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-extended --enable-profiler | |||
# SCRIPT: python x.py dist | |||
# DEPLOY_ALT: 1 | |||
|
|||
# TEMPORARILY ENABLE MAC AND WINDOWS TESTS ON BORS TRY. | |||
# FIXME(richkadel): remove this before merging the PR |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Noting this so we don't forget it.
src/test/run-make-fulldeps/instrument-coverage/expected_coverage_summary.json
Outdated
Show resolved
Hide resolved
pub fn coverage_loc(&self, source_map: &SourceMap) -> CoverageLoc { | ||
let (file, start_line, start_col) = | ||
lookup_file_line_col(source_map, BytePos::from_u32(self.coverage_span.start_byte_pos)); | ||
let (_, end_line, end_col) = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe assert!()
or debug_assert!()
that these files are the same?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@wesleywiser Yes, thanks! So I added this check, and surprisingly saw some cases (during ad hoc testing) where the assert failed. I was getting different filenames for the start and end of the byte_pos range!
But I've also seen some coverage results that show source ranges inside comments (not rustdoc code comments), so something is off sometimes.
It's almost surprising that a lot of things work correctly. So I still need to do more investigation.
For now, to avoid crashing, I changed this function to return an Option. Coverage mappings that have this problem get None
from coverage_loc()
, and I just skip them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@richkadel I wonder if any of those are related to macros? If you look at the MIR for a simple hello world (playground), you can see that some of the spans come from the playground file (src/lib.rs
) while many of the others come from the expansion of the println!()
macro and point into the std library (/rustc/{git commit}/src/libstd/macros.rs
).
That seems fine to me as well. There's no expectation that unstable features are fully implemented or bug-free during development. |
dccafde
to
c379fc8
Compare
@wesleywiser @tmandry - Assuming the PR build succeeds, can we start another I think the error on Windows is resolved. I'm confused by the MacOS error, but with other changes made, I'd like to test it again. Thanks! |
FYI, the normal PR build is failing with:
I did add a new tool, |
c379fc8
to
8926430
Compare
Never mind! This is resolved. |
@wesleywiser @tmandry - I think I've addressed all of your comments with the latest changes. I'm going to go back through them though and reply or resolve. Note that when I started working on your feedback last week, I already anticipated some restructuring. Instead of submitting changes just to resolve the feedback alone, I incorporated your feedback into the restructured code. So there are some more differences from what you reviewed last time, but all feedback was taken into account. I was able to generate coverage on the entire I also implemented support for name demangling, so Here's an example from the revised test: |
As previously discussed, I resolved this by adding the function source hash to the |
Looks spurious: Details
|
@bors retry |
⌛ Testing commit a6f8b8a with merge 28487bc5bc0433159b337420f8f7f1a7b3571703... |
💥 Test timed out |
Ugh. I checked the Pipeline UI just a couple of minutes before this timeout, and it was still going strong, just slow to complete the remaining tests on Windows. It was chugging along on test/ui at the time. Timing out like this after 4 hours without an actual problem was a waste of resources. Any way to extend the timeout? |
Actually, it looks like the build was proactively cancelled by someone. I agree the job was taking exceptionally long, but I assume it is due to an infrastructure issue, not the PR. Sad to see it get that far without getting the chance to complete. @wesleywiser @tmandry - Any reason to think that the PR has a problem? (It did complete the If not, can we queue it up again? Thanks |
Intermittent timeouts are relatively common so it's probably just that. I'm not at a computer to verify but we can give it another try on the assumption that's the issue. @bors rety |
@bors retry |
Thanks @wesleywiser ! |
☀️ Test successful - checks-actions, checks-azure |
This is absolutely fantastic—huge thank you @richkadel, and everyone who's worked on this so far. One thing that I've noticed on a large library crate, when building the test harness with |
@eggyal could you make sure LTO is not enabled? |
@mati865 It's not. Have been investigating since my previous comment and it appears to be due to generics/monomorphisation. For example: pub struct Foo<T>(T);
impl<T> Foo<T> {
pub fn foo(&self) {
// coverage exists (although regions look a bit buggy to me?)
}
pub fn bar(&self) {
// no coverage
}
}
#[cfg(test)]
mod tests {
#[test]
fn test() {
let foo = super::Foo(());
foo.foo();
}
} I guess |
@eggyal Thanks for the repro! This feature is still very much "in progress" so lots of stuff doesn't work correctly. Even still, I think it would be helpful to open bug reports as you find things so that we can track what issues have been resolved and which are still open. |
Yes, I believe that's true. Generics are still just source templates, and don't actually become executable code until instantiated, when used. So the |
You probably meant to cc @eggyal |
@tmandry @wesleywiser
rustc now generates the coverage map and can support (limited)
coverage report generation, at the function level.
Example commands to generate a coverage report:
r? @wesleywiser
Rust compiler MCP rust-lang/compiler-team#278
Relevant issue: #34701 - Implement support for LLVMs code coverage instrumentation