Skip to content

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

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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
Collaborator

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
Collaborator

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 richkadel force-pushed the llvm-coverage-map-gen-6b.4 branch from 37562b0 to 83adfeb Compare August 30, 2020 21:32
@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
Collaborator

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).
@richkadel richkadel force-pushed the llvm-coverage-map-gen-6b.4 branch from 83adfeb to 7225f66 Compare September 1, 2020 01:42
@tmandry
Copy link
Member

tmandry commented Sep 1, 2020

@bors r=wesleywiser

@bors
Copy link
Collaborator

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
# for free to join this conversation on GitHub. Already have an account? # 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