@@ -10,7 +10,6 @@ use rustc_hir as hir;
1010use rustc_hir:: def:: { DefKind , Res } ;
1111use rustc_hir:: def_id:: { DefId , LocalDefId } ;
1212use rustc_hir:: intravisit:: { self , Visitor } ;
13- use rustc_hir:: itemlikevisit:: ItemLikeVisitor ;
1413use rustc_hir:: Node ;
1514use rustc_middle:: middle:: codegen_fn_attrs:: { CodegenFnAttrFlags , CodegenFnAttrs } ;
1615use rustc_middle:: middle:: privacy;
@@ -314,79 +313,56 @@ impl<'tcx> ReachableContext<'tcx> {
314313 }
315314}
316315
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 > (
326317 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 ) ) ;
330332
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 ;
347339 }
340+
341+ worklist. extend (
342+ tcx. provided_trait_methods ( trait_def_id)
343+ . map ( |assoc| assoc. def_id . expect_local ( ) ) ,
344+ ) ;
348345 }
349346 }
350347}
351348
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 )
359362 {
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) ;
378364 }
379365 }
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- }
390366}
391367
392368fn reachable_set < ' tcx > ( tcx : TyCtxt < ' tcx > , ( ) : ( ) ) -> FxHashSet < LocalDefId > {
@@ -418,12 +394,23 @@ fn reachable_set<'tcx>(tcx: TyCtxt<'tcx>, (): ()) -> FxHashSet<LocalDefId> {
418394 }
419395 }
420396 {
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+ }
427414 }
428415
429416 // Step 2: Mark all symbols that the symbols on the worklist touch.
0 commit comments