@@ -273,20 +273,34 @@ fn save_function_record(
273273/// `codegened_and_inlined_items`).
274274///
275275/// These unused functions are then codegen'd in one of the CGUs which is marked as the
276- /// "code coverage dead code cgu" during the partitioning process.
276+ /// "code coverage dead code cgu" during the partitioning process. This prevents us from generating
277+ /// code regions for the same function more than once which can lead to linker errors regarding
278+ /// duplicate symbols.
277279fn add_unused_functions < ' ll , ' tcx > ( cx : & CodegenCx < ' ll , ' tcx > ) {
278280 assert ! ( cx. codegen_unit. is_code_coverage_dead_code_cgu( ) ) ;
279281
280282 let tcx = cx. tcx ;
281283
282284 let ignore_unused_generics = tcx. sess . instrument_coverage_except_unused_generics ( ) ;
283285
284- let all_def_ids : DefIdSet = tcx
286+ let eligible_def_ids : DefIdSet = tcx
285287 . mir_keys ( ( ) )
286288 . iter ( )
287289 . filter_map ( |local_def_id| {
288290 let def_id = local_def_id. to_def_id ( ) ;
289- if ignore_unused_generics && tcx. generics_of ( def_id) . requires_monomorphization ( tcx) {
291+ let kind = tcx. def_kind ( def_id) ;
292+ // `mir_keys` will give us `DefId`s for all kinds of things, not
293+ // just "functions", like consts, statics, etc. Filter those out.
294+ // If `ignore_unused_generics` was specified, filter out any
295+ // generic functions from consideration as well.
296+ if !matches ! (
297+ kind,
298+ DefKind :: Fn | DefKind :: AssocFn | DefKind :: Closure | DefKind :: Generator
299+ ) {
300+ return None ;
301+ } else if ignore_unused_generics
302+ && tcx. generics_of ( def_id) . requires_monomorphization ( tcx)
303+ {
290304 return None ;
291305 }
292306 Some ( local_def_id. to_def_id ( ) )
@@ -295,24 +309,17 @@ fn add_unused_functions<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) {
295309
296310 let codegenned_def_ids = tcx. codegened_and_inlined_items ( ( ) ) ;
297311
298- for & non_codegenned_def_id in all_def_ids. difference ( codegenned_def_ids) {
299- // `all_def_ids` contains things besides just "functions" such as constants,
300- // statics, etc. We need to filter those out.
301- let kind = tcx. def_kind ( non_codegenned_def_id) ;
302- if matches ! ( kind, DefKind :: Fn | DefKind :: AssocFn | DefKind :: Closure | DefKind :: Generator ) {
303- let codegen_fn_attrs = tcx. codegen_fn_attrs ( non_codegenned_def_id) ;
304-
305- // If a function is marked `#[no_coverage]`, then skip generating a
306- // dead code stub for it.
307- if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: NO_COVERAGE ) {
308- debug ! ( "skipping unused fn marked #[no_coverage]: {:?}" , non_codegenned_def_id) ;
309- continue ;
310- }
312+ for & non_codegenned_def_id in eligible_def_ids. difference ( codegenned_def_ids) {
313+ let codegen_fn_attrs = tcx. codegen_fn_attrs ( non_codegenned_def_id) ;
311314
312- debug ! ( "generating unused fn: {:?}" , non_codegenned_def_id) ;
313- cx. define_unused_fn ( non_codegenned_def_id) ;
314- } else {
315- debug ! ( "skipping unused {:?}: {:?}" , kind, non_codegenned_def_id) ;
315+ // If a function is marked `#[no_coverage]`, then skip generating a
316+ // dead code stub for it.
317+ if codegen_fn_attrs. flags . contains ( CodegenFnAttrFlags :: NO_COVERAGE ) {
318+ debug ! ( "skipping unused fn marked #[no_coverage]: {:?}" , non_codegenned_def_id) ;
319+ continue ;
316320 }
321+
322+ debug ! ( "generating unused fn: {:?}" , non_codegenned_def_id) ;
323+ cx. define_unused_fn ( non_codegenned_def_id) ;
317324 }
318325}
0 commit comments