@@ -11,7 +11,7 @@ use rustc_middle::mir::{
1111use rustc_middle:: ty:: TyCtxt ;
1212
1313use rustc_span:: source_map:: original_sp;
14- use rustc_span:: { BytePos , ExpnKind , MacroKind , Span } ;
14+ use rustc_span:: { BytePos , ExpnKind , MacroKind , Span , Symbol } ;
1515
1616use std:: cmp:: Ordering ;
1717
@@ -67,20 +67,17 @@ impl CoverageStatement {
6767#[ derive( Debug , Clone ) ]
6868pub ( super ) struct CoverageSpan {
6969 pub span : Span ,
70- pub is_macro_expansion : bool ,
70+ pub expn_span : Span ,
7171 pub bcb : BasicCoverageBlock ,
7272 pub coverage_statements : Vec < CoverageStatement > ,
7373 pub is_closure : bool ,
7474}
7575
7676impl CoverageSpan {
7777 pub fn for_fn_sig ( fn_sig_span : Span ) -> Self {
78- // Whether the function signature is from a macro or not, it should not be treated like
79- // macro-expanded statements and terminators.
80- let is_macro_expansion = false ;
8178 Self {
8279 span : fn_sig_span,
83- is_macro_expansion ,
80+ expn_span : fn_sig_span ,
8481 bcb : START_BCB ,
8582 coverage_statements : vec ! [ ] ,
8683 is_closure : false ,
@@ -90,7 +87,7 @@ impl CoverageSpan {
9087 pub fn for_statement (
9188 statement : & Statement < ' tcx > ,
9289 span : Span ,
93- is_macro_expansion : bool ,
90+ expn_span : Span ,
9491 bcb : BasicCoverageBlock ,
9592 bb : BasicBlock ,
9693 stmt_index : usize ,
@@ -105,7 +102,7 @@ impl CoverageSpan {
105102
106103 Self {
107104 span,
108- is_macro_expansion ,
105+ expn_span ,
109106 bcb,
110107 coverage_statements : vec ! [ CoverageStatement :: Statement ( bb, span, stmt_index) ] ,
111108 is_closure,
@@ -114,13 +111,13 @@ impl CoverageSpan {
114111
115112 pub fn for_terminator (
116113 span : Span ,
117- is_macro_expansion : bool ,
114+ expn_span : Span ,
118115 bcb : BasicCoverageBlock ,
119116 bb : BasicBlock ,
120117 ) -> Self {
121118 Self {
122119 span,
123- is_macro_expansion ,
120+ expn_span ,
124121 bcb,
125122 coverage_statements : vec ! [ CoverageStatement :: Terminator ( bb, span) ] ,
126123 is_closure : false ,
@@ -176,6 +173,34 @@ impl CoverageSpan {
176173 . collect :: < Vec < _ > > ( )
177174 . join ( "\n " )
178175 }
176+
177+ /// If the span is part of a macro, and the macro is visible (expands directly to the given
178+ /// body_span), returns the macro name symbol.
179+ pub fn current_macro ( & self ) -> Option < Symbol > {
180+ if let ExpnKind :: Macro ( MacroKind :: Bang , current_macro) =
181+ self . expn_span . ctxt ( ) . outer_expn_data ( ) . kind
182+ {
183+ return Some ( current_macro) ;
184+ }
185+ None
186+ }
187+
188+ /// If the span is part of a macro, and the macro is visible (expands directly to the given
189+ /// body_span), returns the macro name symbol.
190+ pub fn visible_macro ( & self , body_span : Span ) -> Option < Symbol > {
191+ if let Some ( current_macro) = self . current_macro ( ) {
192+ if self . expn_span . parent ( ) . unwrap_or_else ( || bug ! ( "macro must have a parent" ) ) . ctxt ( )
193+ == body_span. ctxt ( )
194+ {
195+ return Some ( current_macro) ;
196+ }
197+ }
198+ None
199+ }
200+
201+ pub fn is_macro_expansion ( & self ) -> bool {
202+ self . current_macro ( ) . is_some ( )
203+ }
179204}
180205
181206/// Converts the initial set of `CoverageSpan`s (one per MIR `Statement` or `Terminator`) into a
@@ -219,6 +244,9 @@ pub struct CoverageSpans<'a, 'tcx> {
219244 /// Assigned from `curr_original_span` from the previous iteration.
220245 prev_original_span : Span ,
221246
247+ /// A copy of the expn_span from the prior iteration.
248+ prev_expn_span : Option < Span > ,
249+
222250 /// One or more `CoverageSpan`s with the same `Span` but different `BasicCoverageBlock`s, and
223251 /// no `BasicCoverageBlock` in this list dominates another `BasicCoverageBlock` in the list.
224252 /// If a new `curr` span also fits this criteria (compared to an existing list of
@@ -273,15 +301,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
273301 curr_original_span : Span :: with_root_ctxt ( BytePos ( 0 ) , BytePos ( 0 ) ) ,
274302 some_prev : None ,
275303 prev_original_span : Span :: with_root_ctxt ( BytePos ( 0 ) , BytePos ( 0 ) ) ,
304+ prev_expn_span : None ,
276305 pending_dups : Vec :: new ( ) ,
277306 } ;
278307
279308 let sorted_spans = coverage_spans. mir_to_initial_sorted_coverage_spans ( ) ;
280309
281310 coverage_spans. sorted_spans_iter = Some ( sorted_spans. into_iter ( ) ) ;
282- coverage_spans. some_prev = coverage_spans. sorted_spans_iter . as_mut ( ) . unwrap ( ) . next ( ) ;
283- coverage_spans. prev_original_span =
284- coverage_spans. some_prev . as_ref ( ) . expect ( "at least one span" ) . span ;
285311
286312 coverage_spans. to_refined_spans ( )
287313 }
@@ -335,10 +361,14 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
335361 /// de-duplicated `CoverageSpan`s.
336362 fn to_refined_spans ( mut self ) -> Vec < CoverageSpan > {
337363 while self . next_coverage_span ( ) {
338- if self . curr ( ) . is_mergeable ( self . prev ( ) ) {
364+ if self . some_prev . is_none ( ) {
365+ debug ! ( " initial span" ) ;
366+ self . check_invoked_macro_name_span ( ) ;
367+ } else if self . curr ( ) . is_mergeable ( self . prev ( ) ) {
339368 debug ! ( " same bcb (and neither is a closure), merge with prev={:?}" , self . prev( ) ) ;
340369 let prev = self . take_prev ( ) ;
341370 self . curr_mut ( ) . merge_from ( prev) ;
371+ self . check_invoked_macro_name_span ( ) ;
342372 // Note that curr.span may now differ from curr_original_span
343373 } else if self . prev_ends_before_curr ( ) {
344374 debug ! (
@@ -347,7 +377,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
347377 self . prev( )
348378 ) ;
349379 let prev = self . take_prev ( ) ;
350- self . refined_spans . push ( prev) ;
380+ self . push_refined_span ( prev) ;
381+ self . check_invoked_macro_name_span ( ) ;
351382 } else if self . prev ( ) . is_closure {
352383 // drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
353384 // next iter
@@ -362,7 +393,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
362393 } else if self . prev_original_span == self . curr ( ) . span {
363394 // Note that this compares the new span to `prev_original_span`, which may not
364395 // be the full `prev.span` (if merged during the previous iteration).
365- if self . prev ( ) . is_macro_expansion && self . curr ( ) . is_macro_expansion {
396+ if self . prev ( ) . is_macro_expansion ( ) && self . curr ( ) . is_macro_expansion ( ) {
366397 // Macros that expand to include branching (such as
367398 // `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
368399 // `trace!()) typically generate callee spans with identical
@@ -385,15 +416,16 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
385416 }
386417 } else {
387418 self . cutoff_prev_at_overlapping_curr ( ) ;
419+ self . check_invoked_macro_name_span ( ) ;
388420 }
389421 }
390422
391423 debug ! ( " AT END, adding last prev={:?}" , self . prev( ) ) ;
392424 let prev = self . take_prev ( ) ;
393- let CoverageSpans { pending_dups, mut refined_spans , .. } = self ;
425+ let pending_dups = self . pending_dups . split_off ( 0 ) ;
394426 for dup in pending_dups {
395427 debug ! ( " ...adding at least one pending dup={:?}" , dup) ;
396- refined_spans . push ( dup) ;
428+ self . push_refined_span ( dup) ;
397429 }
398430
399431 // Async functions wrap a closure that implements the body to be executed. The enclosing
@@ -403,21 +435,60 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
403435 // excluded. The closure's `Return` is the only one that will be counted. This provides
404436 // adequate coverage, and more intuitive counts. (Avoids double-counting the closing brace
405437 // of the function body.)
406- let body_ends_with_closure = if let Some ( last_covspan) = refined_spans. last ( ) {
438+ let body_ends_with_closure = if let Some ( last_covspan) = self . refined_spans . last ( ) {
407439 last_covspan. is_closure && last_covspan. span . hi ( ) == self . body_span . hi ( )
408440 } else {
409441 false
410442 } ;
411443
412444 if !body_ends_with_closure {
413- refined_spans . push ( prev) ;
445+ self . push_refined_span ( prev) ;
414446 }
415447
416448 // Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
417449 // regions for the current function leave room for the closure's own coverage regions
418450 // (injected separately, from the closure's own MIR).
419- refined_spans. retain ( |covspan| !covspan. is_closure ) ;
420- refined_spans
451+ self . refined_spans . retain ( |covspan| !covspan. is_closure ) ;
452+ self . refined_spans
453+ }
454+
455+ fn push_refined_span ( & mut self , covspan : CoverageSpan ) {
456+ let len = self . refined_spans . len ( ) ;
457+ if len > 0 {
458+ let last = & mut self . refined_spans [ len - 1 ] ;
459+ if last. is_mergeable ( & covspan) {
460+ debug ! (
461+ "merging new refined span with last refined span, last={:?}, covspan={:?}" ,
462+ last, covspan
463+ ) ;
464+ last. merge_from ( covspan) ;
465+ return ;
466+ }
467+ }
468+ self . refined_spans . push ( covspan)
469+ }
470+
471+ fn check_invoked_macro_name_span ( & mut self ) {
472+ if let Some ( visible_macro) = self . curr ( ) . visible_macro ( self . body_span ) {
473+ if self . prev_expn_span . map_or ( true , |prev_expn_span| {
474+ self . curr ( ) . expn_span . ctxt ( ) != prev_expn_span. ctxt ( )
475+ } ) {
476+ let merged_prefix_len = self . curr_original_span . lo ( ) - self . curr ( ) . span . lo ( ) ;
477+ let after_macro_bang = merged_prefix_len
478+ + BytePos ( visible_macro. to_string ( ) . bytes ( ) . count ( ) as u32 + 1 ) ;
479+ let mut macro_name_cov = self . curr ( ) . clone ( ) ;
480+ self . curr_mut ( ) . span =
481+ self . curr ( ) . span . with_lo ( self . curr ( ) . span . lo ( ) + after_macro_bang) ;
482+ macro_name_cov. span =
483+ macro_name_cov. span . with_hi ( macro_name_cov. span . lo ( ) + after_macro_bang) ;
484+ debug ! (
485+ " and curr starts a new macro expansion, so add a new span just for \
486+ the macro `{}!`, new span={:?}",
487+ visible_macro, macro_name_cov
488+ ) ;
489+ self . push_refined_span ( macro_name_cov) ;
490+ }
491+ }
421492 }
422493
423494 // Generate a set of `CoverageSpan`s from the filtered set of `Statement`s and `Terminator`s of
@@ -440,22 +511,15 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
440511 . enumerate ( )
441512 . filter_map ( move |( index, statement) | {
442513 filtered_statement_span ( statement, self . body_span ) . map (
443- |( span, is_macro_expansion ) | {
514+ |( span, expn_span ) | {
444515 CoverageSpan :: for_statement (
445- statement,
446- span,
447- is_macro_expansion,
448- bcb,
449- bb,
450- index,
516+ statement, span, expn_span, bcb, bb, index,
451517 )
452518 } ,
453519 )
454520 } )
455521 . chain ( filtered_terminator_span ( data. terminator ( ) , self . body_span ) . map (
456- |( span, is_macro_expansion) | {
457- CoverageSpan :: for_terminator ( span, is_macro_expansion, bcb, bb)
458- } ,
522+ |( span, expn_span) | CoverageSpan :: for_terminator ( span, expn_span, bcb, bb) ,
459523 ) )
460524 } )
461525 . collect ( )
@@ -509,7 +573,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
509573 let pending_dups = self . pending_dups . split_off ( 0 ) ;
510574 for dup in pending_dups. into_iter ( ) {
511575 debug ! ( " ...adding at least one pending={:?}" , dup) ;
512- self . refined_spans . push ( dup) ;
576+ self . push_refined_span ( dup) ;
513577 }
514578 } else {
515579 self . pending_dups . clear ( ) ;
@@ -521,12 +585,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
521585 /// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order.
522586 fn next_coverage_span ( & mut self ) -> bool {
523587 if let Some ( curr) = self . some_curr . take ( ) {
588+ self . prev_expn_span = Some ( curr. expn_span ) ;
524589 self . some_prev = Some ( curr) ;
525590 self . prev_original_span = self . curr_original_span ;
526591 }
527592 while let Some ( curr) = self . sorted_spans_iter . as_mut ( ) . unwrap ( ) . next ( ) {
528593 debug ! ( "FOR curr={:?}" , curr) ;
529- if self . prev_starts_after_next ( & curr) {
594+ if self . some_prev . is_some ( ) && self . prev_starts_after_next ( & curr) {
530595 debug ! (
531596 " prev.span starts after curr.span, so curr will be dropped (skipping past \
532597 closure?); prev={:?}",
@@ -583,10 +648,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
583648 for mut dup in pending_dups. iter ( ) . cloned ( ) {
584649 dup. span = dup. span . with_hi ( left_cutoff) ;
585650 debug ! ( " ...and at least one pre_closure dup={:?}" , dup) ;
586- self . refined_spans . push ( dup) ;
651+ self . push_refined_span ( dup) ;
587652 }
588653 }
589- self . refined_spans . push ( pre_closure) ;
654+ self . push_refined_span ( pre_closure) ;
590655 }
591656 if has_post_closure_span {
592657 // Update prev.span to start after the closure (and discard curr)
@@ -597,7 +662,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
597662 }
598663 self . pending_dups . append ( & mut pending_dups) ;
599664 let closure_covspan = self . take_curr ( ) ;
600- self . refined_spans . push ( closure_covspan) ; // since self.prev() was already updated
665+ self . push_refined_span ( closure_covspan) ; // since self.prev() was already updated
601666 } else {
602667 pending_dups. clear ( ) ;
603668 }
@@ -688,7 +753,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
688753 } else {
689754 debug ! ( " ... adding modified prev={:?}" , self . prev( ) ) ;
690755 let prev = self . take_prev ( ) ;
691- self . refined_spans . push ( prev) ;
756+ self . push_refined_span ( prev) ;
692757 }
693758 } else {
694759 // with `pending_dups`, `prev` cannot have any statements that don't overlap
@@ -704,7 +769,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
704769pub ( super ) fn filtered_statement_span (
705770 statement : & ' a Statement < ' tcx > ,
706771 body_span : Span ,
707- ) -> Option < ( Span , bool ) > {
772+ ) -> Option < ( Span , Span ) > {
708773 match statement. kind {
709774 // These statements have spans that are often outside the scope of the executed source code
710775 // for their parent `BasicBlock`.
@@ -749,7 +814,7 @@ pub(super) fn filtered_statement_span(
749814pub ( super ) fn filtered_terminator_span (
750815 terminator : & ' a Terminator < ' tcx > ,
751816 body_span : Span ,
752- ) -> Option < ( Span , bool ) > {
817+ ) -> Option < ( Span , Span ) > {
753818 match terminator. kind {
754819 // These terminators have spans that don't positively contribute to computing a reasonable
755820 // span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -779,14 +844,10 @@ pub(super) fn filtered_terminator_span(
779844 }
780845}
781846
847+ /// Returns the span within the function source body, and the given span, which will be different
848+ /// if the given span is an expansion (macro, syntactic sugar, etc.).
782849#[ inline]
783- fn function_source_span ( span : Span , body_span : Span ) -> ( Span , bool ) {
784- let is_macro_expansion = span. ctxt ( ) != body_span. ctxt ( )
785- && if let ExpnKind :: Macro ( MacroKind :: Bang , _) = span. ctxt ( ) . outer_expn_data ( ) . kind {
786- true
787- } else {
788- false
789- } ;
790- let span = original_sp ( span, body_span) . with_ctxt ( body_span. ctxt ( ) ) ;
791- ( if body_span. contains ( span) { span } else { body_span } , is_macro_expansion)
850+ fn function_source_span ( span : Span , body_span : Span ) -> ( Span , Span ) {
851+ let original_span = original_sp ( span, body_span) . with_ctxt ( body_span. ctxt ( ) ) ;
852+ ( if body_span. contains ( original_span) { original_span } else { body_span } , span)
792853}
0 commit comments