coverage: Only merge adjacent coverage spans
This also removes some manipulation of the function signature span that only made sense in the context of merging non-adjacent spans.
This commit is contained in:
parent
651e9cf327
commit
4d5a1acebf
139 changed files with 2982 additions and 1919 deletions
|
|
@ -91,7 +91,7 @@ pub(super) fn extract_all_mapping_info_from_mir<'tcx>(
|
|||
// When debugging flag `-Zcoverage-options=no-mir-spans` is set, we need
|
||||
// to give the same treatment to _all_ functions, because `llvm-cov`
|
||||
// seems to ignore functions that don't have any ordinary code spans.
|
||||
if let Some(span) = hir_info.fn_sig_span_extended {
|
||||
if let Some(span) = hir_info.fn_sig_span {
|
||||
code_mappings.push(CodeMapping { span, bcb: START_BCB });
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -268,9 +268,9 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb
|
|||
struct ExtractedHirInfo {
|
||||
function_source_hash: u64,
|
||||
is_async_fn: bool,
|
||||
/// The span of the function's signature, extended to the start of `body_span`.
|
||||
/// The span of the function's signature, if available.
|
||||
/// Must have the same context and filename as the body span.
|
||||
fn_sig_span_extended: Option<Span>,
|
||||
fn_sig_span: Option<Span>,
|
||||
body_span: Span,
|
||||
/// "Holes" are regions within the function body (or its expansions) that
|
||||
/// should not be included in coverage spans for this function
|
||||
|
|
@ -308,30 +308,20 @@ fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> ExtractedHir
|
|||
|
||||
// The actual signature span is only used if it has the same context and
|
||||
// filename as the body, and precedes the body.
|
||||
let fn_sig_span_extended = maybe_fn_sig
|
||||
.map(|fn_sig| fn_sig.span)
|
||||
.filter(|&fn_sig_span| {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo());
|
||||
let fn_sig_span = maybe_fn_sig.map(|fn_sig| fn_sig.span).filter(|&fn_sig_span| {
|
||||
let source_map = tcx.sess.source_map();
|
||||
let file_idx = |span: Span| source_map.lookup_source_file_idx(span.lo());
|
||||
|
||||
fn_sig_span.eq_ctxt(body_span)
|
||||
&& fn_sig_span.hi() <= body_span.lo()
|
||||
&& file_idx(fn_sig_span) == file_idx(body_span)
|
||||
})
|
||||
// If so, extend it to the start of the body span.
|
||||
.map(|fn_sig_span| fn_sig_span.with_hi(body_span.lo()));
|
||||
fn_sig_span.eq_ctxt(body_span)
|
||||
&& fn_sig_span.hi() <= body_span.lo()
|
||||
&& file_idx(fn_sig_span) == file_idx(body_span)
|
||||
});
|
||||
|
||||
let function_source_hash = hash_mir_source(tcx, hir_body);
|
||||
|
||||
let hole_spans = extract_hole_spans_from_hir(tcx, hir_body);
|
||||
|
||||
ExtractedHirInfo {
|
||||
function_source_hash,
|
||||
is_async_fn,
|
||||
fn_sig_span_extended,
|
||||
body_span,
|
||||
hole_spans,
|
||||
}
|
||||
ExtractedHirInfo { function_source_hash, is_async_fn, fn_sig_span, body_span, hole_spans }
|
||||
}
|
||||
|
||||
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx hir::Body<'tcx>) -> u64 {
|
||||
|
|
|
|||
|
|
@ -42,12 +42,12 @@ pub(super) fn extract_refined_covspans<'tcx>(
|
|||
return;
|
||||
}
|
||||
|
||||
// Also add the adjusted function signature span, if available.
|
||||
// Also add the function signature span, if available.
|
||||
// Otherwise, add a fake span at the start of the body, to avoid an ugly
|
||||
// gap between the start of the body and the first real span.
|
||||
// FIXME: Find a more principled way to solve this problem.
|
||||
covspans.push(SpanFromMir::for_fn_sig(
|
||||
hir_info.fn_sig_span_extended.unwrap_or_else(|| body_span.shrink_to_lo()),
|
||||
hir_info.fn_sig_span.unwrap_or_else(|| body_span.shrink_to_lo()),
|
||||
));
|
||||
|
||||
// First, perform the passes that need macro information.
|
||||
|
|
@ -227,19 +227,21 @@ struct Covspan {
|
|||
}
|
||||
|
||||
impl Covspan {
|
||||
/// 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.
|
||||
/// If `self` and `other` can be merged, 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.
|
||||
/// Two covspans can be merged if they have the same BCB, and they are
|
||||
/// overlapping or adjacent.
|
||||
fn merge_if_eligible(&mut self, other: &Self) -> bool {
|
||||
if self.bcb != other.bcb {
|
||||
return false;
|
||||
}
|
||||
let eligible_for_merge =
|
||||
|a: &Self, b: &Self| (a.bcb == b.bcb) && a.span.overlaps_or_adjacent(b.span);
|
||||
|
||||
self.span = self.span.to(other.span);
|
||||
true
|
||||
if eligible_for_merge(self, other) {
|
||||
self.span = self.span.to(other.span);
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue