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

Adds two source span utility functions used in source-based coverage #76003

Merged
merged 1 commit into from
Sep 1, 2020

Conversation

richkadel
Copy link
Contributor

span.is_empty() - returns true if lo() and hi() are equal. This is
not only a convenience, but makes it clear that a Span can be empty
(that is, retrieving the source for an empty Span will return an empty
string), and codifies the (otherwise undocumented--in the rustc_span
package, at least) fact that Span is a half-open interval (where
hi() is the open end).

source_map.lookup_file_span() - returns an enclosing Span
representing the start and end positions of the file enclosing the given
BytePos. This gives developers a clear way to quickly determine if any
any other BytePos or Span is also from the same file (for example,
by simply calling file_span.contains(span)).

This results in much simpler code and is much more runtime efficient
compared with the obvious alternative: calling source_map.lookup_line()
for any two Span's byte positions, handle both arms of the Result
(both contain the file), and then compare files. It is also more
efficient than the non-public method lookup_source_file_idx() for each
BytePos, because, while comparing the internal source file indexes
would be efficient, looking up the source file index for every BytePos
or Span to be compared requires a binary search (worst case
performance being O(log n) for every lookup).

source_map.lookup_file_span() performs the binary search only once, to
get the file_span result that can be used to compare to any number of
other BytePos or Span values and those comparisons are always O(1).

This PR was split out from PR #75828 .

r? @tmandry
FYI: @wesleywiser

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Aug 27, 2020
@tmandry
Copy link
Member

tmandry commented Aug 27, 2020

Looks good to me, though I'd like to run it by someone on t-compiler first.

r? @wesleywiser
cc @petrochenkov

@rust-highfive rust-highfive assigned wesleywiser and unassigned tmandry Aug 27, 2020
@richkadel richkadel force-pushed the llvm-coverage-map-gen-6b.4 branch 2 times, most recently from e68136a to 37562b0 Compare August 27, 2020 23:04
@wesleywiser
Copy link
Member

@bors r+ rollup

@bors
Copy link
Contributor

bors commented Aug 28, 2020

📌 Commit 37562b024d4a6f2662bd99e347a36ec8b041afff has been approved by wesleywiser

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Aug 28, 2020
@bors
Copy link
Contributor

bors commented Aug 30, 2020

