1- use rustc_middle:: mir;
21use rustc_middle:: mir:: coverage:: { Mapping , MappingKind , START_BCB } ;
32use rustc_middle:: ty:: TyCtxt ;
43use rustc_span:: source_map:: SourceMap ;
54use rustc_span:: { BytePos , DesugaringKind , ExpnId , ExpnKind , MacroKind , Span } ;
65use tracing:: instrument;
76
8- use crate :: coverage:: expansion:: { self , ExpnTree , SpanWithBcb } ;
7+ use crate :: coverage:: expansion:: { ExpnTree , SpanWithBcb } ;
98use crate :: coverage:: graph:: { BasicCoverageBlock , CoverageGraph } ;
109use crate :: coverage:: hir_info:: ExtractedHirInfo ;
11- use crate :: coverage:: spans:: from_mir:: { Hole , RawSpanFromMir } ;
12-
13- mod from_mir;
1410
1511pub ( super ) fn extract_refined_covspans < ' tcx > (
1612 tcx : TyCtxt < ' tcx > ,
17- mir_body : & mir:: Body < ' tcx > ,
1813 hir_info : & ExtractedHirInfo ,
1914 graph : & CoverageGraph ,
15+ expn_tree : & ExpnTree ,
2016 mappings : & mut Vec < Mapping > ,
2117) {
2218 if hir_info. is_async_fn {
@@ -32,22 +28,32 @@ pub(super) fn extract_refined_covspans<'tcx>(
3228
3329 let & ExtractedHirInfo { body_span, .. } = hir_info;
3430
35- let raw_spans = from_mir:: extract_raw_spans_from_mir ( mir_body, graph) ;
36- // Use the raw spans to build a tree of expansions for this function.
37- let expn_tree = expansion:: build_expn_tree (
38- raw_spans
39- . into_iter ( )
40- . map ( |RawSpanFromMir { raw_span, bcb } | SpanWithBcb { span : raw_span, bcb } ) ,
41- ) ;
31+ // If there somehow isn't an expansion tree node corresponding to the
32+ // body span, return now and don't create any mappings.
33+ let Some ( node) = expn_tree. get ( body_span. ctxt ( ) . outer_expn ( ) ) else { return } ;
4234
4335 let mut covspans = vec ! [ ] ;
44- let mut push_covspan = |covspan : Covspan | {
36+
37+ for & SpanWithBcb { span, bcb } in & node. spans {
38+ covspans. push ( Covspan { span, bcb } ) ;
39+ }
40+
41+ // For each expansion with its call-site in the body span, try to
42+ // distill a corresponding covspan.
43+ for & child_expn_id in & node. child_expn_ids {
44+ if let Some ( covspan) = single_covspan_for_child_expn ( tcx, graph, & expn_tree, child_expn_id)
45+ {
46+ covspans. push ( covspan) ;
47+ }
48+ }
49+
50+ covspans. retain ( |covspan : & Covspan | {
4551 let covspan_span = covspan. span ;
4652 // Discard any spans not contained within the function body span.
4753 // Also discard any spans that fill the entire body, because they tend
4854 // to represent compiler-inserted code, e.g. implicitly returning `()`.
4955 if !body_span. contains ( covspan_span) || body_span. source_equal ( covspan_span) {
50- return ;
56+ return false ;
5157 }
5258
5359 // Each pushed covspan should have the same context as the body span.
@@ -57,27 +63,11 @@ pub(super) fn extract_refined_covspans<'tcx>(
5763 false ,
5864 "span context mismatch: body_span={body_span:?}, covspan.span={covspan_span:?}"
5965 ) ;
60- return ;
66+ return false ;
6167 }
6268
63- covspans. push ( covspan) ;
64- } ;
65-
66- if let Some ( node) = expn_tree. get ( body_span. ctxt ( ) . outer_expn ( ) ) {
67- for & SpanWithBcb { span, bcb } in & node. spans {
68- push_covspan ( Covspan { span, bcb } ) ;
69- }
70-
71- // For each expansion with its call-site in the body span, try to
72- // distill a corresponding covspan.
73- for & child_expn_id in & node. child_expn_ids {
74- if let Some ( covspan) =
75- single_covspan_for_child_expn ( tcx, graph, & expn_tree, child_expn_id)
76- {
77- push_covspan ( covspan) ;
78- }
79- }
80- }
69+ true
70+ } ) ;
8171
8272 // Only proceed if we found at least one usable span.
8373 if covspans. is_empty ( ) {
@@ -107,14 +97,8 @@ pub(super) fn extract_refined_covspans<'tcx>(
10797 covspans. dedup_by ( |b, a| a. span . source_equal ( b. span ) ) ;
10898
10999 // Sort the holes, and merge overlapping/adjacent holes.
110- let mut holes = hir_info
111- . hole_spans
112- . iter ( )
113- . copied ( )
114- // Discard any holes that aren't directly visible within the body span.
115- . filter ( |& hole_span| body_span. contains ( hole_span) && body_span. eq_ctxt ( hole_span) )
116- . map ( |span| Hole { span } )
117- . collect :: < Vec < _ > > ( ) ;
100+ let mut holes = node. hole_spans . iter ( ) . copied ( ) . map ( |span| Hole { span } ) . collect :: < Vec < _ > > ( ) ;
101+
118102 holes. sort_by ( |a, b| compare_spans ( a. span , b. span ) ) ;
119103 holes. dedup_by ( |b, a| a. merge_if_overlapping_or_adjacent ( b) ) ;
120104
@@ -295,3 +279,19 @@ fn ensure_non_empty_span(source_map: &SourceMap, span: Span) -> Option<Span> {
295279 } )
296280 . ok ( ) ?
297281}
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