@@ -11,7 +11,7 @@ use rustc_middle::mir::{
11
11
use rustc_middle:: ty:: TyCtxt ;
12
12
13
13
use rustc_span:: source_map:: original_sp;
14
- use rustc_span:: { BytePos , Span } ;
14
+ use rustc_span:: { BytePos , ExpnKind , MacroKind , Span } ;
15
15
16
16
use std:: cmp:: Ordering ;
17
17
@@ -67,19 +67,30 @@ impl CoverageStatement {
67
67
#[ derive( Debug , Clone ) ]
68
68
pub ( super ) struct CoverageSpan {
69
69
pub span : Span ,
70
+ pub is_macro_expansion : bool ,
70
71
pub bcb : BasicCoverageBlock ,
71
72
pub coverage_statements : Vec < CoverageStatement > ,
72
73
pub is_closure : bool ,
73
74
}
74
75
75
76
impl CoverageSpan {
76
77
pub fn for_fn_sig ( fn_sig_span : Span ) -> Self {
77
- Self { span : fn_sig_span, bcb : START_BCB , coverage_statements : vec ! [ ] , is_closure : false }
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 ;
81
+ Self {
82
+ span : fn_sig_span,
83
+ is_macro_expansion,
84
+ bcb : START_BCB ,
85
+ coverage_statements : vec ! [ ] ,
86
+ is_closure : false ,
87
+ }
78
88
}
79
89
80
90
pub fn for_statement (
81
91
statement : & Statement < ' tcx > ,
82
92
span : Span ,
93
+ is_macro_expansion : bool ,
83
94
bcb : BasicCoverageBlock ,
84
95
bb : BasicBlock ,
85
96
stmt_index : usize ,
@@ -94,15 +105,22 @@ impl CoverageSpan {
94
105
95
106
Self {
96
107
span,
108
+ is_macro_expansion,
97
109
bcb,
98
110
coverage_statements : vec ! [ CoverageStatement :: Statement ( bb, span, stmt_index) ] ,
99
111
is_closure,
100
112
}
101
113
}
102
114
103
- pub fn for_terminator ( span : Span , bcb : BasicCoverageBlock , bb : BasicBlock ) -> Self {
115
+ pub fn for_terminator (
116
+ span : Span ,
117
+ is_macro_expansion : bool ,
118
+ bcb : BasicCoverageBlock ,
119
+ bb : BasicBlock ,
120
+ ) -> Self {
104
121
Self {
105
122
span,
123
+ is_macro_expansion,
106
124
bcb,
107
125
coverage_statements : vec ! [ CoverageStatement :: Terminator ( bb, span) ] ,
108
126
is_closure : false ,
@@ -344,7 +362,27 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
344
362
} else if self . prev_original_span == self . curr ( ) . span {
345
363
// Note that this compares the new span to `prev_original_span`, which may not
346
364
// be the full `prev.span` (if merged during the previous iteration).
347
- self . hold_pending_dups_unless_dominated ( ) ;
365
+ if self . prev ( ) . is_macro_expansion && self . curr ( ) . is_macro_expansion {
366
+ // Macros that expand to include branching (such as
367
+ // `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
368
+ // `trace!()) typically generate callee spans with identical
369
+ // ranges (typically the full span of the macro) for all
370
+ // `BasicBlocks`. This makes it impossible to distinguish
371
+ // the condition (`if val1 != val2`) from the optional
372
+ // branched statements (such as the call to `panic!()` on
373
+ // assert failure). In this case it is better (or less
374
+ // worse) to drop the optional branch bcbs and keep the
375
+ // non-conditional statements, to count when reached.
376
+ debug ! (
377
+ " curr and prev are part of a macro expansion, and curr has the same span \
378
+ as prev, but is in a different bcb. Drop curr and keep prev for next iter. \
379
+ prev={:?}",
380
+ self . prev( )
381
+ ) ;
382
+ self . take_curr ( ) ;
383
+ } else {
384
+ self . hold_pending_dups_unless_dominated ( ) ;
385
+ }
348
386
} else {
349
387
self . cutoff_prev_at_overlapping_curr ( ) ;
350
388
}
@@ -401,14 +439,24 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
401
439
. iter ( )
402
440
. enumerate ( )
403
441
. filter_map ( move |( index, statement) | {
404
- filtered_statement_span ( statement, self . body_span ) . map ( |span| {
405
- CoverageSpan :: for_statement ( statement, span, bcb, bb, index)
406
- } )
442
+ filtered_statement_span ( statement, self . body_span ) . map (
443
+ |( span, is_macro_expansion) | {
444
+ CoverageSpan :: for_statement (
445
+ statement,
446
+ span,
447
+ is_macro_expansion,
448
+ bcb,
449
+ bb,
450
+ index,
451
+ )
452
+ } ,
453
+ )
407
454
} )
408
- . chain (
409
- filtered_terminator_span ( data. terminator ( ) , self . body_span )
410
- . map ( |span| CoverageSpan :: for_terminator ( span, bcb, bb) ) ,
411
- )
455
+ . 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
+ } ,
459
+ ) )
412
460
} )
413
461
. collect ( )
414
462
}
@@ -656,7 +704,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
656
704
pub ( super ) fn filtered_statement_span (
657
705
statement : & ' a Statement < ' tcx > ,
658
706
body_span : Span ,
659
- ) -> Option < Span > {
707
+ ) -> Option < ( Span , bool ) > {
660
708
match statement. kind {
661
709
// These statements have spans that are often outside the scope of the executed source code
662
710
// for their parent `BasicBlock`.
@@ -701,7 +749,7 @@ pub(super) fn filtered_statement_span(
701
749
pub ( super ) fn filtered_terminator_span (
702
750
terminator : & ' a Terminator < ' tcx > ,
703
751
body_span : Span ,
704
- ) -> Option < Span > {
752
+ ) -> Option < ( Span , bool ) > {
705
753
match terminator. kind {
706
754
// These terminators have spans that don't positively contribute to computing a reasonable
707
755
// span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -742,7 +790,13 @@ pub(super) fn filtered_terminator_span(
742
790
}
743
791
744
792
#[ inline]
745
- fn function_source_span ( span : Span , body_span : Span ) -> Span {
793
+ fn function_source_span ( span : Span , body_span : Span ) -> ( Span , bool ) {
794
+ let is_macro_expansion = span. ctxt ( ) != body_span. ctxt ( )
795
+ && if let ExpnKind :: Macro ( MacroKind :: Bang , _) = span. ctxt ( ) . outer_expn_data ( ) . kind {
796
+ true
797
+ } else {
798
+ false
799
+ } ;
746
800
let span = original_sp ( span, body_span) . with_ctxt ( body_span. ctxt ( ) ) ;
747
- if body_span. contains ( span) { span } else { body_span }
801
+ ( if body_span. contains ( span) { span } else { body_span } , is_macro_expansion )
748
802
}
0 commit comments