☔ The latest upstream changes (presumably #74862) made this pull request unmergeable. Please resolve the merge conflicts.

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 30, 2020
@joshtriplett

This comment has been minimized.

@wesleywiser
Copy link
Member

@joshtriplett Can you expand on that? I'm not seeing why this would need to.

@richkadel
Copy link
Contributor Author

@wesleywiser - I rebased everything in the PR chain after the massive directory path changes that just landed. (No real changes required.)

I also don't see why a crater run would be useful, since this only adds two non-mutating methods (that no existing crates would have called) and doesn't add any data elements or anything.

Can we get these queued back up in bors (this PR and also #76002 )?

Also if you haven't already, and have time, please take a look at #76074 and #76004 ?

@joshtriplett
Copy link
Member

joshtriplett commented Aug 31, 2020

@wesleywiser @richkadel Sorry, was reviewing several PRs on mobile, and accidentally posted that comment to the wrong one. That comment was meant for #76010 .

@tmandry
Copy link
Member

tmandry commented Aug 31, 2020

@bors r+

@bors
Copy link
Contributor

bors commented Aug 31, 2020

📌 Commit 83adfebc369fd7f7ac2bbc563a04ebb72d366dcd has been approved by tmandry

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Aug 31, 2020
@wesleywiser
Copy link
Member

@bors rollup=always

`span.is_empty()` - returns true if `lo()` and `hi()` are equal. This is
not only a convenience, but makes it clear that a `Span` can be empty
(that is, retrieving the source for an empty `Span` will return an empty
string), and codifies the (otherwise undocumented--in the rustc_span
package, at least) fact that `Span` is a half-open interval (where
`hi()` is the open end).

`source_map.lookup_file_span()` - returns an enclosing `Span`
representing the start and end positions of the file enclosing the given
`BytePos`. This gives developers a clear way to quickly determine if any
any other `BytePos` or `Span` is also from the same file (for example,
by simply calling `file_span.contains(span)`).

This results in much simpler code and is much more runtime efficient
compared with the obvious alternative: calling `source_map.lookup_line()`
for any two `Span`'s byte positions, handle both arms of the `Result`
(both contain the file), and then compare files. It is also more
efficient than the non-public method `lookup_source_file_idx()` for each
`BytePos`, because, while comparing the internal source file indexes
would be efficient, looking up the source file index for every `BytePos`
or `Span` to be compared requires a binary search (worst case
performance being O(log n) for every lookup).

`source_map.lookup_file_span()` performs the binary search only once, to
get the `file_span` result that can be used to compare to any number of
other `BytePos` or `Span` values and those comparisons are always O(1).
@tmandry
Copy link
Member

tmandry commented Sep 1, 2020

@bors r=wesleywiser

@bors
Copy link
Contributor

bors commented Sep 1, 2020

📌 Commit 7225f66 has been approved by wesleywiser

bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 1, 2020
Rollup of 12 pull requests

Successful merges:

 - rust-lang#75945 (Use `env::func()`, not 'the function env::func' in docs for std::env)
 - rust-lang#76002 (Fix `-Z instrument-coverage` on MSVC)
 - rust-lang#76003 (Adds two source span utility functions used in source-based coverage)
 - rust-lang#76059 (Clean up E0764)
 - rust-lang#76103 (Clean up E0769)
 - rust-lang#76139 (Make `cow_is_borrowed` methods const)
 - rust-lang#76154 (Fix rustdoc strings indentation)
 - rust-lang#76161 (Remove notrust in rustc_middle)
 - rust-lang#76163 (README: Adjust Linux and macOS support platform and architecture)
 - rust-lang#76166 (Make `StringReader` private)
 - rust-lang#76172 (Revert rust-lang#75463)
 - rust-lang#76178 (Update expect-test to 1.0)

Failed merges:

r? @ghost
@bors bors merged commit 934127c into rust-lang:master Sep 1, 2020
bors added a commit to rust-lang-ci/rust that referenced this pull request Sep 4, 2020
… r=tmandry

Tools, tests, and experimenting with MIR-derived coverage counters

Leverages the new mir_dump output file in HTML+CSS (from rust-lang#76074) to visualize coverage code regions
and the MIR features that they came from (including overlapping spans).

See example below.

The `run-make-fulldeps/instrument-coverage` test has been refactored to maximize test coverage and reduce code duplication. The new tests support testing with and without `-Clink-dead-code`, so Rust coverage can be tested on MSVC (which, currently, only works with `link-dead-code` _disabled_).

New tests validate coverage region generation and coverage reports with multiple counters per function. Starting with a simple `if-else` branch tests, coverage tests for each additional syntax type can be added by simply dropping in a new Rust sample program.

Includes a basic, MIR-block-based implementation of coverage injection,
available via `-Zexperimental-coverage`. This implementation has known
flaws and omissions, but is simple enough to validate the new tools and
tests.

The existing `-Zinstrument-coverage` option currently enables
function-level coverage only, which at least appears to generate
accurate coverage reports at that level.

Experimental coverage is not accurate at this time. When branch coverage
works as intended, the `-Zexperimental-coverage` option should be
removed.

This PR replaces the bulk of PR rust-lang#75828, with the remaining parts of
that PR distributed among other separate and indentpent PRs.

This PR depends on two of those other PRs: rust-lang#76002, rust-lang#76003 and rust-lang#76074

Rust compiler MCP rust-lang/compiler-team#278

Relevant issue: rust-lang#34701 - Implement support for LLVMs code coverage
instrumentation

![Screen-Recording-2020-08-21-at-2](https://user-images.githubusercontent.com/3827298/90972923-ff417880-e4d1-11ea-92bb-8713c6198f6d.gif)

r? @tmandry
FYI: @wesleywiser
@cuviper cuviper added this to the 1.48.0 milestone Nov 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants