@@ -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 , ExpnKind , MacroKind , Span } ;
14
+ use rustc_span:: { BytePos , ExpnKind , MacroKind , Span , Symbol } ;
15
15
16
16
use std:: cmp:: Ordering ;
17
17
@@ -67,20 +67,17 @@ 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
+ pub expn_span : Span ,
71
71
pub bcb : BasicCoverageBlock ,
72
72
pub coverage_statements : Vec < CoverageStatement > ,
73
73
pub is_closure : bool ,
74
74
}
75
75
76
76
impl CoverageSpan {
77
77
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 ;
81
78
Self {
82
79
span : fn_sig_span,
83
- is_macro_expansion ,
80
+ expn_span : fn_sig_span ,
84
81
bcb : START_BCB ,
85
82
coverage_statements : vec ! [ ] ,
86
83
is_closure : false ,
@@ -90,7 +87,7 @@ impl CoverageSpan {
90
87
pub fn for_statement (
91
88
statement : & Statement < ' tcx > ,
92
89
span : Span ,
93
- is_macro_expansion : bool ,
90
+ expn_span : Span ,
94
91
bcb : BasicCoverageBlock ,
95
92
bb : BasicBlock ,
96
93
stmt_index : usize ,
@@ -105,7 +102,7 @@ impl CoverageSpan {
105
102
106
103
Self {
107
104
span,
108
- is_macro_expansion ,
105
+ expn_span ,
109
106
bcb,
110
107
coverage_statements : vec ! [ CoverageStatement :: Statement ( bb, span, stmt_index) ] ,
111
108
is_closure,
@@ -114,13 +111,13 @@ impl CoverageSpan {
114
111
115
112
pub fn for_terminator (
116
113
span : Span ,
117
- is_macro_expansion : bool ,
114
+ expn_span : Span ,
118
115
bcb : BasicCoverageBlock ,
119
116
bb : BasicBlock ,
120
117
) -> Self {
121
118
Self {
122
119
span,
123
- is_macro_expansion ,
120
+ expn_span ,
124
121
bcb,
125
122
coverage_statements : vec ! [ CoverageStatement :: Terminator ( bb, span) ] ,
126
123
is_closure : false ,
@@ -176,6 +173,34 @@ impl CoverageSpan {
176
173
. collect :: < Vec < _ > > ( )
177
174
. join ( "\n " )
178
175
}
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
+ }
179
204
}
180
205
181
206
/// Converts the initial set of `CoverageSpan`s (one per MIR `Statement` or `Terminator`) into a
@@ -219,6 +244,9 @@ pub struct CoverageSpans<'a, 'tcx> {
219
244
/// Assigned from `curr_original_span` from the previous iteration.
220
245
prev_original_span : Span ,
221
246
247
+ /// A copy of the expn_span from the prior iteration.
248
+ prev_expn_span : Option < Span > ,
249
+
222
250
/// One or more `CoverageSpan`s with the same `Span` but different `BasicCoverageBlock`s, and
223
251
/// no `BasicCoverageBlock` in this list dominates another `BasicCoverageBlock` in the list.
224
252
/// 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> {
273
301
curr_original_span : Span :: with_root_ctxt ( BytePos ( 0 ) , BytePos ( 0 ) ) ,
274
302
some_prev : None ,
275
303
prev_original_span : Span :: with_root_ctxt ( BytePos ( 0 ) , BytePos ( 0 ) ) ,
304
+ prev_expn_span : None ,
276
305
pending_dups : Vec :: new ( ) ,
277
306
} ;
278
307
279
308
let sorted_spans = coverage_spans. mir_to_initial_sorted_coverage_spans ( ) ;
280
309
281
310
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 ;
285
311
286
312
coverage_spans. to_refined_spans ( )
287
313
}
@@ -335,10 +361,14 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
335
361
/// de-duplicated `CoverageSpan`s.
336
362
fn to_refined_spans ( mut self ) -> Vec < CoverageSpan > {
337
363
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 ( ) ) {
339
368
debug ! ( " same bcb (and neither is a closure), merge with prev={:?}" , self . prev( ) ) ;
340
369
let prev = self . take_prev ( ) ;
341
370
self . curr_mut ( ) . merge_from ( prev) ;
371
+ self . check_invoked_macro_name_span ( ) ;
342
372
// Note that curr.span may now differ from curr_original_span
343
373
} else if self . prev_ends_before_curr ( ) {
344
374
debug ! (
@@ -347,7 +377,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
347
377
self . prev( )
348
378
) ;
349
379
let prev = self . take_prev ( ) ;
350
- self . refined_spans . push ( prev) ;
380
+ self . push_refined_span ( prev) ;
381
+ self . check_invoked_macro_name_span ( ) ;
351
382
} else if self . prev ( ) . is_closure {
352
383
// drop any equal or overlapping span (`curr`) and keep `prev` to test again in the
353
384
// next iter
@@ -362,7 +393,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
362
393
} else if self . prev_original_span == self . curr ( ) . span {
363
394
// Note that this compares the new span to `prev_original_span`, which may not
364
395
// 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 ( ) {
366
397
// Macros that expand to include branching (such as
367
398
// `assert_eq!()`, `assert_ne!()`, `info!()`, `debug!()`, or
368
399
// `trace!()) typically generate callee spans with identical
@@ -385,15 +416,16 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
385
416
}
386
417
} else {
387
418
self . cutoff_prev_at_overlapping_curr ( ) ;
419
+ self . check_invoked_macro_name_span ( ) ;
388
420
}
389
421
}
390
422
391
423
debug ! ( " AT END, adding last prev={:?}" , self . prev( ) ) ;
392
424
let prev = self . take_prev ( ) ;
393
- let CoverageSpans { pending_dups, mut refined_spans , .. } = self ;
425
+ let pending_dups = self . pending_dups . split_off ( 0 ) ;
394
426
for dup in pending_dups {
395
427
debug ! ( " ...adding at least one pending dup={:?}" , dup) ;
396
- refined_spans . push ( dup) ;
428
+ self . push_refined_span ( dup) ;
397
429
}
398
430
399
431
// Async functions wrap a closure that implements the body to be executed. The enclosing
@@ -403,21 +435,60 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
403
435
// excluded. The closure's `Return` is the only one that will be counted. This provides
404
436
// adequate coverage, and more intuitive counts. (Avoids double-counting the closing brace
405
437
// 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 ( ) {
407
439
last_covspan. is_closure && last_covspan. span . hi ( ) == self . body_span . hi ( )
408
440
} else {
409
441
false
410
442
} ;
411
443
412
444
if !body_ends_with_closure {
413
- refined_spans . push ( prev) ;
445
+ self . push_refined_span ( prev) ;
414
446
}
415
447
416
448
// Remove `CoverageSpan`s derived from closures, originally added to ensure the coverage
417
449
// regions for the current function leave room for the closure's own coverage regions
418
450
// (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
+ }
421
492
}
422
493
423
494
// 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> {
440
511
. enumerate ( )
441
512
. filter_map ( move |( index, statement) | {
442
513
filtered_statement_span ( statement, self . body_span ) . map (
443
- |( span, is_macro_expansion ) | {
514
+ |( span, expn_span ) | {
444
515
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,
451
517
)
452
518
} ,
453
519
)
454
520
} )
455
521
. 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) ,
459
523
) )
460
524
} )
461
525
. collect ( )
@@ -509,7 +573,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
509
573
let pending_dups = self . pending_dups . split_off ( 0 ) ;
510
574
for dup in pending_dups. into_iter ( ) {
511
575
debug ! ( " ...adding at least one pending={:?}" , dup) ;
512
- self . refined_spans . push ( dup) ;
576
+ self . push_refined_span ( dup) ;
513
577
}
514
578
} else {
515
579
self . pending_dups . clear ( ) ;
@@ -521,12 +585,13 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
521
585
/// Advance `prev` to `curr` (if any), and `curr` to the next `CoverageSpan` in sorted order.
522
586
fn next_coverage_span ( & mut self ) -> bool {
523
587
if let Some ( curr) = self . some_curr . take ( ) {
588
+ self . prev_expn_span = Some ( curr. expn_span ) ;
524
589
self . some_prev = Some ( curr) ;
525
590
self . prev_original_span = self . curr_original_span ;
526
591
}
527
592
while let Some ( curr) = self . sorted_spans_iter . as_mut ( ) . unwrap ( ) . next ( ) {
528
593
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) {
530
595
debug ! (
531
596
" prev.span starts after curr.span, so curr will be dropped (skipping past \
532
597
closure?); prev={:?}",
@@ -583,10 +648,10 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
583
648
for mut dup in pending_dups. iter ( ) . cloned ( ) {
584
649
dup. span = dup. span . with_hi ( left_cutoff) ;
585
650
debug ! ( " ...and at least one pre_closure dup={:?}" , dup) ;
586
- self . refined_spans . push ( dup) ;
651
+ self . push_refined_span ( dup) ;
587
652
}
588
653
}
589
- self . refined_spans . push ( pre_closure) ;
654
+ self . push_refined_span ( pre_closure) ;
590
655
}
591
656
if has_post_closure_span {
592
657
// Update prev.span to start after the closure (and discard curr)
@@ -597,7 +662,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
597
662
}
598
663
self . pending_dups . append ( & mut pending_dups) ;
599
664
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
601
666
} else {
602
667
pending_dups. clear ( ) ;
603
668
}
@@ -688,7 +753,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
688
753
} else {
689
754
debug ! ( " ... adding modified prev={:?}" , self . prev( ) ) ;
690
755
let prev = self . take_prev ( ) ;
691
- self . refined_spans . push ( prev) ;
756
+ self . push_refined_span ( prev) ;
692
757
}
693
758
} else {
694
759
// with `pending_dups`, `prev` cannot have any statements that don't overlap
@@ -704,7 +769,7 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
704
769
pub ( super ) fn filtered_statement_span (
705
770
statement : & ' a Statement < ' tcx > ,
706
771
body_span : Span ,
707
- ) -> Option < ( Span , bool ) > {
772
+ ) -> Option < ( Span , Span ) > {
708
773
match statement. kind {
709
774
// These statements have spans that are often outside the scope of the executed source code
710
775
// for their parent `BasicBlock`.
@@ -749,7 +814,7 @@ pub(super) fn filtered_statement_span(
749
814
pub ( super ) fn filtered_terminator_span (
750
815
terminator : & ' a Terminator < ' tcx > ,
751
816
body_span : Span ,
752
- ) -> Option < ( Span , bool ) > {
817
+ ) -> Option < ( Span , Span ) > {
753
818
match terminator. kind {
754
819
// These terminators have spans that don't positively contribute to computing a reasonable
755
820
// span of actually executed source code. (For example, SwitchInt terminators extracted from
@@ -789,14 +854,10 @@ pub(super) fn filtered_terminator_span(
789
854
}
790
855
}
791
856
857
+ /// Returns the span within the function source body, and the given span, which will be different
858
+ /// if the given span is an expansion (macro, syntactic sugar, etc.).
792
859
#[ inline]
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
- } ;
800
- let span = original_sp ( span, body_span) . with_ctxt ( body_span. ctxt ( ) ) ;
801
- ( if body_span. contains ( span) { span } else { body_span } , is_macro_expansion)
860
+ fn function_source_span ( span : Span , body_span : Span ) -> ( Span , Span ) {
861
+ let original_span = original_sp ( span, body_span) . with_ctxt ( body_span. ctxt ( ) ) ;
862
+ ( if body_span. contains ( original_span) { original_span } else { body_span } , span)
802
863
}
0 commit comments