Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 1941cb0

Browse files
committedDec 24, 2023
coverage: Split out SpanFromMir from CoverageSpan
This draws a clear distinction between the fields/methods that are needed by initial span extraction and preprocessing, and those that are needed by the main "refinement" loop.
1 parent c1ad2b9 commit 1941cb0

File tree

2 files changed

+80
-66
lines changed

2 files changed

+80
-66
lines changed
 

‎compiler/rustc_mir_transform/src/coverage/spans.rs

+4-55
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
1-
use std::cell::OnceCell;
2-
31
use rustc_data_structures::graph::WithNumNodes;
42
use rustc_index::IndexVec;
53
use rustc_middle::mir;
6-
use rustc_span::{BytePos, ExpnKind, MacroKind, Span, Symbol, DUMMY_SP};
4+
use rustc_span::{BytePos, Span, DUMMY_SP};
75

8-
use super::graph::{BasicCoverageBlock, CoverageGraph, START_BCB};
6+
use super::graph::{BasicCoverageBlock, CoverageGraph};
97
use crate::coverage::ExtractedHirInfo;
108

119
mod from_mir;
@@ -66,8 +64,6 @@ impl CoverageSpans {
6664
#[derive(Debug, Clone)]
6765
struct CoverageSpan {
6866
span: Span,
69-
expn_span: Span,
70-
current_macro_or_none: OnceCell<Option<Symbol>>,
7167
bcb: BasicCoverageBlock,
7268
/// List of all the original spans from MIR that have been merged into this
7369
/// span. Mainly used to precisely skip over gaps when truncating a span.
@@ -76,24 +72,8 @@ struct CoverageSpan {
7672
}
7773

7874
impl CoverageSpan {
79-
pub fn for_fn_sig(fn_sig_span: Span) -> Self {
80-
Self::new(fn_sig_span, fn_sig_span, START_BCB, false)
81-
}
82-
83-
pub(super) fn new(
84-
span: Span,
85-
expn_span: Span,
86-
bcb: BasicCoverageBlock,
87-
is_closure: bool,
88-
) -> Self {
89-
Self {
90-
span,
91-
expn_span,
92-
current_macro_or_none: Default::default(),
93-
bcb,
94-
merged_spans: vec![span],
95-
is_closure,
96-
}
75+
fn new(span: Span, bcb: BasicCoverageBlock, is_closure: bool) -> Self {
76+
Self { span, bcb, merged_spans: vec![span], is_closure }
9777
}
9878

9979
pub fn merge_from(&mut self, other: &Self) {
@@ -118,37 +98,6 @@ impl CoverageSpan {
11898
pub fn is_in_same_bcb(&self, other: &Self) -> bool {
11999
self.bcb == other.bcb
120100
}
121-
122-
/// If the span is part of a macro, returns the macro name symbol.
123-
pub fn current_macro(&self) -> Option<Symbol> {
124-
self.current_macro_or_none
125-
.get_or_init(|| {
126-
if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
127-
self.expn_span.ctxt().outer_expn_data().kind
128-
{
129-
return Some(current_macro);
130-
}
131-
None
132-
})
133-
.map(|symbol| symbol)
134-
}
135-
136-
/// If the span is part of a macro, and the macro is visible (expands directly to the given
137-
/// body_span), returns the macro name symbol.
138-
pub fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
139-
let current_macro = self.current_macro()?;
140-
let parent_callsite = self.expn_span.parent_callsite()?;
141-
142-
// In addition to matching the context of the body span, the parent callsite
143-
// must also be the source callsite, i.e. the parent must have no parent.
144-
let is_visible_macro =
145-
parent_callsite.parent_callsite().is_none() && parent_callsite.eq_ctxt(body_span);
146-
is_visible_macro.then_some(current_macro)
147-
}
148-
149-
pub fn is_macro_expansion(&self) -> bool {
150-
self.current_macro().is_some()
151-
}
152101
}
153102

154103
/// Converts the initial set of `CoverageSpan`s (one per MIR `Statement` or `Terminator`) into a

‎compiler/rustc_mir_transform/src/coverage/spans/from_mir.rs

+76-11
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ use rustc_middle::mir::{
44
self, AggregateKind, FakeReadCause, Rvalue, Statement, StatementKind, Terminator,
55
TerminatorKind,
66
};
7-
use rustc_span::Span;
7+
use rustc_span::{ExpnKind, MacroKind, Span, Symbol};
88

9-
use crate::coverage::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
9+
use crate::coverage::graph::{
10+
BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph, START_BCB,
11+
};
1012
use crate::coverage::spans::CoverageSpan;
1113
use crate::coverage::ExtractedHirInfo;
1214

@@ -17,7 +19,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
1719
) -> Vec<CoverageSpan> {
1820
let &ExtractedHirInfo { is_async_fn, fn_sig_span, body_span, .. } = hir_info;
1921

20-
let mut initial_spans = vec![CoverageSpan::for_fn_sig(fn_sig_span)];
22+
let mut initial_spans = vec![SpanFromMir::for_fn_sig(fn_sig_span)];
2123

2224
if is_async_fn {
2325
// An async function desugars into a function that returns a future,
@@ -57,7 +59,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
5759
.then_with(|| Ord::cmp(&a.is_closure, &b.is_closure).reverse())
5860
});
5961

60-
initial_spans
62+
initial_spans.into_iter().map(SpanFromMir::into_coverage_span).collect::<Vec<_>>()
6163
}
6264

6365
/// Macros that expand into branches (e.g. `assert!`, `trace!`) tend to generate
@@ -67,7 +69,7 @@ pub(super) fn mir_to_initial_sorted_coverage_spans(
6769
///
6870
/// (The input spans should be sorted in BCB dominator order, so that the
6971
/// retained "first" span is likely to dominate the others.)
70-
fn remove_unwanted_macro_spans(initial_spans: &mut Vec<CoverageSpan>) {
72+
fn remove_unwanted_macro_spans(initial_spans: &mut Vec<SpanFromMir>) {
7173
let mut seen_spans = FxHashSet::default();
7274
initial_spans.retain(|covspan| {
7375
// Ignore (retain) closure spans and non-macro-expansion spans.
@@ -84,7 +86,7 @@ fn remove_unwanted_macro_spans(initial_spans: &mut Vec<CoverageSpan>) {
8486
/// function body, split it into two parts. The first part covers just the
8587
/// macro name plus `!`, and the second part covers the rest of the macro
8688
/// invocation. This seems to give better results for code that uses macros.
87-
fn split_visible_macro_spans(initial_spans: &mut Vec<CoverageSpan>, hir_info: &ExtractedHirInfo) {
89+
fn split_visible_macro_spans(initial_spans: &mut Vec<SpanFromMir>, hir_info: &ExtractedHirInfo) {
8890
let mut extra_spans = vec![];
8991

9092
initial_spans.retain(|covspan| {
@@ -105,8 +107,8 @@ fn split_visible_macro_spans(initial_spans: &mut Vec<CoverageSpan>, hir_info: &E
105107
}
106108

107109
assert!(!covspan.is_closure);
108-
extra_spans.push(CoverageSpan::new(before, covspan.expn_span, covspan.bcb, false));
109-
extra_spans.push(CoverageSpan::new(after, covspan.expn_span, covspan.bcb, false));
110+
extra_spans.push(SpanFromMir::new(before, covspan.expn_span, covspan.bcb, false));
111+
extra_spans.push(SpanFromMir::new(after, covspan.expn_span, covspan.bcb, false));
110112
false // Discard the original covspan that we just split.
111113
});
112114

@@ -125,22 +127,22 @@ fn bcb_to_initial_coverage_spans<'a, 'tcx>(
125127
body_span: Span,
126128
bcb: BasicCoverageBlock,
127129
bcb_data: &'a BasicCoverageBlockData,
128-
) -> impl Iterator<Item = CoverageSpan> + Captures<'a> + Captures<'tcx> {
130+
) -> impl Iterator<Item = SpanFromMir> + Captures<'a> + Captures<'tcx> {
129131
bcb_data.basic_blocks.iter().flat_map(move |&bb| {
130132
let data = &mir_body[bb];
131133

132134
let statement_spans = data.statements.iter().filter_map(move |statement| {
133135
let expn_span = filtered_statement_span(statement)?;
134136
let span = unexpand_into_body_span(expn_span, body_span)?;
135137

136-
Some(CoverageSpan::new(span, expn_span, bcb, is_closure(statement)))
138+
Some(SpanFromMir::new(span, expn_span, bcb, is_closure(statement)))
137139
});
138140

139141
let terminator_span = Some(data.terminator()).into_iter().filter_map(move |terminator| {
140142
let expn_span = filtered_terminator_span(terminator)?;
141143
let span = unexpand_into_body_span(expn_span, body_span)?;
142144

143-
Some(CoverageSpan::new(span, expn_span, bcb, false))
145+
Some(SpanFromMir::new(span, expn_span, bcb, false))
144146
});
145147

146148
statement_spans.chain(terminator_span)
@@ -270,3 +272,66 @@ fn unexpand_into_body_span(span: Span, body_span: Span) -> Option<Span> {
270272
let original_span = original_sp(span, body_span).with_ctxt(body_span.ctxt());
271273
body_span.contains(original_span).then_some(original_span)
272274
}
275+
276+
#[derive(Debug)]
277+
struct SpanFromMir {
278+
/// A copy of `expn_span` that has been "un-expanded" back to the current
279+
/// function's `body_span`. After various intermediate processing steps,
280+
/// this span is emitted as part of the final coverage mappings.
281+
///
282+
/// With the exception of `fn_sig_span`, this should always be contained
283+
/// within `body_span`.
284+
span: Span,
285+
/// The actual span that was extracted from MIR, used to look up information
286+
/// about macro expansions.
287+
expn_span: Span,
288+
current_macro_or_none: std::cell::OnceCell<Option<Symbol>>,
289+
bcb: BasicCoverageBlock,
290+
is_closure: bool,
291+
}
292+
293+
impl SpanFromMir {
294+
fn for_fn_sig(fn_sig_span: Span) -> Self {
295+
Self::new(fn_sig_span, fn_sig_span, START_BCB, false)
296+
}
297+
298+
fn new(span: Span, expn_span: Span, bcb: BasicCoverageBlock, is_closure: bool) -> Self {
299+
Self { span, expn_span, current_macro_or_none: Default::default(), bcb, is_closure }
300+
}
301+
302+
/// If the span is part of a macro, returns the macro name symbol.
303+
fn current_macro(&self) -> Option<Symbol> {
304+
self.current_macro_or_none
305+
.get_or_init(|| {
306+
if let ExpnKind::Macro(MacroKind::Bang, current_macro) =
307+
self.expn_span.ctxt().outer_expn_data().kind
308+
{
309+
return Some(current_macro);
310+
}
311+
None
312+
})
313+
.map(|symbol| symbol)
314+
}
315+
316+
/// If the span is part of a macro, and the macro is visible (expands directly to the given
317+
/// body_span), returns the macro name symbol.
318+
fn visible_macro(&self, body_span: Span) -> Option<Symbol> {
319+
let current_macro = self.current_macro()?;
320+
let parent_callsite = self.expn_span.parent_callsite()?;
321+
322+
// In addition to matching the context of the body span, the parent callsite
323+
// must also be the source callsite, i.e. the parent must have no parent.
324+
let is_visible_macro =
325+
parent_callsite.parent_callsite().is_none() && parent_callsite.eq_ctxt(body_span);
326+
is_visible_macro.then_some(current_macro)
327+
}
328+
329+
fn is_macro_expansion(&self) -> bool {
330+
self.current_macro().is_some()
331+
}
332+
333+
fn into_coverage_span(self) -> CoverageSpan {
334+
let Self { span, expn_span: _, current_macro_or_none: _, bcb, is_closure } = self;
335+
CoverageSpan::new(span, bcb, is_closure)
336+
}
337+
}

0 commit comments

Comments
 (0)
Failed to load comments.