@@ -8,7 +8,7 @@ mod spans;
88mod  tests; 
99
1010use  self :: counters:: { BcbCounter ,  CoverageCounters } ; 
11- use  self :: graph:: CoverageGraph ; 
11+ use  self :: graph:: { BasicCoverageBlock ,   CoverageGraph } ; 
1212use  self :: spans:: CoverageSpans ; 
1313
1414use  crate :: MirPass ; 
@@ -70,7 +70,6 @@ struct Instrumentor<'a, 'tcx> {
7070    mir_body :  & ' a  mut  mir:: Body < ' tcx > , 
7171    hir_info :  ExtractedHirInfo , 
7272    basic_coverage_blocks :  CoverageGraph , 
73-     coverage_counters :  CoverageCounters , 
7473} 
7574
7675impl < ' a ,  ' tcx >  Instrumentor < ' a ,  ' tcx >  { 
@@ -80,9 +79,8 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
8079        debug ! ( ?hir_info,  "instrumenting {:?}" ,  mir_body. source. def_id( ) ) ; 
8180
8281        let  basic_coverage_blocks = CoverageGraph :: from_mir ( mir_body) ; 
83-         let  coverage_counters = CoverageCounters :: new ( & basic_coverage_blocks) ; 
8482
85-         Self  {  tcx,  mir_body,  hir_info,  basic_coverage_blocks,  coverage_counters  } 
83+         Self  {  tcx,  mir_body,  hir_info,  basic_coverage_blocks } 
8684    } 
8785
8886    fn  inject_counters ( & ' a  mut  self )  { 
@@ -103,25 +101,31 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
103101        // and all `Expression` dependencies (operands) are also generated, for any other 
104102        // `BasicCoverageBlock`s not already associated with a coverage span. 
105103        let  bcb_has_coverage_spans = |bcb| coverage_spans. bcb_has_coverage_spans ( bcb) ; 
106-         self . coverage_counters 
107-             . make_bcb_counters ( & self . basic_coverage_blocks ,  bcb_has_coverage_spans) ; 
104+         let  coverage_counters = CoverageCounters :: make_bcb_counters ( 
105+             & self . basic_coverage_blocks , 
106+             bcb_has_coverage_spans, 
107+         ) ; 
108108
109-         let  mappings = self . create_mappings_and_inject_coverage_statements ( & coverage_spans) ; 
109+         let  mappings = self . create_mappings ( & coverage_spans,  & coverage_counters) ; 
110+         self . inject_coverage_statements ( bcb_has_coverage_spans,  & coverage_counters) ; 
110111
111112        self . mir_body . function_coverage_info  = Some ( Box :: new ( FunctionCoverageInfo  { 
112113            function_source_hash :  self . hir_info . function_source_hash , 
113-             num_counters :  self . coverage_counters . num_counters ( ) , 
114-             expressions :  self . coverage_counters . take_expressions ( ) , 
114+             num_counters :  coverage_counters. num_counters ( ) , 
115+             expressions :  coverage_counters. into_expressions ( ) , 
115116            mappings, 
116117        } ) ) ; 
117118    } 
118119
119-     /// For each [`BcbCounter`] associated with a BCB node or BCB edge, create 
120- /// any corresponding mappings (for BCB nodes only), and inject any necessary 
121- /// coverage statements into MIR. 
122- fn  create_mappings_and_inject_coverage_statements ( 
123-         & mut  self , 
120+     /// For each coverage span extracted from MIR, create a corresponding 
121+ /// mapping. 
122+ /// 
123+ /// Precondition: All BCBs corresponding to those spans have been given 
124+ /// coverage counters. 
125+ fn  create_mappings ( 
126+         & self , 
124127        coverage_spans :  & CoverageSpans , 
128+         coverage_counters :  & CoverageCounters , 
125129    )  -> Vec < Mapping >  { 
126130        let  source_map = self . tcx . sess . source_map ( ) ; 
127131        let  body_span = self . hir_info . body_span ; 
@@ -131,30 +135,42 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
131135        let  file_name =
132136            Symbol :: intern ( & source_file. name . for_codegen ( self . tcx . sess ) . to_string_lossy ( ) ) ; 
133137
134-         let  mut  mappings = Vec :: new ( ) ; 
135- 
136-         // Process the counters and spans associated with BCB nodes. 
137-         for  ( bcb,  counter_kind)  in  self . coverage_counters . bcb_node_counters ( )  { 
138-             let  spans = coverage_spans. spans_for_bcb ( bcb) ; 
139-             let  has_mappings = !spans. is_empty ( ) ; 
140- 
141-             // If this BCB has any coverage spans, add corresponding mappings to 
142-             // the mappings table. 
143-             if  has_mappings { 
144-                 let  term = counter_kind. as_term ( ) ; 
145-                 mappings. extend ( spans. iter ( ) . map ( |& span| { 
146-                     let  code_region = make_code_region ( source_map,  file_name,  span,  body_span) ; 
147-                     Mapping  {  code_region,  term } 
148-                 } ) ) ; 
149-             } 
138+         coverage_spans
139+             . bcbs_with_coverage_spans ( ) 
140+             // For each BCB with spans, get a coverage term for its counter. 
141+             . map ( |( bcb,  spans) | { 
142+                 let  term = coverage_counters
143+                     . bcb_counter ( bcb) 
144+                     . expect ( "all BCBs with spans were given counters" ) 
145+                     . as_term ( ) ; 
146+                 ( term,  spans) 
147+             } ) 
148+             // Flatten the spans into individual term/span pairs. 
149+             . flat_map ( |( term,  spans) | spans. iter ( ) . map ( move  |& span| ( term,  span) ) ) 
150+             // Convert each span to a code region, and create the final mapping. 
151+             . map ( |( term,  span) | { 
152+                 let  code_region = make_code_region ( source_map,  file_name,  span,  body_span) ; 
153+                 Mapping  {  term,  code_region } 
154+             } ) 
155+             . collect :: < Vec < _ > > ( ) 
156+     } 
150157
158+     /// For each BCB node or BCB edge that has an associated coverage counter, 
159+ /// inject any necessary coverage statements into MIR. 
160+ fn  inject_coverage_statements ( 
161+         & mut  self , 
162+         bcb_has_coverage_spans :  impl  Fn ( BasicCoverageBlock )  -> bool , 
163+         coverage_counters :  & CoverageCounters , 
164+     )  { 
165+         // Process the counters associated with BCB nodes. 
166+         for  ( bcb,  counter_kind)  in  coverage_counters. bcb_node_counters ( )  { 
151167            let  do_inject = match  counter_kind { 
152168                // Counter-increment statements always need to be injected. 
153169                BcbCounter :: Counter  {  .. }  => true , 
154170                // The only purpose of expression-used statements is to detect 
155171                // when a mapping is unreachable, so we only inject them for 
156172                // expressions with one or more mappings. 
157-                 BcbCounter :: Expression  {  .. }  => has_mappings , 
173+                 BcbCounter :: Expression  {  .. }  => bcb_has_coverage_spans ( bcb ) , 
158174            } ; 
159175            if  do_inject { 
160176                inject_statement ( 
@@ -166,7 +182,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
166182        } 
167183
168184        // Process the counters associated with BCB edges. 
169-         for  ( from_bcb,  to_bcb,  counter_kind)  in  self . coverage_counters . bcb_edge_counters ( )  { 
185+         for  ( from_bcb,  to_bcb,  counter_kind)  in  coverage_counters. bcb_edge_counters ( )  { 
170186            let  do_inject = match  counter_kind { 
171187                // Counter-increment statements always need to be injected. 
172188                BcbCounter :: Counter  {  .. }  => true , 
@@ -192,8 +208,6 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
192208            // Inject a counter into the newly-created BB. 
193209            inject_statement ( self . mir_body ,  self . make_mir_coverage_kind ( counter_kind) ,  new_bb) ; 
194210        } 
195- 
196-         mappings
197211    } 
198212
199213    fn  make_mir_coverage_kind ( & self ,  counter_kind :  & BcbCounter )  -> CoverageKind  { 
0 commit comments