Skip to content

Commit ccd6f89

Browse files
committed
coverage: Never emit improperly-ordered coverage regions
If we emit a coverage region that is improperly ordered (end < start), `llvm-cov` will fail with `coveragemap_error::malformed`, which is inconvenient for users and also very hard to debug. Ideally we would fix the root causes of these situations, but they tend to occur in very obscure edge-case scenarios (often involving nested macros), and we don't always have a good MCVE to work from. So it makes sense to also have a catch-all check that will prevent improperly-ordered regions from ever being emitted.
1 parent 5b49e17 commit ccd6f89

File tree

1 file changed

+21
-7
lines changed
  • compiler/rustc_mir_transform/src/coverage

1 file changed

+21
-7
lines changed

compiler/rustc_mir_transform/src/coverage/mod.rs

+21-7
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,27 @@ fn make_code_region(
286286
start_line = source_map.doctest_offset_line(&file.name, start_line);
287287
end_line = source_map.doctest_offset_line(&file.name, end_line);
288288
}
289-
Some(CodeRegion {
290-
file_name,
291-
start_line: start_line as u32,
292-
start_col: start_col as u32,
293-
end_line: end_line as u32,
294-
end_col: end_col as u32,
295-
})
289+
290+
// Convert lines/columns to u32 now, so that our checks see the same values
291+
// that LLVM will see.
292+
let start_line = start_line as u32;
293+
let start_col = start_col as u32;
294+
let end_line = end_line as u32;
295+
let end_col = end_col as u32;
296+
297+
// If we ever emit a region that is improperly ordered (end < start),
298+
// `llvm-cov` will fail with `coveragemap_error::malformed`, which is
299+
// inconvenient for users and also very hard to debug.
300+
let is_ordered = (start_line, start_col) <= (end_line, end_col);
301+
debug_assert!(is_ordered, "{start_line}:{start_col} <= {end_line}:{end_col}");
302+
if !is_ordered {
303+
debug!(
304+
"Skipping improperly-ordered region: {start_line}:{start_col} to {end_line}:{end_col}"
305+
);
306+
return None;
307+
}
308+
309+
Some(CodeRegion { file_name, start_line, start_col, end_line, end_col })
296310
}
297311

298312
fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {

0 commit comments

Comments
 (0)