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