@@ -13,6 +13,7 @@ use rustc_middle::bug;
13
13
use rustc_middle:: mir;
14
14
use rustc_middle:: mir:: coverage:: CodeRegion ;
15
15
use rustc_middle:: ty:: { self , TyCtxt } ;
16
+ use rustc_span:: def_id:: DefIdSet ;
16
17
use rustc_span:: Symbol ;
17
18
18
19
/// Generates and exports the Coverage Map.
@@ -313,8 +314,7 @@ fn save_function_record(
313
314
/// `-Clink-dead-code` will not generate code for unused generic functions.)
314
315
///
315
316
/// We can find the unused functions (including generic functions) by the set difference of all MIR
316
- /// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`tcx` query
317
- /// `codegened_and_inlined_items`).
317
+ /// `DefId`s (`tcx` query `mir_keys`) minus the codegenned `DefId`s (`codegenned_and_inlined_items`).
318
318
///
319
319
/// These unused functions don't need to be codegenned, but we do need to add them to the function
320
320
/// coverage map (in a single designated CGU) so that we still emit coverage mappings for them.
@@ -350,7 +350,7 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
350
350
} )
351
351
. collect ( ) ;
352
352
353
- let codegenned_def_ids = tcx . codegened_and_inlined_items ( ( ) ) ;
353
+ let codegenned_def_ids = codegenned_and_inlined_items ( tcx ) ;
354
354
355
355
// For each `DefId` that should have coverage instrumentation but wasn't
356
356
// codegenned, add it to the function coverage map as an unused function.
@@ -368,6 +368,37 @@ fn add_unused_functions(cx: &CodegenCx<'_, '_>) {
368
368
}
369
369
}
370
370
371
+ /// All items participating in code generation together with (instrumented)
372
+ /// items inlined into them.
373
+ fn codegenned_and_inlined_items ( tcx : TyCtxt < ' _ > ) -> DefIdSet {
374
+ let ( items, cgus) = tcx. collect_and_partition_mono_items ( ( ) ) ;
375
+ let mut visited = DefIdSet :: default ( ) ;
376
+ let mut result = items. clone ( ) ;
377
+
378
+ for cgu in cgus {
379
+ for item in cgu. items ( ) . keys ( ) {
380
+ if let mir:: mono:: MonoItem :: Fn ( ref instance) = item {
381
+ let did = instance. def_id ( ) ;
382
+ if !visited. insert ( did) {
383
+ continue ;
384
+ }
385
+ let body = tcx. instance_mir ( instance. def ) ;
386
+ for block in body. basic_blocks . iter ( ) {
387
+ for statement in & block. statements {
388
+ let mir:: StatementKind :: Coverage ( _) = statement. kind else { continue } ;
389
+ let scope = statement. source_info . scope ;
390
+ if let Some ( inlined) = scope. inlined_instance ( & body. source_scopes ) {
391
+ result. insert ( inlined. def_id ( ) ) ;
392
+ }
393
+ }
394
+ }
395
+ }
396
+ }
397
+ }
398
+
399
+ result
400
+ }
401
+
371
402
fn declare_unused_fn < ' tcx > ( tcx : TyCtxt < ' tcx > , def_id : DefId ) -> ty:: Instance < ' tcx > {
372
403
ty:: Instance :: new (
373
404
def_id,
0 commit comments