about summary refs log tree commit diff
path: root/compiler/rustc_mir/src/transform/coverage/mod.rs
AgeCommit message (Collapse)AuthorLines
2021-09-07Move rustc_mir::transform to rustc_mir_transform.Camille GILLOT-588/+0
2021-08-22Fix typos “a”→“an”Frank Steffahn-1/+1
2021-08-18Remove box syntax from rustc_mirest31-3/+3
2021-05-12`coverageinfo` query needs to use the same MIR as codegenRich Kadel-11/+1
I ran into an error trying to fix dead block coverage and realized the `coverageinfo` query is getting a different MIR compared to the codegenned MIR, which can sometimes be a problem during mapgen. I changed that query to use the `InstandeDef` (which includes the generic parameter substitutions, prosibly specific to const params) instead of the `DefId` (without unknown/default const substitutions).
2021-05-12Simplified body_span and filtered span codeRich Kadel-21/+43
Some code cleanup extracted from future (but unfinished) commit to fix coverage in attr macro functions.
2021-05-12Spanview needs the relevant body_span used for coverageRich Kadel-0/+1
The coverage body_span doesn't always match the function body_span.
2021-05-12Auto merge of #83813 - cbeuw:remap-std, r=michaelwoeristerbors-5/+5
Fix `--remap-path-prefix` not correctly remapping `rust-src` component paths and unify handling of path mapping with virtualized paths This PR fixes #73167 ("Binaries end up containing path to the rust-src component despite `--remap-path-prefix`") by preventing real local filesystem paths from reaching compilation output if the path is supposed to be remapped. `RealFileName::Named` introduced in #72767 is now renamed as `LocalPath`, because this variant wraps a (most likely) valid local filesystem path. `RealFileName::Devirtualized` is renamed as `Remapped` to be used for remapped path from a real path via `--remap-path-prefix` argument, as well as real path inferred from a virtualized (during compiler bootstrapping) `/rustc/...` path. The `local_path` field is now an `Option<PathBuf>`, as it will be set to `None` before serialisation, so it never reaches any build output. Attempting to serialise a non-`None` `local_path` will cause an assertion faliure. When a path is remapped, a `RealFileName::Remapped` variant is created. The original path is preserved in `local_path` field and the remapped path is saved in `virtual_name` field. Previously, the `local_path` is directly modified which goes against its purpose of "suitable for reading from the file system on the local host". `rustc_span::SourceFile`'s fields `unmapped_path` (introduced by #44940) and `name_was_remapped` (introduced by #41508 when `--remap-path-prefix` feature originally added) are removed, as these two pieces of information can be inferred from the `name` field: if it's anything other than a `FileName::Real(_)`, or if it is a `FileName::Real(RealFileName::LocalPath(_))`, then clearly `name_was_remapped` would've been false and `unmapped_path` would've been `None`. If it is a `FileName::Real(RealFileName::Remapped{local_path, virtual_name})`, then `name_was_remapped` would've been true and `unmapped_path` would've been `Some(local_path)`. cc `@eddyb` who implemented `/rustc/...` path devirtualisation
2021-05-12Implement span quoting for proc-macrosAaron Hill-1/+1
This PR implements span quoting, allowing proc-macros to produce spans pointing *into their own crate*. This is used by the unstable `proc_macro::quote!` macro, allowing us to get error messages like this: ``` error[E0412]: cannot find type `MissingType` in this scope --> $DIR/auxiliary/span-from-proc-macro.rs:37:20 | LL | pub fn error_from_attribute(_args: TokenStream, _input: TokenStream) -> TokenStream { | ----------------------------------------------------------------------------------- in this expansion of procedural macro `#[error_from_attribute]` ... LL | field: MissingType | ^^^^^^^^^^^ not found in this scope | ::: $DIR/span-from-proc-macro.rs:8:1 | LL | #[error_from_attribute] | ----------------------- in this macro invocation ``` Here, `MissingType` occurs inside the implementation of the proc-macro `#[error_from_attribute]`. Previosuly, this would always result in a span pointing at `#[error_from_attribute]` This will make many proc-macro-related error message much more useful - when a proc-macro generates code containing an error, users will get an error message pointing directly at that code (within the macro definition), instead of always getting a span pointing at the macro invocation site. This is implemented as follows: * When a proc-macro crate is being *compiled*, it causes the `quote!` macro to get run. This saves all of the sapns in the input to `quote!` into the metadata of *the proc-macro-crate* (which we are currently compiling). The `quote!` macro then expands to a call to `proc_macro::Span::recover_proc_macro_span(id)`, where `id` is an opaque identifier for the span in the crate metadata. * When the same proc-macro crate is *run* (e.g. it is loaded from disk and invoked by some consumer crate), the call to `proc_macro::Span::recover_proc_macro_span` causes us to load the span from the proc-macro crate's metadata. The proc-macro then produces a `TokenStream` containing a `Span` pointing into the proc-macro crate itself. The recursive nature of 'quote!' can be difficult to understand at first. The file `src/test/ui/proc-macro/quote-debug.stdout` shows the output of the `quote!` macro, which should make this eaier to understand. This PR also supports custom quoting spans in custom quote macros (e.g. the `quote` crate). All span quoting goes through the `proc_macro::quote_span` method, which can be called by a custom quote macro to perform span quoting. An example of this usage is provided in `src/test/ui/proc-macro/auxiliary/custom-quote.rs` Custom quoting currently has a few limitations: In order to quote a span, we need to generate a call to `proc_macro::Span::recover_proc_macro_span`. However, proc-macros support renaming the `proc_macro` crate, so we can't simply hardcode this path. Previously, the `quote_span` method used the path `crate::Span` - however, this only works when it is called by the builtin `quote!` macro in the same crate. To support being called from arbitrary crates, we need access to the name of the `proc_macro` crate to generate a path. This PR adds an additional argument to `quote_span` to specify the name of the `proc_macro` crate. Howver, this feels kind of hacky, and we may want to change this before stabilizing anything quote-related. Additionally, using `quote_span` currently requires enabling the `proc_macro_internals` feature. The builtin `quote!` macro has an `#[allow_internal_unstable]` attribute, but this won't work for custom quote implementations. This will likely require some additional tricks to apply `allow_internal_unstable` to the span of `proc_macro::Span::recover_proc_macro_span`.
2021-05-11Split span_to_string into span_to_diagnostic/embeddable_stringAndy Wang-4/+4
2021-05-06Coverage instruments closure bodies in macros (not the macro body)Rich Kadel-3/+24
Fixes: #84884 This solution might be considered a compromise, but I think it is the better choice. The results in the `closure.rs` test correctly resolve all test cases broken as described in #84884. One test pattern (in both `closure_macro.rs` and `closure_macro_async.rs`) was also affected, and removes coverage statistics for the lines inside the closure, because the closure includes a macro. (The coverage remains at the callsite of the macro, so we lose some detail, but there isn't a perfect choice with macros. Often macro implementations are split across the macro and the callsite, and there doesn't appear to be a single "right choice" for which body should be covered. For the current implementation, we can't do both. The callsite is most likely to be the preferred site for coverage. I applied this fix to all `MacroKinds`, not just `Bang`. I'm trying to resolve an issue of lost coverage in a `MacroKind::Attr`-based, function-scoped macro. Instead of only searching for a body_span that is "not a function-like macro" (that is, MacroKind::Bang), I'm expanding this to all `MacroKind`s. Maybe I should expand this to `ExpnKind::Desugaring` and `ExpnKind::AstPass` (or subsets, depending on their sub-kinds) as well, but I'm not sure that's a good idea. I'd like to add a test of the `Attr` macro on functions, but I need time to figure out how to constract a good, simple example without external crate dependencies. For the moment, all tests still work as expected (no change), this new commit shouldn't have a negative affect, and more importantly, I believe it will have a positive effect. I will try to confirm this.
2021-05-05Use local and remapped paths where appropriateAndy Wang-1/+1
2021-04-27Derived Eq no longer shows uncoveredRich Kadel-0/+6
The Eq trait has a special hidden function. MIR `InstrumentCoverage` would add this function to the coverage map, but it is never called, so the `Eq` trait would always appear uncovered. Fixes: #83601 The fix required creating a new function attribute `no_coverage` to mark functions that should be ignored by `InstrumentCoverage` and the coverage `mapgen` (during codegen). While testing, I also noticed two other issues: * spanview debug file output ICEd on a function with no body. The workaround for this is included in this PR. * `assert_*!()` macro coverage can appear covered if followed by another `assert_*!()` macro. Normally they appear uncovered. I submitted a new Issue #84561, and added a coverage test to demonstrate this issue.
2021-04-24Fix coverage ICE because fn_sig can have a span that crosses file boundariesRich Kadel-1/+1
Fixes: #83792 MIR `InstrumentCoverage` assumed the `FnSig` span was contained within a single file, but this is not always the case. Some macro constructions can result in a span that starts in one `SourceFile` and ends in a different one. The `FnSig` span is included in coverage results as long as that span is in the same `SourceFile` and the same macro context, but by assuming the `FnSig` span's `hi()` and `lo()` were in the same file, I took this for granted, and checked only that the `FnSig` `hi()` was in the same `SourceFile` as the `body_span`. I actually drop the `hi()` though, and extend the `FnSig` span to the `body_span.lo()`, so I really should have simply checked that the `FnSig` span's `lo()` was in the `SourceFile` of the `body_span`.
2021-04-22Fix ICE if original_span(fn_sig) returns a span not in body sourcefileRich Kadel-1/+2
Fixes: #84421
2020-12-19Remap instrument-coverage line numbers in doctestsArpad Borsos-1/+5
This uses the `SourceMap::doctest_offset_line` method to re-map line numbers from doctests. Remapping columns is not yet done. Part of issue #79417.
2020-12-15Fixed conflict with drop elaboration and coverageRich Kadel-2/+2
See https://github.com/rust-lang/rust/issues/80045#issuecomment-745733339 Coverage statements are moved to the beginning of the BCB. This does also affect what's counted before a panic, changing some results, but I think these results may even be preferred? In any case, there are no guarantees about what's counted when a panic occurs (by design).
2020-12-11Fixes reported bugs in Rust CoverageRich Kadel-0/+8
Fixes: #79569 Fixes: #79566 Fixes: #79565 For the first issue (#79569), I got hit a `debug_assert!()` before encountering the reported error message (because I have `debug = true` enabled in my config.toml). The assertion showed me that some `SwitchInt`s can have more than one target pointing to the same `BasicBlock`. I had thought that was invalid, but since it seems to be possible, I'm allowing this now. I added a new test for this. ---- In the last two cases above, both tests (intentionally) fail to compile, but the `InstrumentCoverage` pass is invoked anyway. The MIR starts with an `Unreachable` `BasicBlock`, which I hadn't encountered before. (I had assumed the `InstrumentCoverage` pass would only be invoked with MIRs from successful compilations.) I don't have test infrastructure set up to test coverage on files that fail to compile, so I didn't add a new test.
2020-12-07Fixes to Rust coverageRich Kadel-4/+18
Fixes: #79725 Some macros can create a situation where `fn_sig_span` and `body_span` map to different files. New documentation on coverage tests incorrectly assumed multiple test binaries could just be listed at the end of the `llvm-cov` command, but it turns out each binary needs a `--object` prefix. This PR fixes the bug and updates the documentation to correct that issue. It also fixes a few other minor issues in internal implementation comments, and adds documentation on getting coverage results for doc tests.
2020-12-03Addressed feedback from 2020-12-01Rich Kadel-0/+2
Added one more test (two files) showing coverage of generics and unused functions across crates. Created and referenced new Issues, as requested. Added comments. Added a note about the possible effects of compiler options on LLVM coverage maps.
2020-12-03Combination of commitsRich Kadel-49/+26
Fixes multiple issue with counters, with simplification Includes a change to the implicit else span in ast_lowering, so coverage of the implicit else no longer spans the `then` block. Adds coverage for unused closures and async function bodies. Fixes: #78542 Adding unreachable regions for known MIR missing from coverage map Cleaned up PR commits, and removed link-dead-code requirement and tests Coverage no longer depends on Issue #76038 (`-C link-dead-code` is no longer needed or enforced, so MSVC can use the same tests as Linux and MacOS now) Restrict adding unreachable regions to covered files Improved the code that adds coverage for uncalled functions (with MIR but not-codegenned) to avoid generating coverage in files not already included in the files with covered functions. Resolved last known issue requiring --emit llvm-ir workaround Fixed bugs in how unreachable code spans were added.
2020-11-13Addressed feedbackRich Kadel-1/+1
2020-11-11Added some unit tests as requestedRich Kadel-1/+4
As discussed in PR #78267, for example: * https://github.com/rust-lang/rust/pull/78267#discussion_r515404722 * https://github.com/rust-lang/rust/pull/78267#discussion_r515405958
2020-11-05Responded to all feedback as of 2020-10-30Rich Kadel-5/+15
2020-11-05Injecting expressions in place of counters where helpfulRich Kadel-34/+289
Implementing the Graph traits for the BasicCoverageBlock graph. optimized replacement of counters with expressions plus new BCB graphviz * Avoid adding coverage to unreachable blocks. * Special case for Goto at the end of the body. Make it non-reportable. Improved debugging and formatting options (from env) Don't automatically add counters to BCBs without CoverageSpans. They may still get counters but only if there are dependencies from other BCBs that have spans, I think. Make CodeRegions optional for Counters too. It is possible to inject counters (`llvm.instrprof.increment` intrinsic calls without corresponding code regions in the coverage map. An expression can still uses these counter values. Refactored instrument_coverage.rs -> instrument_coverage/mod.rs, and then broke up the mod into multiple files. Compiling with coverage, with the expression optimization, works on the json5format crate and its dependencies. Refactored debug features from mod.rs to debug.rs
2020-11-05Adds coverage graphvizRich Kadel-3/+31
2020-11-05Implemented CoverageGraph of BasicCoverageBlocksRich Kadel-8/+13
2020-11-05Splitting transform/instrument_coverage.rs into transform/coverage/...Rich Kadel-0/+241