1
Fork 0

coverage: Don't refer to the body span when enlarging empty spans

Given that we now only enlarge empty spans to "{" or "}", there shouldn't be
any danger of enlarging beyond a function body.
This commit is contained in:
Zalathar 2025-03-18 20:31:14 +11:00
parent 259fdb5212
commit cd2b978433
2 changed files with 9 additions and 26 deletions

View file

@ -118,9 +118,8 @@ fn fill_region_tables<'tcx>(
let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } = let ffi::Regions { code_regions, branch_regions, mcdc_branch_regions, mcdc_decision_regions } =
&mut covfun.regions; &mut covfun.regions;
let make_cov_span = |span: Span| { let make_cov_span =
spans::make_coverage_span(local_file_id, source_map, fn_cov_info, &source_file, span) |span: Span| spans::make_coverage_span(local_file_id, source_map, &source_file, span);
};
let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen(); let discard_all = tcx.sess.coverage_discard_all_spans_in_codegen();
// For each counter/region pair in this function+file, convert it to a // For each counter/region pair in this function+file, convert it to a

View file

@ -1,4 +1,3 @@
use rustc_middle::mir::coverage::FunctionCoverageInfo;
use rustc_span::source_map::SourceMap; use rustc_span::source_map::SourceMap;
use rustc_span::{BytePos, Pos, SourceFile, Span}; use rustc_span::{BytePos, Pos, SourceFile, Span};
use tracing::debug; use tracing::debug;
@ -19,11 +18,10 @@ use crate::coverageinfo::mapgen::LocalFileId;
pub(crate) fn make_coverage_span( pub(crate) fn make_coverage_span(
file_id: LocalFileId, file_id: LocalFileId,
source_map: &SourceMap, source_map: &SourceMap,
fn_cov_info: &FunctionCoverageInfo,
file: &SourceFile, file: &SourceFile,
span: Span, span: Span,
) -> Option<ffi::CoverageSpan> { ) -> Option<ffi::CoverageSpan> {
let span = ensure_non_empty_span(source_map, fn_cov_info, span)?; let span = ensure_non_empty_span(source_map, span)?;
let lo = span.lo(); let lo = span.lo();
let hi = span.hi(); let hi = span.hi();
@ -55,36 +53,22 @@ pub(crate) fn make_coverage_span(
}) })
} }
fn ensure_non_empty_span( fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
source_map: &SourceMap,
fn_cov_info: &FunctionCoverageInfo,
span: Span,
) -> Option<Span> {
if !span.is_empty() { if !span.is_empty() {
return Some(span); return Some(span);
} }
let lo = span.lo(); // The span is empty, so try to enlarge it to cover an adjacent '{' or '}'.
let hi = span.hi();
// The span is empty, so try to expand it to cover an adjacent '{' or '}',
// but only within the bounds of the body span.
let try_next = hi < fn_cov_info.body_span.hi();
let try_prev = fn_cov_info.body_span.lo() < lo;
if !(try_next || try_prev) {
return None;
}
source_map source_map
.span_to_source(span, |src, start, end| try { .span_to_source(span, |src, start, end| try {
// Adjusting span endpoints by `BytePos(1)` is normally a bug, // Adjusting span endpoints by `BytePos(1)` is normally a bug,
// but in this case we have specifically checked that the character // but in this case we have specifically checked that the character
// we're skipping over is one of two specific ASCII characters, so // we're skipping over is one of two specific ASCII characters, so
// adjusting by exactly 1 byte is correct. // adjusting by exactly 1 byte is correct.
if try_next && src.as_bytes()[end] == b'{' { if src.as_bytes().get(end).copied() == Some(b'{') {
Some(span.with_hi(hi + BytePos(1))) Some(span.with_hi(span.hi() + BytePos(1)))
} else if try_prev && src.as_bytes()[start - 1] == b'}' { } else if start > 0 && src.as_bytes()[start - 1] == b'}' {
Some(span.with_lo(lo - BytePos(1))) Some(span.with_lo(span.lo() - BytePos(1)))
} else { } else {
None None
} }