@@ -10,7 +10,6 @@ use rustc_hir as hir;
10
10
use rustc_hir:: def:: { DefKind , Res } ;
11
11
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
12
12
use rustc_hir:: intravisit:: { self , Visitor } ;
13
- use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
14
13
use rustc_hir:: Node ;
15
14
use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
16
15
use rustc_middle:: middle:: privacy;
@@ -314,79 +313,56 @@ impl<'tcx> ReachableContext<'tcx> {
314
313
}
315
314
}
316
315
317
- // Some methods from non-exported (completely private) trait impls still have to be
318
- // reachable if they are called from inlinable code. Generally, it's not known until
319
- // monomorphization if a specific trait impl item can be reachable or not. So, we
320
- // conservatively mark all of them as reachable.
321
- // FIXME: One possible strategy for pruning the reachable set is to avoid marking impl
322
- // items of non-exported traits (or maybe all local traits?) unless their respective
323
- // trait items are used from inlinable code through method call syntax or UFCS, or their
324
- // trait is a lang item.
325
- struct CollectPrivateImplItemsVisitor < ' a , ' tcx > {
316
+ fn check_item < ' tcx > (
326
317
tcx : TyCtxt < ' tcx > ,
327
- access_levels : & ' a privacy:: AccessLevels ,
328
- worklist : & ' a mut Vec < LocalDefId > ,
329
- }
318
+ item : & hir:: Item < ' _ > ,
319
+ worklist : & mut Vec < LocalDefId > ,
320
+ access_levels : & privacy:: AccessLevels
321
+ ) {
322
+ push_to_worklist_if_has_custom_linkage ( tcx, worklist, item. def_id ) ;
323
+
324
+ // We need only trait impls here, not inherent impls, and only non-exported ones
325
+ if let hir:: ItemKind :: Impl ( hir:: Impl { of_trait : Some ( ref trait_ref) , ref items, .. } ) =
326
+ item. kind
327
+ {
328
+ if !access_levels. is_reachable ( item. def_id ) {
329
+ // FIXME(#53488) remove `let`
330
+ let tcx = tcx;
331
+ worklist. extend ( items. iter ( ) . map ( |ii_ref| ii_ref. id . def_id ) ) ;
330
332
331
- impl CollectPrivateImplItemsVisitor < ' _ , ' _ > {
332
- fn push_to_worklist_if_has_custom_linkage ( & mut self , def_id : LocalDefId ) {
333
- // Anything which has custom linkage gets thrown on the worklist no
334
- // matter where it is in the crate, along with "special std symbols"
335
- // which are currently akin to allocator symbols.
336
- if self . tcx . def_kind ( def_id) . has_codegen_attrs ( ) {
337
- let codegen_attrs = self . tcx . codegen_fn_attrs ( def_id) ;
338
- if codegen_attrs. contains_extern_indicator ( )
339
- || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: RUSTC_STD_INTERNAL_SYMBOL )
340
- // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
341
- // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
342
- // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
343
- || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED )
344
- || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED_LINKER )
345
- {
346
- self . worklist . push ( def_id) ;
333
+ let Res :: Def ( DefKind :: Trait , trait_def_id) = trait_ref. path . res else {
334
+ unreachable ! ( ) ;
335
+ } ;
336
+
337
+ if !trait_def_id. is_local ( ) {
338
+ return ;
347
339
}
340
+
341
+ worklist. extend (
342
+ tcx. provided_trait_methods ( trait_def_id)
343
+ . map ( |assoc| assoc. def_id . expect_local ( ) ) ,
344
+ ) ;
348
345
}
349
346
}
350
347
}
351
348
352
- impl < ' a , ' tcx > ItemLikeVisitor < ' tcx > for CollectPrivateImplItemsVisitor < ' a , ' tcx > {
353
- fn visit_item ( & mut self , item : & hir:: Item < ' _ > ) {
354
- self . push_to_worklist_if_has_custom_linkage ( item. def_id ) ;
355
-
356
- // We need only trait impls here, not inherent impls, and only non-exported ones
357
- if let hir:: ItemKind :: Impl ( hir:: Impl { of_trait : Some ( ref trait_ref) , ref items, .. } ) =
358
- item. kind
349
+ fn push_to_worklist_if_has_custom_linkage < ' tcx > ( tcx : TyCtxt < ' tcx > , worklist : & mut Vec < LocalDefId > , def_id : LocalDefId ) {
350
+ // Anything which has custom linkage gets thrown on the worklist no
351
+ // matter where it is in the crate, along with "special std symbols"
352
+ // which are currently akin to allocator symbols.
353
+ if tcx. def_kind ( def_id) . has_codegen_attrs ( ) {
354
+ let codegen_attrs = tcx. codegen_fn_attrs ( def_id) ;
355
+ if codegen_attrs. contains_extern_indicator ( )
356
+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: RUSTC_STD_INTERNAL_SYMBOL )
357
+ // FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
358
+ // `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
359
+ // `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
360
+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED )
361
+ || codegen_attrs. flags . contains ( CodegenFnAttrFlags :: USED_LINKER )
359
362
{
360
- if !self . access_levels . is_reachable ( item. def_id ) {
361
- // FIXME(#53488) remove `let`
362
- let tcx = self . tcx ;
363
- self . worklist . extend ( items. iter ( ) . map ( |ii_ref| ii_ref. id . def_id ) ) ;
364
-
365
- let Res :: Def ( DefKind :: Trait , trait_def_id) = trait_ref. path . res else {
366
- unreachable ! ( ) ;
367
- } ;
368
-
369
- if !trait_def_id. is_local ( ) {
370
- return ;
371
- }
372
-
373
- self . worklist . extend (
374
- tcx. provided_trait_methods ( trait_def_id)
375
- . map ( |assoc| assoc. def_id . expect_local ( ) ) ,
376
- ) ;
377
- }
363
+ worklist. push ( def_id) ;
378
364
}
379
365
}
380
-
381
- fn visit_trait_item ( & mut self , _trait_item : & hir:: TraitItem < ' _ > ) { }
382
-
383
- fn visit_impl_item ( & mut self , impl_item : & hir:: ImplItem < ' _ > ) {
384
- self . push_to_worklist_if_has_custom_linkage ( impl_item. def_id ) ;
385
- }
386
-
387
- fn visit_foreign_item ( & mut self , _foreign_item : & hir:: ForeignItem < ' _ > ) {
388
- // We never export foreign functions as they have no body to export.
389
- }
390
366
}
391
367
392
368
fn reachable_set < ' tcx > ( tcx : TyCtxt < ' tcx > , ( ) : ( ) ) -> FxHashSet < LocalDefId > {
@@ -418,12 +394,23 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
418
394
}
419
395
}
420
396
{
421
- let mut collect_private_impl_items = CollectPrivateImplItemsVisitor {
422
- tcx,
423
- access_levels,
424
- worklist : & mut reachable_context. worklist ,
425
- } ;
426
- tcx. hir ( ) . visit_all_item_likes ( & mut collect_private_impl_items) ;
397
+ // Some methods from non-exported (completely private) trait impls still have to be
398
+ // reachable if they are called from inlinable code. Generally, it's not known until
399
+ // monomorphization if a specific trait impl item can be reachable or not. So, we
400
+ // conservatively mark all of them as reachable.
401
+ // FIXME: One possible strategy for pruning the reachable set is to avoid marking impl
402
+ // items of non-exported traits (or maybe all local traits?) unless their respective
403
+ // trait items are used from inlinable code through method call syntax or UFCS, or their
404
+ // trait is a lang item.
405
+ let crate_items = tcx. hir_crate_items ( ( ) ) ;
406
+
407
+ for id in crate_items. items ( ) {
408
+ check_item ( tcx, tcx. hir ( ) . item ( id) , & mut reachable_context. worklist , access_levels) ;
409
+ }
410
+
411
+ for id in crate_items. impl_items ( ) {
412
+ push_to_worklist_if_has_custom_linkage ( tcx, & mut reachable_context. worklist , id. def_id )
413
+ }
427
414
}
428
415
429
416
// Step 2: Mark all symbols that the symbols on the worklist touch.
0 commit comments