diff options
| author | Matthias Krüger <476013+matthiaskrgr@users.noreply.github.com> | 2025-03-25 18:09:05 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-03-25 18:09:05 +0100 |
| commit | 91b98d6511fa9e7e8cb25af8e0dd37df78533500 (patch) | |
| tree | 1e470f716319be053b6aa9281cf77a4780ef421c /compiler/rustc_mir_transform/src/coverage/spans.rs | |
| parent | 43297ffc22ae4c053dc9904cd8a2cb0fde1198a9 (diff) | |
| parent | 7fdac5eef09a11fd4f35ab272d83f5ea08b15320 (diff) | |
| download | rust-91b98d6511fa9e7e8cb25af8e0dd37df78533500.tar.gz rust-91b98d6511fa9e7e8cb25af8e0dd37df78533500.zip | |
Rollup merge of #138776 - Zalathar:unexpand, r=oli-obk
coverage: Separate span-extraction from unexpansion Historically, coverage instrumentation has relied on eagerly “unexpanding” MIR spans back to ancestor spans that have the same context as the function body, and lie within that body. Doing so makes several subsequent operations more straightforward. In order to support expansion regions, we need to stop doing that, and handle layers of macro-expansion more explicitly. This PR takes a step in that direction, by deferring some of the unexpansion steps, and concentrating them in one place (`spans::extract_refined_covspans`). Unexpansion still takes place as before, but these changes will make it easier to experiment with expansion-aware coverage instrumentation.
Diffstat (limited to 'compiler/rustc_mir_transform/src/coverage/spans.rs')
| -rw-r--r-- | compiler/rustc_mir_transform/src/coverage/spans.rs | 45 |
1 files changed, 39 insertions, 6 deletions
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index b9ed6984ddb..8befe9c5d8d 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -6,10 +6,8 @@ use rustc_span::{DesugaringKind, ExpnKind, MacroKind, Span}; use tracing::{debug, debug_span, instrument}; use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph}; -use crate::coverage::spans::from_mir::{ - ExtractedCovspans, Hole, SpanFromMir, extract_covspans_from_mir, -}; -use crate::coverage::{ExtractedHirInfo, mappings}; +use crate::coverage::spans::from_mir::{Hole, RawSpanFromMir, SpanFromMir}; +use crate::coverage::{ExtractedHirInfo, mappings, unexpand}; mod from_mir; @@ -19,7 +17,35 @@ pub(super) fn extract_refined_covspans( graph: &CoverageGraph, code_mappings: &mut impl Extend<mappings::CodeMapping>, ) { - let ExtractedCovspans { mut covspans } = extract_covspans_from_mir(mir_body, hir_info, graph); + let &ExtractedHirInfo { body_span, .. } = hir_info; + + let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph); + let mut covspans = raw_spans + .into_iter() + .filter_map(|RawSpanFromMir { raw_span, bcb }| try { + let (span, expn_kind) = + unexpand::unexpand_into_body_span_with_expn_kind(raw_span, body_span)?; + // Discard any spans that fill the entire body, because they tend + // to represent compiler-inserted code, e.g. implicitly returning `()`. + if span.source_equal(body_span) { + return None; + }; + SpanFromMir { span, expn_kind, bcb } + }) + .collect::<Vec<_>>(); + + // Only proceed if we found at least one usable span. + if covspans.is_empty() { + return; + } + + // Also add the adjusted 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()), + )); // First, perform the passes that need macro information. covspans.sort_by(|a, b| graph.cmp_in_dominator_order(a.bcb, b.bcb)); @@ -43,7 +69,14 @@ pub(super) fn extract_refined_covspans( covspans.dedup_by(|b, a| a.span.source_equal(b.span)); // Sort the holes, and merge overlapping/adjacent holes. - let mut holes = hir_info.hole_spans.iter().map(|&span| Hole { span }).collect::<Vec<_>>(); + let mut holes = hir_info + .hole_spans + .iter() + .copied() + // Discard any holes that aren't directly visible within the body span. + .filter(|&hole_span| body_span.contains(hole_span) && body_span.eq_ctxt(hole_span)) + .map(|span| Hole { span }) + .collect::<Vec<_>>(); holes.sort_by(|a, b| compare_spans(a.span, b.span)); holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b)); |
