@@ -18,7 +18,9 @@ use tracing::{debug, debug_span, trace, warn};
1818use rustc_data_structures:: fingerprint:: Fingerprint ;
1919use rustc_data_structures:: fx:: FxHashSet ;
2020use rustc_data_structures:: stable_hasher:: { HashStable , StableHasher } ;
21+ use rustc_hir:: def:: DefKind ;
2122use rustc_hir:: def_id:: DefId ;
23+ use rustc_hir:: ItemId ;
2224use rustc_middle:: mir:: interpret:: { AllocId , ConstValue , ErrorHandled , GlobalAlloc , Scalar } ;
2325use rustc_middle:: mir:: mono:: MonoItem ;
2426use rustc_middle:: mir:: visit:: Visitor as MirVisitor ;
@@ -57,18 +59,35 @@ pub fn collect_reachable_items<'tcx>(
5759}
5860
5961/// Collect all (top-level) items in the crate that matches the given predicate.
62+ /// An item can only be a root if they are: non-generic Fn / Static / GlobalASM
6063pub fn filter_crate_items < F > ( tcx : TyCtxt , predicate : F ) -> Vec < MonoItem >
6164where
62- F : FnMut ( TyCtxt , DefId ) -> bool ,
65+ F : Fn ( TyCtxt , DefId ) -> bool ,
6366{
64- let mut filter = predicate;
65- tcx. hir_crate_items ( ( ) )
66- . items ( )
67- . filter_map ( |hir_id| {
68- let def_id = hir_id. owner_id . def_id . to_def_id ( ) ;
69- filter ( tcx, def_id) . then ( || MonoItem :: Fn ( Instance :: mono ( tcx, def_id) ) )
70- } )
71- . collect ( )
67+ let crate_items = tcx. hir_crate_items ( ( ) ) ;
68+ // Filter regular items.
69+ let root_items = crate_items. items ( ) . filter_map ( |item| {
70+ let def_id = item. owner_id . def_id . to_def_id ( ) ;
71+ if !is_generic ( tcx, def_id) && predicate ( tcx, def_id) {
72+ to_mono_root ( tcx, item, def_id)
73+ } else {
74+ None
75+ }
76+ } ) ;
77+
78+ // Filter items from implementation blocks.
79+ let impl_items = crate_items. impl_items ( ) . filter_map ( |impl_item| {
80+ let def_id = impl_item. owner_id . def_id . to_def_id ( ) ;
81+ if matches ! ( tcx. def_kind( def_id) , DefKind :: AssocFn )
82+ && !is_generic ( tcx, def_id)
83+ && predicate ( tcx, def_id)
84+ {
85+ Some ( MonoItem :: Fn ( Instance :: mono ( tcx, def_id) ) )
86+ } else {
87+ None
88+ }
89+ } ) ;
90+ root_items. chain ( impl_items) . collect ( )
7291}
7392
7493/// Use a predicate to find `const` declarations, then extract all closures from those declarations
@@ -96,6 +115,24 @@ where
96115 roots
97116}
98117
118+ fn is_generic ( tcx : TyCtxt , def_id : DefId ) -> bool {
119+ let generics = tcx. generics_of ( def_id) ;
120+ generics. requires_monomorphization ( tcx)
121+ }
122+
123+ fn to_mono_root ( tcx : TyCtxt , item_id : ItemId , def_id : DefId ) -> Option < MonoItem > {
124+ let kind = tcx. def_kind ( def_id) ;
125+ match kind {
126+ DefKind :: Static ( ..) => Some ( MonoItem :: Static ( def_id) ) ,
127+ DefKind :: Fn => Some ( MonoItem :: Fn ( Instance :: mono ( tcx, def_id) ) ) ,
128+ DefKind :: GlobalAsm => Some ( MonoItem :: GlobalAsm ( item_id) ) ,
129+ _ => {
130+ debug ! ( ?def_id, ?kind, "Ignored item. Not a root type." ) ;
131+ None
132+ }
133+ }
134+ }
135+
99136struct MonoItemsCollector < ' tcx > {
100137 /// The compiler context.
101138 tcx : TyCtxt < ' tcx > ,
0 commit comments