@@ -381,7 +381,7 @@ impl BasicCoverageBlocks {
381
381
let successors = IndexVec :: from_fn_n (
382
382
|bcb| {
383
383
let bcb_data = & bcbs[ bcb] ;
384
- let bcb_successors = bcb_filtered_successors ( & bcb_data. terminator ( mir_body) . kind )
384
+ let bcb_successors = bcb_filtered_successors ( & mir_body , & bcb_data. terminator ( mir_body) . kind )
385
385
// TODO(richkadel):
386
386
// MAKE SURE WE ONLY RETURN THE SAME SUCCESSORS USED WHEN CREATING THE BCB (THE FIRST SUCCESSOR ONLY,
387
387
// UNLESS ITS A SWITCHINT).)
@@ -425,7 +425,7 @@ impl BasicCoverageBlocks {
425
425
// each block terminator's `successors()`. Coverage spans must map to actual source code,
426
426
// so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
427
427
// intentionally omits unwind paths.
428
- let mir_cfg_without_unwind = ShortCircuitPreorder :: new ( mir_body, bcb_filtered_successors) ;
428
+ let mir_cfg_without_unwind = ShortCircuitPreorder :: new ( & mir_body, bcb_filtered_successors) ;
429
429
430
430
let mut basic_blocks = Vec :: new ( ) ;
431
431
for ( bb, data) in mir_cfg_without_unwind {
@@ -1078,7 +1078,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1078
1078
if let Some ( bcb_to_coverage_spans_with_counters) = debug_bcb_to_coverage_spans_with_counters. as_mut ( ) {
1079
1079
bcb_to_coverage_spans_with_counters. entry ( bcb) . or_insert_with ( || Vec :: new ( ) ) . push ( ( covspan. clone ( ) , counter_kind. clone ( ) ) ) ;
1080
1080
}
1081
- self . inject_statement ( counter_kind, self . bcb_last_bb ( bcb) , make_code_region ( file_name, & source_file, span, body_span) ) ;
1081
+ let mut code_region = None ;
1082
+ if span. hi ( ) == body_span. hi ( ) {
1083
+ // TODO(richkadel): add a comment if this works
1084
+ if let TerminatorKind :: Goto { .. } = self . bcb_terminator ( bcb) . kind {
1085
+ code_region = Some ( make_non_reportable_code_region ( file_name, & source_file, span) ) ;
1086
+ }
1087
+ }
1088
+ if code_region. is_none ( ) {
1089
+ code_region = Some ( make_code_region ( file_name, & source_file, span, body_span) ) ;
1090
+ } ;
1091
+ self . inject_statement ( counter_kind, self . bcb_last_bb ( bcb) , code_region. unwrap ( ) ) ;
1082
1092
}
1083
1093
1084
1094
// The previous step looped through the `CoverageSpan`s and injected the counter from the
@@ -1218,7 +1228,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
1218
1228
} ;
1219
1229
let edge_labels = |from_bcb| {
1220
1230
let from_terminator = self . bcb_terminator ( from_bcb) ;
1221
- let edge_labels = from_terminator. kind . fmt_successor_labels ( ) ;
1231
+ let mut edge_labels = from_terminator. kind . fmt_successor_labels ( ) ;
1232
+ edge_labels. retain ( |label| label. to_string ( ) != "unreachable" ) ;
1222
1233
let edge_counters = from_terminator. successors ( ) . map ( |& successor| {
1223
1234
edge_to_counter. get ( & ( from_bcb, successor) )
1224
1235
} ) ;
@@ -2663,34 +2674,34 @@ fn hash(
2663
2674
stable_hasher. finish ( )
2664
2675
}
2665
2676
2666
- fn bcb_filtered_successors < ' tcx > ( term_kind : & ' tcx TerminatorKind < ' tcx > ) -> mir :: Successors < ' tcx > {
2677
+ fn bcb_filtered_successors < ' a , ' tcx > ( body : & ' tcx & ' a mir :: Body < ' tcx > , term_kind : & ' tcx TerminatorKind < ' tcx > ) -> Box < dyn Iterator < Item = & ' a BasicBlock > + ' a > {
2667
2678
let mut successors = term_kind. successors ( ) ;
2668
- match & term_kind {
2679
+ box match & term_kind {
2669
2680
// SwitchInt successors are never unwind, and all of them should be traversed.
2670
2681
TerminatorKind :: SwitchInt { .. } => successors,
2671
2682
// For all other kinds, return only the first successor, if any, and ignore unwinds.
2672
2683
// NOTE: `chain(&[])` is required to coerce the `option::iter` (from
2673
2684
// `next().into_iter()`) into the `mir::Successors` aliased type.
2674
2685
_ => successors. next ( ) . into_iter ( ) . chain ( & [ ] ) ,
2675
- }
2686
+ } . filter ( move | & & successor| body [ successor ] . terminator ( ) . kind != TerminatorKind :: Unreachable )
2676
2687
}
2677
2688
2678
2689
pub struct ShortCircuitPreorder <
2679
2690
' a ,
2680
2691
' tcx ,
2681
- F : Fn ( & ' tcx TerminatorKind < ' tcx > ) -> mir :: Successors < ' tcx > ,
2692
+ F : Fn ( & ' tcx & ' a mir :: Body < ' tcx > , & ' tcx TerminatorKind < ' tcx > ) -> Box < dyn Iterator < Item = & ' a BasicBlock > + ' a > ,
2682
2693
> {
2683
- body : & ' a mir:: Body < ' tcx > ,
2694
+ body : & ' tcx & ' a mir:: Body < ' tcx > ,
2684
2695
visited : BitSet < BasicBlock > ,
2685
2696
worklist : Vec < BasicBlock > ,
2686
2697
filtered_successors : F ,
2687
2698
}
2688
2699
2689
- impl < ' a , ' tcx , F : Fn ( & ' tcx TerminatorKind < ' tcx > ) -> mir :: Successors < ' tcx > >
2700
+ impl < ' a , ' tcx , F : Fn ( & ' tcx & ' a mir :: Body < ' tcx > , & ' tcx TerminatorKind < ' tcx > ) -> Box < dyn Iterator < Item = & ' a BasicBlock > + ' a > >
2690
2701
ShortCircuitPreorder < ' a , ' tcx , F >
2691
2702
{
2692
2703
pub fn new (
2693
- body : & ' a mir:: Body < ' tcx > ,
2704
+ body : & ' tcx & ' a mir:: Body < ' tcx > ,
2694
2705
filtered_successors : F ,
2695
2706
) -> ShortCircuitPreorder < ' a , ' tcx , F > {
2696
2707
let worklist = vec ! [ mir:: START_BLOCK ] ;
@@ -2704,7 +2715,7 @@ impl<'a, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
2704
2715
}
2705
2716
}
2706
2717
2707
- impl < ' a : ' tcx , ' tcx , F : Fn ( & ' tcx TerminatorKind < ' tcx > ) -> mir :: Successors < ' tcx > > Iterator
2718
+ impl < ' a : ' tcx , ' tcx , F : Fn ( & ' tcx & ' a mir :: Body < ' tcx > , & ' tcx TerminatorKind < ' tcx > ) -> Box < dyn Iterator < Item = & ' a BasicBlock > + ' a > > Iterator
2708
2719
for ShortCircuitPreorder < ' a , ' tcx , F >
2709
2720
{
2710
2721
type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
@@ -2718,7 +2729,7 @@ impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
2718
2729
let data = & self . body [ idx] ;
2719
2730
2720
2731
if let Some ( ref term) = data. terminator {
2721
- self . worklist . extend ( ( self . filtered_successors ) ( & term. kind ) ) ;
2732
+ self . worklist . extend ( ( self . filtered_successors ) ( & self . body , & term. kind ) ) ;
2722
2733
}
2723
2734
2724
2735
return Some ( ( idx, data) ) ;
@@ -2733,49 +2744,10 @@ impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
2733
2744
}
2734
2745
}
2735
2746
2736
- // NOTE: Regarding past efforts and revelations when trying to identify `Unreachable` coverage spans
2737
- // from the MIR:
2738
- //
2739
- // TerminatorKind::FalseEdge targets from SwitchInt don't appear to be helpful in identifying
2740
- // unreachable code. I did test the theory, but the following changes were not beneficial. (I
2741
- // assumed that replacing some constants with non-deterministic variables might effect which blocks
2742
- // were targeted by a `FalseEdge` `imaginary_target`. It did not.)
2743
- //
2744
- // Also note that, if there is a way to identify BasicBlocks that are part of the MIR CFG, but not
2745
- // actually reachable, here are some other things to consider:
2746
- //
2747
- // Injecting unreachable code regions will probably require computing the set difference between the
2748
- // basic blocks found without filtering out unreachable blocks, and the basic blocks found with a
2749
- // filter (similar to or as an extension of the `filter_unwind_paths` filter); then computing the
2750
- // `CoverageSpans` without the filter; and then injecting `Counter`s or `Expression`s for
2751
- // blocks that are not unreachable, or injecting `Unreachable` code regions otherwise. This seems
2752
- // straightforward, but not trivial.
2753
- //
2754
- // Alternatively, we might instead want to leave the unreachable blocks in (bypass the filter here),
2755
- // and inject the counters. This will result in counter values of zero (0) for unreachable code
2756
- // (and, notably, the code will be displayed with a red background by `llvm-cov show`).
2757
- //
2758
- // ```rust
2759
- // TerminatorKind::SwitchInt { .. } => {
2760
- // let some_imaginary_target = successors.clone().find_map(|&successor| {
2761
- // let term = mir_body[successor].terminator();
2762
- // if let TerminatorKind::FalseEdge { imaginary_target, .. } = term.kind {
2763
- // if mir_body.predecessors()[imaginary_target].len() == 1 {
2764
- // return Some(imaginary_target);
2765
- // }
2766
- // }
2767
- // None
2768
- // });
2769
- // if let Some(imaginary_target) = some_imaginary_target {
2770
- // box successors.filter(move |&&successor| successor != imaginary_target)
2771
- // } else {
2772
- // box successors
2773
- // }
2774
- // }
2775
- // ```
2776
- //
2777
- // Note this also required changing the closure signature for the `ShortCurcuitPreorder` to:
2747
+ // TODO(richkadel): try_error_result.rs
2748
+ // When executing the Result as Try>::from_error() returns to one or more
2749
+ // Goto that then targets Return.
2750
+ // Both the Goto (after error) and the Return have coverage at the last
2751
+ // bytepos, 0-length Span.
2778
2752
//
2779
- // ```rust
2780
- // F: Fn(&'tcx TerminatorKind<'tcx>) -> Box<dyn Iterator<Item = &BasicBlock> + 'a>,
2781
- // ```
2753
+ // How should I eliminate one, and which one, to avoid counting both.
0 commit comments