@@ -107,6 +107,9 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
107
107
. make_bcb_counters ( & self . basic_coverage_blocks , bcb_has_coverage_spans) ;
108
108
109
109
let mappings = self . create_mappings_and_inject_coverage_statements ( & coverage_spans) ;
110
+ if mappings. is_empty ( ) {
111
+ return ;
112
+ }
110
113
111
114
self . mir_body . function_coverage_info = Some ( Box :: new ( FunctionCoverageInfo {
112
115
function_source_hash : self . hir_info . function_source_hash ,
@@ -135,18 +138,24 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
135
138
136
139
// Process the counters and spans associated with BCB nodes.
137
140
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
141
// If this BCB has any coverage spans, add corresponding mappings to
142
142
// the mappings table.
143
- if has_mappings {
143
+ let has_mappings = {
144
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 }
145
+ let old_mappings_len = mappings. len ( ) ;
146
+
147
+ mappings. extend ( coverage_spans. spans_for_bcb ( bcb) . iter ( ) . filter_map ( |& span| {
148
+ let Some ( code_region) =
149
+ make_code_region ( source_map, file_name, span, body_span)
150
+ else {
151
+ debug ! ( ?span, "Couldn't convert span to code region" ) ;
152
+ return None ;
153
+ } ;
154
+ Some ( Mapping { code_region, term } )
148
155
} ) ) ;
149
- }
156
+
157
+ mappings. len ( ) > old_mappings_len
158
+ } ;
150
159
151
160
let do_inject = match counter_kind {
152
161
// Counter-increment statements always need to be injected.
@@ -238,13 +247,19 @@ fn inject_statement(mir_body: &mut mir::Body<'_>, counter_kind: CoverageKind, bb
238
247
data. statements . insert ( 0 , statement) ;
239
248
}
240
249
241
- /// Convert the Span into its file name, start line and column, and end line and column
250
+ /// Convert the Span into its file name, start line and column, and end line and column.
251
+ ///
252
+ /// Returns `None` if the conversion failed for some reason. There is no known example
253
+ /// of code that would cause this to happen, but it's hard to rule out entirely
254
+ /// (especially in the presence of complex macros or other expansions), and if it does
255
+ /// happen then skipping a span or function is better than an ICE that the user might
256
+ /// have no way to avoid.
242
257
fn make_code_region (
243
258
source_map : & SourceMap ,
244
259
file_name : Symbol ,
245
260
span : Span ,
246
261
body_span : Span ,
247
- ) -> CodeRegion {
262
+ ) -> Option < CodeRegion > {
248
263
debug ! (
249
264
"Called make_code_region(file_name={}, span={}, body_span={})" ,
250
265
file_name,
@@ -266,13 +281,13 @@ fn make_code_region(
266
281
start_line = source_map. doctest_offset_line ( & file. name , start_line) ;
267
282
end_line = source_map. doctest_offset_line ( & file. name , end_line) ;
268
283
}
269
- CodeRegion {
284
+ Some ( CodeRegion {
270
285
file_name,
271
286
start_line : start_line as u32 ,
272
287
start_col : start_col as u32 ,
273
288
end_line : end_line as u32 ,
274
289
end_col : end_col as u32 ,
275
- }
290
+ } )
276
291
}
277
292
278
293
fn is_eligible_for_coverage ( tcx : TyCtxt < ' _ > , def_id : LocalDefId ) -> bool {
0 commit comments