@@ -381,7 +381,7 @@ impl BasicCoverageBlocks {
381381 let successors = IndexVec :: from_fn_n (
382382 |bcb| {
383383 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 )
385385// TODO(richkadel):
386386// MAKE SURE WE ONLY RETURN THE SAME SUCCESSORS USED WHEN CREATING THE BCB (THE FIRST SUCCESSOR ONLY,
387387// UNLESS ITS A SWITCHINT).)
@@ -425,7 +425,7 @@ impl BasicCoverageBlocks {
425425 // each block terminator's `successors()`. Coverage spans must map to actual source code,
426426 // so compiler generated blocks and paths can be ignored. To that end, the CFG traversal
427427 // 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) ;
429429
430430 let mut basic_blocks = Vec :: new ( ) ;
431431 for ( bb, data) in mir_cfg_without_unwind {
@@ -1078,7 +1078,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
10781078 if let Some ( bcb_to_coverage_spans_with_counters) = debug_bcb_to_coverage_spans_with_counters. as_mut ( ) {
10791079 bcb_to_coverage_spans_with_counters. entry ( bcb) . or_insert_with ( || Vec :: new ( ) ) . push ( ( covspan. clone ( ) , counter_kind. clone ( ) ) ) ;
10801080 }
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 ( ) ) ;
10821092 }
10831093
10841094 // The previous step looped through the `CoverageSpan`s and injected the counter from the
@@ -1218,7 +1228,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
12181228 } ;
12191229 let edge_labels = |from_bcb| {
12201230 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" ) ;
12221233 let edge_counters = from_terminator. successors ( ) . map ( |& successor| {
12231234 edge_to_counter. get ( & ( from_bcb, successor) )
12241235 } ) ;
@@ -2663,34 +2674,34 @@ fn hash(
26632674 stable_hasher. finish ( )
26642675}
26652676
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 > {
26672678 let mut successors = term_kind. successors ( ) ;
2668- match & term_kind {
2679+ box match & term_kind {
26692680 // SwitchInt successors are never unwind, and all of them should be traversed.
26702681 TerminatorKind :: SwitchInt { .. } => successors,
26712682 // For all other kinds, return only the first successor, if any, and ignore unwinds.
26722683 // NOTE: `chain(&[])` is required to coerce the `option::iter` (from
26732684 // `next().into_iter()`) into the `mir::Successors` aliased type.
26742685 _ => successors. next ( ) . into_iter ( ) . chain ( & [ ] ) ,
2675- }
2686+ } . filter ( move | & & successor| body [ successor ] . terminator ( ) . kind != TerminatorKind :: Unreachable )
26762687}
26772688
26782689pub struct ShortCircuitPreorder <
26792690 ' a ,
26802691 ' 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 > ,
26822693> {
2683- body : & ' a mir:: Body < ' tcx > ,
2694+ body : & ' tcx & ' a mir:: Body < ' tcx > ,
26842695 visited : BitSet < BasicBlock > ,
26852696 worklist : Vec < BasicBlock > ,
26862697 filtered_successors : F ,
26872698}
26882699
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 > >
26902701 ShortCircuitPreorder < ' a , ' tcx , F >
26912702{
26922703 pub fn new (
2693- body : & ' a mir:: Body < ' tcx > ,
2704+ body : & ' tcx & ' a mir:: Body < ' tcx > ,
26942705 filtered_successors : F ,
26952706 ) -> ShortCircuitPreorder < ' a , ' tcx , F > {
26962707 let worklist = vec ! [ mir:: START_BLOCK ] ;
@@ -2704,7 +2715,7 @@ impl<'a, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
27042715 }
27052716}
27062717
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
27082719 for ShortCircuitPreorder < ' a , ' tcx , F >
27092720{
27102721 type Item = ( BasicBlock , & ' a BasicBlockData < ' tcx > ) ;
@@ -2718,7 +2729,7 @@ impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
27182729 let data = & self . body [ idx] ;
27192730
27202731 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 ) ) ;
27222733 }
27232734
27242735 return Some ( ( idx, data) ) ;
@@ -2733,49 +2744,10 @@ impl<'a: 'tcx, 'tcx, F: Fn(&'tcx TerminatorKind<'tcx>) -> mir::Successors<'tcx>>
27332744 }
27342745}
27352746
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.
27782752//
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