Skip to content

Commit 696690b

Browse files
committed
coverage: Associate hole spans with expansion tree nodes
This will make it easier to perform span refinement for child expansions.
1 parent 075f9c4 commit 696690b

File tree

4 files changed

+39
-27
lines changed

4 files changed

+39
-27
lines changed

compiler/rustc_mir_transform/src/coverage/expansion.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_span::{ExpnId, ExpnKind, Span};
55

66
use crate::coverage::from_mir;
77
use crate::coverage::graph::CoverageGraph;
8+
use crate::coverage::hir_info::ExtractedHirInfo;
89

910
#[derive(Clone, Copy, Debug)]
1011
pub(crate) struct SpanWithBcb {
@@ -74,6 +75,10 @@ pub(crate) struct ExpnNode {
7475
pub(crate) spans: Vec<SpanWithBcb>,
7576
/// Expansions whose call-site is in this expansion.
7677
pub(crate) child_expn_ids: FxIndexSet<ExpnId>,
78+
79+
/// Hole spans belonging to this expansion, to be carved out from the
80+
/// code spans during span refinement.
81+
pub(crate) hole_spans: Vec<Span>,
7782
}
7883

7984
impl ExpnNode {
@@ -92,13 +97,19 @@ impl ExpnNode {
9297

9398
spans: vec![],
9499
child_expn_ids: FxIndexSet::default(),
100+
101+
hole_spans: vec![],
95102
}
96103
}
97104
}
98105

99106
/// Extracts raw span/BCB pairs from potentially-different syntax contexts, and
100107
/// arranges them into an "expansion tree" based on their expansion call-sites.
101-
pub(crate) fn build_expn_tree(mir_body: &mir::Body<'_>, graph: &CoverageGraph) -> ExpnTree {
108+
pub(crate) fn build_expn_tree(
109+
mir_body: &mir::Body<'_>,
110+
hir_info: &ExtractedHirInfo,
111+
graph: &CoverageGraph,
112+
) -> ExpnTree {
102113
let raw_spans = from_mir::extract_raw_spans_from_mir(mir_body, graph);
103114

104115
let mut nodes = FxIndexMap::default();
@@ -131,5 +142,13 @@ pub(crate) fn build_expn_tree(mir_body: &mir::Body<'_>, graph: &CoverageGraph) -
131142
}
132143
}
133144

145+
// Associate each hole span (extracted from HIR) with its corresponding
146+
// expansion tree node.
147+
for &hole_span in &hir_info.hole_spans {
148+
let expn_id = hole_span.ctxt().outer_expn();
149+
let Some(node) = nodes.get_mut(&expn_id) else { continue };
150+
node.hole_spans.push(hole_span);
151+
}
152+
134153
ExpnTree { nodes }
135154
}

compiler/rustc_mir_transform/src/coverage/from_mir.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,3 @@ fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Span> {
142142
| TerminatorKind::InlineAsm { .. } => Some(terminator.source_info.span),
143143
}
144144
}
145-
146-
#[derive(Debug)]
147-
pub(crate) struct Hole {
148-
pub(crate) span: Span,
149-
}
150-
151-
impl Hole {
152-
pub(crate) fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
153-
if !self.span.overlaps_or_adjacent(other.span) {
154-
return false;
155-
}
156-
157-
self.span = self.span.to(other.span);
158-
true
159-
}
160-
}

compiler/rustc_mir_transform/src/coverage/mappings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ pub(crate) fn extract_mappings_from_mir<'tcx>(
2424
hir_info: &ExtractedHirInfo,
2525
graph: &CoverageGraph,
2626
) -> ExtractedMappings {
27-
let expn_tree = expansion::build_expn_tree(mir_body, graph);
27+
let expn_tree = expansion::build_expn_tree(mir_body, hir_info, graph);
2828

2929
let mut mappings = vec![];
3030

compiler/rustc_mir_transform/src/coverage/spans.rs

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ use rustc_span::{BytePos, DesugaringKind, ExpnId, ExpnKind, MacroKind, Span};
55
use tracing::instrument;
66

77
use crate::coverage::expansion::{ExpnTree, SpanWithBcb};
8-
use crate::coverage::from_mir::Hole;
98
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
109
use crate::coverage::hir_info::ExtractedHirInfo;
1110

@@ -98,14 +97,8 @@ pub(super) fn extract_refined_covspans<'tcx>(
9897
covspans.dedup_by(|b, a| a.span.source_equal(b.span));
9998

10099
// Sort the holes, and merge overlapping/adjacent holes.
101-
let mut holes = hir_info
102-
.hole_spans
103-
.iter()
104-
.copied()
105-
// Discard any holes that aren't directly visible within the body span.
106-
.filter(|&hole_span| body_span.contains(hole_span) && body_span.eq_ctxt(hole_span))
107-
.map(|span| Hole { span })
108-
.collect::<Vec<_>>();
100+
let mut holes = node.hole_spans.iter().copied().map(|span| Hole { span }).collect::<Vec<_>>();
101+
109102
holes.sort_by(|a, b| compare_spans(a.span, b.span));
110103
holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
111104

@@ -286,3 +279,19 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
286279
})
287280
.ok()?
288281
}
282+
283+
#[derive(Debug)]
284+
struct Hole {
285+
span: Span,
286+
}
287+
288+
impl Hole {
289+
fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self) -> bool {
290+
if !self.span.overlaps_or_adjacent(other.span) {
291+
return false;
292+
}
293+
294+
self.span = self.span.to(other.span);
295+
true
296+
}
297+
}

0 commit comments

Comments
 (0)