2024-06-16 01:11:32 +10:00
|
|
|
use std::collections::VecDeque;
|
|
|
|
|
|
|
|
|
|
use rustc_data_structures::fx::FxHashSet;
|
2023-10-17 21:22:02 +11:00
|
|
|
use rustc_middle::mir;
|
2024-09-06 10:25:25 +12:00
|
|
|
use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span};
|
2024-08-28 15:03:14 +10:00
|
|
|
use tracing::{debug, debug_span, instrument};
|
Updates to experimental coverage counter injection
This is a combination of 18 commits.
Commit #2:
Additional examples and some small improvements.
Commit #3:
fixed mir-opt non-mir extensions and spanview title elements
Corrected a fairly recent assumption in runtest.rs that all MIR dump
files end in .mir. (It was appending .mir to the graphviz .dot and
spanview .html file names when generating blessed output files. That
also left outdated files in the baseline alongside the files with the
incorrect names, which I've now removed.)
Updated spanview HTML title elements to match their content, replacing a
hardcoded and incorrect name that was left in accidentally when
originally submitted.
Commit #4:
added more test examples
also improved Makefiles with support for non-zero exit status and to
force validation of tests unless a specific test overrides it with a
specific comment.
Commit #5:
Fixed rare issues after testing on real-world crate
Commit #6:
Addressed PR feedback, and removed temporary -Zexperimental-coverage
-Zinstrument-coverage once again supports the latest capabilities of
LLVM instrprof coverage instrumentation.
Also fixed a bug in spanview.
Commit #7:
Fix closure handling, add tests for closures and inner items
And cleaned up other tests for consistency, and to make it more clear
where spans start/end by breaking up lines.
Commit #8:
renamed "typical" test results "expected"
Now that the `llvm-cov show` tests are improved to normally expect
matching actuals, and to allow individual tests to override that
expectation.
Commit #9:
test coverage of inline generic struct function
Commit #10:
Addressed review feedback
* Removed unnecessary Unreachable filter.
* Replaced a match wildcard with remining variants.
* Added more comments to help clarify the role of successors() in the
CFG traversal
Commit #11:
refactoring based on feedback
* refactored `fn coverage_spans()`.
* changed the way I expand an empty coverage span to improve performance
* fixed a typo that I had accidently left in, in visit.rs
Commit #12:
Optimized use of SourceMap and SourceFile
Commit #13:
Fixed a regression, and synched with upstream
Some generated test file names changed due to some new change upstream.
Commit #14:
Stripping out crate disambiguators from demangled names
These can vary depending on the test platform.
Commit #15:
Ignore llvm-cov show diff on test with generics, expand IO error message
Tests with generics produce llvm-cov show results with demangled names
that can include an unstable "crate disambiguator" (hex value). The
value changes when run in the Rust CI Windows environment. I added a sed
filter to strip them out (in a prior commit), but sed also appears to
fail in the same environment. Until I can figure out a workaround, I'm
just going to ignore this specific test result. I added a FIXME to
follow up later, but it's not that critical.
I also saw an error with Windows GNU, but the IO error did not
specify a path for the directory or file that triggered the error. I
updated the error messages to provide more info for next, time but also
noticed some other tests with similar steps did not fail. Looks
spurious.
Commit #16:
Modify rust-demangler to strip disambiguators by default
Commit #17:
Remove std::process::exit from coverage tests
Due to Issue #77553, programs that call std::process::exit() do not
generate coverage results on Windows MSVC.
Commit #18:
fix: test file paths exceeding Windows max path len
2020-09-01 16:15:17 -07:00
|
|
|
|
2024-04-29 22:25:09 +10:00
|
|
|
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
|
2024-06-16 01:11:32 +10:00
|
|
|
use crate::coverage::spans::from_mir::{
|
2024-07-01 13:29:54 +10:00
|
|
|
ExtractedCovspans, Hole, SpanFromMir, extract_covspans_from_mir,
|
2024-06-16 01:11:32 +10:00
|
|
|
};
|
2023-12-19 21:50:13 +11:00
|
|
|
use crate::coverage::{ExtractedHirInfo, mappings};
|
2023-10-01 20:57:32 +11:00
|
|
|
|
|
|
|
|
mod from_mir;
|
Updates to experimental coverage counter injection
This is a combination of 18 commits.
Commit #2:
Additional examples and some small improvements.
Commit #3:
fixed mir-opt non-mir extensions and spanview title elements
Corrected a fairly recent assumption in runtest.rs that all MIR dump
files end in .mir. (It was appending .mir to the graphviz .dot and
spanview .html file names when generating blessed output files. That
also left outdated files in the baseline alongside the files with the
incorrect names, which I've now removed.)
Updated spanview HTML title elements to match their content, replacing a
hardcoded and incorrect name that was left in accidentally when
originally submitted.
Commit #4:
added more test examples
also improved Makefiles with support for non-zero exit status and to
force validation of tests unless a specific test overrides it with a
specific comment.
Commit #5:
Fixed rare issues after testing on real-world crate
Commit #6:
Addressed PR feedback, and removed temporary -Zexperimental-coverage
-Zinstrument-coverage once again supports the latest capabilities of
LLVM instrprof coverage instrumentation.
Also fixed a bug in spanview.
Commit #7:
Fix closure handling, add tests for closures and inner items
And cleaned up other tests for consistency, and to make it more clear
where spans start/end by breaking up lines.
Commit #8:
renamed "typical" test results "expected"
Now that the `llvm-cov show` tests are improved to normally expect
matching actuals, and to allow individual tests to override that
expectation.
Commit #9:
test coverage of inline generic struct function
Commit #10:
Addressed review feedback
* Removed unnecessary Unreachable filter.
* Replaced a match wildcard with remining variants.
* Added more comments to help clarify the role of successors() in the
CFG traversal
Commit #11:
refactoring based on feedback
* refactored `fn coverage_spans()`.
* changed the way I expand an empty coverage span to improve performance
* fixed a typo that I had accidently left in, in visit.rs
Commit #12:
Optimized use of SourceMap and SourceFile
Commit #13:
Fixed a regression, and synched with upstream
Some generated test file names changed due to some new change upstream.
Commit #14:
Stripping out crate disambiguators from demangled names
These can vary depending on the test platform.
Commit #15:
Ignore llvm-cov show diff on test with generics, expand IO error message
Tests with generics produce llvm-cov show results with demangled names
that can include an unstable "crate disambiguator" (hex value). The
value changes when run in the Rust CI Windows environment. I added a sed
filter to strip them out (in a prior commit), but sed also appears to
fail in the same environment. Until I can figure out a workaround, I'm
just going to ignore this specific test result. I added a FIXME to
follow up later, but it's not that critical.
I also saw an error with Windows GNU, but the IO error did not
specify a path for the directory or file that triggered the error. I
updated the error messages to provide more info for next, time but also
noticed some other tests with similar steps did not fail. Looks
spurious.
Commit #16:
Modify rust-demangler to strip disambiguators by default
Commit #17:
Remove std::process::exit from coverage tests
Due to Issue #77553, programs that call std::process::exit() do not
generate coverage results on Windows MSVC.
Commit #18:
fix: test file paths exceeding Windows max path len
2020-09-01 16:15:17 -07:00
|
|
|
|
2024-04-29 22:25:09 +10:00
|
|
|
pub(super) fn extract_refined_covspans(
|
|
|
|
|
mir_body: &mir::Body<'_>,
|
|
|
|
|
hir_info: &ExtractedHirInfo,
|
2024-12-18 13:53:23 +11:00
|
|
|
graph: &CoverageGraph,
|
2024-05-02 14:18:22 +10:00
|
|
|
code_mappings: &mut impl Extend<mappings::CodeMapping>,
|
2024-04-29 22:25:09 +10:00
|
|
|
) {
|
2024-12-18 13:53:23 +11:00
|
|
|
let ExtractedCovspans { mut covspans } = extract_covspans_from_mir(mir_body, hir_info, graph);
|
2024-06-16 01:11:32 +10:00
|
|
|
|
2024-06-16 01:25:05 +10:00
|
|
|
// First, perform the passes that need macro information.
|
2024-12-18 13:53:23 +11:00
|
|
|
covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb));
|
2024-09-06 10:25:25 +12:00
|
|
|
remove_unwanted_expansion_spans(&mut covspans);
|
2024-06-16 01:11:32 +10:00
|
|
|
split_visible_macro_spans(&mut covspans);
|
|
|
|
|
|
2024-06-16 01:25:05 +10:00
|
|
|
// We no longer need the extra information in `SpanFromMir`, so convert to `Covspan`.
|
|
|
|
|
let mut covspans = covspans.into_iter().map(SpanFromMir::into_covspan).collect::<Vec<_>>();
|
|
|
|
|
|
|
|
|
|
let compare_covspans = |a: &Covspan, b: &Covspan| {
|
2024-06-16 01:11:32 +10:00
|
|
|
compare_spans(a.span, b.span)
|
|
|
|
|
// After deduplication, we want to keep only the most-dominated BCB.
|
2024-12-18 13:53:23 +11:00
|
|
|
.then_with(|| graph.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
|
2024-06-16 01:11:32 +10:00
|
|
|
};
|
|
|
|
|
covspans.sort_by(compare_covspans);
|
|
|
|
|
|
|
|
|
|
// Among covspans with the same span, keep only one,
|
|
|
|
|
// preferring the one with the most-dominated BCB.
|
|
|
|
|
// (Ideally we should try to preserve _all_ non-dominating BCBs, but that
|
|
|
|
|
// requires a lot more complexity in the span refiner, for little benefit.)
|
|
|
|
|
covspans.dedup_by(|b, a| a.span.source_equal(b.span));
|
|
|
|
|
|
|
|
|
|
// Sort the holes, and merge overlapping/adjacent holes.
|
2024-07-01 13:29:54 +10:00
|
|
|
let mut holes = hir_info.hole_spans.iter().map(|&span| Hole { span }).collect::<Vec<_>>();
|
2024-06-16 01:11:32 +10:00
|
|
|
holes.sort_by(|a, b| compare_spans(a.span, b.span));
|
|
|
|
|
holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
|
|
|
|
|
|
2024-06-16 01:28:22 +10:00
|
|
|
// Split the covspans into separate buckets that don't overlap any holes.
|
|
|
|
|
let buckets = divide_spans_into_buckets(covspans, &holes);
|
2024-06-16 01:11:32 +10:00
|
|
|
|
|
|
|
|
for mut covspans in buckets {
|
|
|
|
|
// Make sure each individual bucket is internally sorted.
|
|
|
|
|
covspans.sort_by(compare_covspans);
|
2024-06-15 23:39:04 +10:00
|
|
|
let _span = debug_span!("processing bucket", ?covspans).entered();
|
|
|
|
|
|
|
|
|
|
let mut covspans = remove_unwanted_overlapping_spans(covspans);
|
|
|
|
|
debug!(?covspans, "after removing overlaps");
|
|
|
|
|
|
|
|
|
|
// Do one last merge pass, to simplify the output.
|
|
|
|
|
covspans.dedup_by(|b, a| a.merge_if_eligible(b));
|
|
|
|
|
debug!(?covspans, "after merge");
|
2024-06-16 01:11:32 +10:00
|
|
|
|
2024-06-16 01:25:05 +10:00
|
|
|
code_mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }| {
|
2024-06-03 15:27:30 +10:00
|
|
|
// Each span produced by the refiner represents an ordinary code region.
|
|
|
|
|
mappings::CodeMapping { span, bcb }
|
|
|
|
|
}));
|
|
|
|
|
}
|
2024-04-29 22:25:09 +10:00
|
|
|
}
|
|
|
|
|
|
2024-06-16 01:11:32 +10:00
|
|
|
/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate
|
|
|
|
|
/// multiple condition/consequent blocks that have the span of the whole macro
|
|
|
|
|
/// invocation, which is unhelpful. Keeping only the first such span seems to
|
|
|
|
|
/// give better mappings, so remove the others.
|
|
|
|
|
///
|
2024-09-06 10:25:25 +12:00
|
|
|
/// Similarly, `await` expands to a branch on the discriminant of `Poll`, which
|
|
|
|
|
/// leads to incorrect coverage if the `Future` is immediately ready (#98712).
|
|
|
|
|
///
|
2024-06-16 01:11:32 +10:00
|
|
|
/// (The input spans should be sorted in BCB dominator order, so that the
|
|
|
|
|
/// retained "first" span is likely to dominate the others.)
|
2024-09-06 10:25:25 +12:00
|
|
|
fn remove_unwanted_expansion_spans(covspans: &mut Vec<SpanFromMir>) {
|
|
|
|
|
let mut deduplicated_spans = FxHashSet::default();
|
|
|
|
|
|
2024-06-16 01:11:32 +10:00
|
|
|
covspans.retain(|covspan| {
|
2024-09-06 10:25:25 +12:00
|
|
|
match covspan.expn_kind {
|
|
|
|
|
// Retain only the first await-related or macro-expanded covspan with this span.
|
2024-10-12 11:52:30 +02:00
|
|
|
Some(ExpnKind::Desugaring(DesugaringKind::Await)) => {
|
2024-09-06 10:25:25 +12:00
|
|
|
deduplicated_spans.insert(covspan.span)
|
|
|
|
|
}
|
|
|
|
|
Some(ExpnKind::Macro(MacroKind::Bang, _)) => deduplicated_spans.insert(covspan.span),
|
|
|
|
|
// Ignore (retain) other spans.
|
|
|
|
|
_ => true,
|
2024-06-16 01:11:32 +10:00
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// When a span corresponds to a macro invocation that is visible from the
|
|
|
|
|
/// function body, split it into two parts. The first part covers just the
|
|
|
|
|
/// macro name plus `!`, and the second part covers the rest of the macro
|
|
|
|
|
/// invocation. This seems to give better results for code that uses macros.
|
|
|
|
|
fn split_visible_macro_spans(covspans: &mut Vec<SpanFromMir>) {
|
|
|
|
|
let mut extra_spans = vec![];
|
|
|
|
|
|
|
|
|
|
covspans.retain(|covspan| {
|
2024-09-06 10:25:25 +12:00
|
|
|
let Some(ExpnKind::Macro(MacroKind::Bang, visible_macro)) = covspan.expn_kind else {
|
|
|
|
|
return true;
|
|
|
|
|
};
|
2024-06-16 01:11:32 +10:00
|
|
|
|
|
|
|
|
let split_len = visible_macro.as_str().len() as u32 + 1;
|
|
|
|
|
let (before, after) = covspan.span.split_at(split_len);
|
|
|
|
|
if !covspan.span.contains(before) || !covspan.span.contains(after) {
|
|
|
|
|
// Something is unexpectedly wrong with the split point.
|
|
|
|
|
// The debug assertion in `split_at` will have already caught this,
|
|
|
|
|
// but in release builds it's safer to do nothing and maybe get a
|
|
|
|
|
// bug report for unexpected coverage, rather than risk an ICE.
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2024-09-06 10:25:25 +12:00
|
|
|
extra_spans.push(SpanFromMir::new(before, covspan.expn_kind.clone(), covspan.bcb));
|
|
|
|
|
extra_spans.push(SpanFromMir::new(after, covspan.expn_kind.clone(), covspan.bcb));
|
2024-06-16 01:11:32 +10:00
|
|
|
false // Discard the original covspan that we just split.
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// The newly-split spans are added at the end, so any previous sorting
|
|
|
|
|
// is not preserved.
|
|
|
|
|
covspans.extend(extra_spans);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-16 01:28:22 +10:00
|
|
|
/// Uses the holes to divide the given covspans into buckets, such that:
|
|
|
|
|
/// - No span in any hole overlaps a bucket (truncating the spans if necessary).
|
|
|
|
|
/// - The spans in each bucket are strictly after all spans in previous buckets,
|
|
|
|
|
/// and strictly before all spans in subsequent buckets.
|
|
|
|
|
///
|
|
|
|
|
/// The resulting buckets are sorted relative to each other, but might not be
|
|
|
|
|
/// internally sorted.
|
|
|
|
|
#[instrument(level = "debug")]
|
|
|
|
|
fn divide_spans_into_buckets(input_covspans: Vec<Covspan>, holes: &[Hole]) -> Vec<Vec<Covspan>> {
|
|
|
|
|
debug_assert!(input_covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
|
|
|
|
debug_assert!(holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
|
|
|
|
|
|
|
|
|
// Now we're ready to start carving holes out of the initial coverage spans,
|
|
|
|
|
// and grouping them in buckets separated by the holes.
|
|
|
|
|
|
|
|
|
|
let mut input_covspans = VecDeque::from(input_covspans);
|
|
|
|
|
let mut fragments = vec![];
|
|
|
|
|
|
|
|
|
|
// For each hole:
|
|
|
|
|
// - Identify the spans that are entirely or partly before the hole.
|
|
|
|
|
// - Put those spans in a corresponding bucket, truncated to the start of the hole.
|
|
|
|
|
// - If one of those spans also extends after the hole, put the rest of it
|
|
|
|
|
// in a "fragments" vector that is processed by the next hole.
|
|
|
|
|
let mut buckets = (0..holes.len()).map(|_| vec![]).collect::<Vec<_>>();
|
|
|
|
|
for (hole, bucket) in holes.iter().zip(&mut buckets) {
|
|
|
|
|
let fragments_from_prev = std::mem::take(&mut fragments);
|
|
|
|
|
|
|
|
|
|
// Only inspect spans that precede or overlap this hole,
|
|
|
|
|
// leaving the rest to be inspected by later holes.
|
|
|
|
|
// (This relies on the spans and holes both being sorted.)
|
|
|
|
|
let relevant_input_covspans =
|
|
|
|
|
drain_front_while(&mut input_covspans, |c| c.span.lo() < hole.span.hi());
|
|
|
|
|
|
|
|
|
|
for covspan in fragments_from_prev.into_iter().chain(relevant_input_covspans) {
|
|
|
|
|
let (before, after) = covspan.split_around_hole_span(hole.span);
|
|
|
|
|
bucket.extend(before);
|
|
|
|
|
fragments.extend(after);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// After finding the spans before each hole, any remaining fragments/spans
|
|
|
|
|
// form their own final bucket, after the final hole.
|
|
|
|
|
// (If there were no holes, this will just be all of the initial spans.)
|
|
|
|
|
fragments.extend(input_covspans);
|
|
|
|
|
buckets.push(fragments);
|
|
|
|
|
|
|
|
|
|
buckets
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-16 01:11:32 +10:00
|
|
|
/// Similar to `.drain(..)`, but stops just before it would remove an item not
|
|
|
|
|
/// satisfying the predicate.
|
|
|
|
|
fn drain_front_while<'a, T>(
|
|
|
|
|
queue: &'a mut VecDeque<T>,
|
|
|
|
|
mut pred_fn: impl FnMut(&T) -> bool,
|
2025-02-20 18:58:46 +00:00
|
|
|
) -> impl Iterator<Item = T> {
|
2024-06-16 01:11:32 +10:00
|
|
|
std::iter::from_fn(move || if pred_fn(queue.front()?) { queue.pop_front() } else { None })
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-10 01:33:33 +10:00
|
|
|
/// Takes one of the buckets of (sorted) spans extracted from MIR, and "refines"
|
2024-06-15 23:39:04 +10:00
|
|
|
/// those spans by removing spans that overlap in unwanted ways.
|
2024-06-10 01:33:33 +10:00
|
|
|
#[instrument(level = "debug")]
|
2024-06-15 23:39:04 +10:00
|
|
|
fn remove_unwanted_overlapping_spans(sorted_spans: Vec<Covspan>) -> Vec<Covspan> {
|
|
|
|
|
debug_assert!(sorted_spans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le()));
|
|
|
|
|
|
2024-06-10 01:33:33 +10:00
|
|
|
// Holds spans that have been read from the input vector, but haven't yet
|
|
|
|
|
// been committed to the output vector.
|
|
|
|
|
let mut pending = vec![];
|
|
|
|
|
let mut refined = vec![];
|
|
|
|
|
|
|
|
|
|
for curr in sorted_spans {
|
2024-06-16 01:25:05 +10:00
|
|
|
pending.retain(|prev: &Covspan| {
|
2024-06-10 01:33:33 +10:00
|
|
|
if prev.span.hi() <= curr.span.lo() {
|
|
|
|
|
// There's no overlap between the previous/current covspans,
|
|
|
|
|
// so move the previous one into the refined list.
|
2024-06-16 01:25:05 +10:00
|
|
|
refined.push(prev.clone());
|
2023-12-07 14:04:10 +11:00
|
|
|
false
|
2024-06-10 01:33:33 +10:00
|
|
|
} else {
|
|
|
|
|
// Otherwise, retain the previous covspan only if it has the
|
|
|
|
|
// same BCB. This tends to discard long outer spans that enclose
|
|
|
|
|
// smaller inner spans with different control flow.
|
|
|
|
|
prev.bcb == curr.bcb
|
2023-12-07 14:04:10 +11:00
|
|
|
}
|
|
|
|
|
});
|
2024-06-10 01:33:33 +10:00
|
|
|
pending.push(curr);
|
Updates to experimental coverage counter injection
This is a combination of 18 commits.
Commit #2:
Additional examples and some small improvements.
Commit #3:
fixed mir-opt non-mir extensions and spanview title elements
Corrected a fairly recent assumption in runtest.rs that all MIR dump
files end in .mir. (It was appending .mir to the graphviz .dot and
spanview .html file names when generating blessed output files. That
also left outdated files in the baseline alongside the files with the
incorrect names, which I've now removed.)
Updated spanview HTML title elements to match their content, replacing a
hardcoded and incorrect name that was left in accidentally when
originally submitted.
Commit #4:
added more test examples
also improved Makefiles with support for non-zero exit status and to
force validation of tests unless a specific test overrides it with a
specific comment.
Commit #5:
Fixed rare issues after testing on real-world crate
Commit #6:
Addressed PR feedback, and removed temporary -Zexperimental-coverage
-Zinstrument-coverage once again supports the latest capabilities of
LLVM instrprof coverage instrumentation.
Also fixed a bug in spanview.
Commit #7:
Fix closure handling, add tests for closures and inner items
And cleaned up other tests for consistency, and to make it more clear
where spans start/end by breaking up lines.
Commit #8:
renamed "typical" test results "expected"
Now that the `llvm-cov show` tests are improved to normally expect
matching actuals, and to allow individual tests to override that
expectation.
Commit #9:
test coverage of inline generic struct function
Commit #10:
Addressed review feedback
* Removed unnecessary Unreachable filter.
* Replaced a match wildcard with remining variants.
* Added more comments to help clarify the role of successors() in the
CFG traversal
Commit #11:
refactoring based on feedback
* refactored `fn coverage_spans()`.
* changed the way I expand an empty coverage span to improve performance
* fixed a typo that I had accidently left in, in visit.rs
Commit #12:
Optimized use of SourceMap and SourceFile
Commit #13:
Fixed a regression, and synched with upstream
Some generated test file names changed due to some new change upstream.
Commit #14:
Stripping out crate disambiguators from demangled names
These can vary depending on the test platform.
Commit #15:
Ignore llvm-cov show diff on test with generics, expand IO error message
Tests with generics produce llvm-cov show results with demangled names
that can include an unstable "crate disambiguator" (hex value). The
value changes when run in the Rust CI Windows environment. I added a sed
filter to strip them out (in a prior commit), but sed also appears to
fail in the same environment. Until I can figure out a workaround, I'm
just going to ignore this specific test result. I added a FIXME to
follow up later, but it's not that critical.
I also saw an error with Windows GNU, but the IO error did not
specify a path for the directory or file that triggered the error. I
updated the error messages to provide more info for next, time but also
noticed some other tests with similar steps did not fail. Looks
spurious.
Commit #16:
Modify rust-demangler to strip disambiguators by default
Commit #17:
Remove std::process::exit from coverage tests
Due to Issue #77553, programs that call std::process::exit() do not
generate coverage results on Windows MSVC.
Commit #18:
fix: test file paths exceeding Windows max path len
2020-09-01 16:15:17 -07:00
|
|
|
}
|
|
|
|
|
|
2024-06-10 01:33:33 +10:00
|
|
|
// Drain the rest of the pending list into the refined list.
|
2024-06-16 01:25:05 +10:00
|
|
|
refined.extend(pending);
|
2024-06-10 01:33:33 +10:00
|
|
|
refined
|
2020-06-07 19:35:15 -07:00
|
|
|
}
|
2024-06-16 01:11:32 +10:00
|
|
|
|
2024-06-16 01:25:05 +10:00
|
|
|
#[derive(Clone, Debug)]
|
|
|
|
|
struct Covspan {
|
|
|
|
|
span: Span,
|
|
|
|
|
bcb: BasicCoverageBlock,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl Covspan {
|
|
|
|
|
/// Splits this covspan into 0-2 parts:
|
|
|
|
|
/// - The part that is strictly before the hole span, if any.
|
|
|
|
|
/// - The part that is strictly after the hole span, if any.
|
|
|
|
|
fn split_around_hole_span(&self, hole_span: Span) -> (Option<Self>, Option<Self>) {
|
|
|
|
|
let before = try {
|
|
|
|
|
let span = self.span.trim_end(hole_span)?;
|
|
|
|
|
Self { span, ..*self }
|
|
|
|
|
};
|
|
|
|
|
let after = try {
|
|
|
|
|
let span = self.span.trim_start(hole_span)?;
|
|
|
|
|
Self { span, ..*self }
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
(before, after)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// If `self` and `other` can be merged (i.e. they have the same BCB),
|
|
|
|
|
/// mutates `self.span` to also include `other.span` and returns true.
|
|
|
|
|
///
|
|
|
|
|
/// Note that compatible covspans can be merged even if their underlying
|
|
|
|
|
/// spans are not overlapping/adjacent; any space between them will also be
|
|
|
|
|
/// part of the merged covspan.
|
|
|
|
|
fn merge_if_eligible(&mut self, other: &Self) -> bool {
|
|
|
|
|
if self.bcb != other.bcb {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
self.span = self.span.to(other.span);
|
|
|
|
|
true
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-16 01:11:32 +10:00
|
|
|
/// Compares two spans in (lo ascending, hi descending) order.
|
|
|
|
|
fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
|
|
|
|
|
// First sort by span start.
|
|
|
|
|
Ord::cmp(&a.lo(), &b.lo())
|
|
|
|
|
// If span starts are the same, sort by span end in reverse order.
|
|
|
|
|
// This ensures that if spans A and B are adjacent in the list,
|
|
|
|
|
// and they overlap but are not equal, then either:
|
|
|
|
|
// - Span A extends further left, or
|
|
|
|
|
// - Both have the same start and span A extends further right
|
|
|
|
|
.then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
|
|
|
|
|
}
|