@@ -27,20 +27,23 @@ pub fn provide(providers: &mut Providers) {
2727 providers. unused_generic_params = unused_generic_params;
2828}
2929
30- /// Determine which generic parameters are used by the function/method/closure represented by
31- /// `def_id`. Returns a bitset where bits representing unused parameters are set (`is_empty`
32- /// indicates all parameters are used).
30+ /// Determine which generic parameters are used by the instance.
31+ ///
32+ /// Returns a bitset where bits representing unused parameters are set (`is_empty` indicates all
33+ /// parameters are used).
3334#[ instrument( level = "debug" , skip( tcx) ) ]
34- fn unused_generic_params ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> FiniteBitSet < u32 > {
35+ fn unused_generic_params < ' tcx > (
36+ tcx : TyCtxt < ' tcx > ,
37+ instance : ty:: InstanceDef < ' tcx > ,
38+ ) -> FiniteBitSet < u32 > {
3539 if !tcx. sess . opts . debugging_opts . polymorphize {
3640 // If polymorphization disabled, then all parameters are used.
3741 return FiniteBitSet :: new_empty ( ) ;
3842 }
3943
40- // Polymorphization results are stored in cross-crate metadata only when there are unused
41- // parameters, so assume that non-local items must have only used parameters (else this query
42- // would not be invoked, and the cross-crate metadata used instead).
43- if !def_id. is_local ( ) {
44+ let def_id = instance. def_id ( ) ;
45+ // Exit early if this instance should not be polymorphized.
46+ if !should_polymorphize ( tcx, def_id, instance) {
4447 return FiniteBitSet :: new_empty ( ) ;
4548 }
4649
@@ -52,38 +55,20 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
5255 return FiniteBitSet :: new_empty ( ) ;
5356 }
5457
55- // Exit early for foreign items, these have no bodies to analyze.
56- if tcx. is_foreign_item ( def_id) {
57- return FiniteBitSet :: new_empty ( ) ;
58- }
59-
60- // Exit early when there is no MIR available.
61- let context = tcx. hir ( ) . body_const_context ( def_id. expect_local ( ) ) ;
62- match context {
63- Some ( ConstContext :: ConstFn ) | None if !tcx. is_mir_available ( def_id) => {
64- debug ! ( "no mir available" ) ;
65- return FiniteBitSet :: new_empty ( ) ;
66- }
67- Some ( _) if !tcx. is_ctfe_mir_available ( def_id) => {
68- debug ! ( "no ctfe mir available" ) ;
69- return FiniteBitSet :: new_empty ( ) ;
70- }
71- _ => { }
72- }
73-
7458 // Create a bitset with N rightmost ones for each parameter.
7559 let generics_count: u32 =
7660 generics. count ( ) . try_into ( ) . expect ( "more generic parameters than can fit into a `u32`" ) ;
7761 let mut unused_parameters = FiniteBitSet :: < u32 > :: new_empty ( ) ;
7862 unused_parameters. set_range ( 0 ..generics_count) ;
7963 debug ! ( ?unused_parameters, "(start)" ) ;
64+
8065 mark_used_by_default_parameters ( tcx, def_id, generics, & mut unused_parameters) ;
8166 debug ! ( ?unused_parameters, "(after default)" ) ;
8267
8368 // Visit MIR and accumululate used generic parameters.
84- let body = match context {
69+ let body = match tcx . hir ( ) . body_const_context ( def_id . expect_local ( ) ) {
8570 // Const functions are actually called and should thus be considered for polymorphization
86- // via their runtime MIR
71+ // via their runtime MIR.
8772 Some ( ConstContext :: ConstFn ) | None => tcx. optimized_mir ( def_id) ,
8873 Some ( _) => tcx. mir_for_ctfe ( def_id) ,
8974 } ;
@@ -99,6 +84,49 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
9984 unused_parameters
10085}
10186
87+ /// Returns `true` if the instance should be polymorphized.
88+ fn should_polymorphize < ' tcx > (
89+ tcx : TyCtxt < ' tcx > ,
90+ def_id : DefId ,
91+ instance : ty:: InstanceDef < ' tcx > ,
92+ ) -> bool {
93+ // If an instance's MIR body is not polymorphic then the modified substitutions that are
94+ // derived from polymorphization's result won't make any difference.
95+ if !instance. has_polymorphic_mir_body ( ) {
96+ return false ;
97+ }
98+
99+ // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic.
100+ if matches ! ( instance, ty:: InstanceDef :: Intrinsic ( ..) | ty:: InstanceDef :: Virtual ( ..) ) {
101+ return false ;
102+ }
103+
104+ // Polymorphization results are stored in cross-crate metadata only when there are unused
105+ // parameters, so assume that non-local items must have only used parameters (else this query
106+ // would not be invoked, and the cross-crate metadata used instead).
107+ if !def_id. is_local ( ) {
108+ return false ;
109+ }
110+
111+ // Foreign items have no bodies to analyze.
112+ if tcx. is_foreign_item ( def_id) {
113+ return false ;
114+ }
115+
116+ // Make sure there is MIR available.
117+ match tcx. hir ( ) . body_const_context ( def_id. expect_local ( ) ) {
118+ Some ( ConstContext :: ConstFn ) | None if !tcx. is_mir_available ( def_id) => {
119+ debug ! ( "no mir available" ) ;
120+ return false ;
121+ }
122+ Some ( _) if !tcx. is_ctfe_mir_available ( def_id) => {
123+ debug ! ( "no ctfe mir available" ) ;
124+ return false ;
125+ }
126+ _ => true ,
127+ }
128+ }
129+
102130/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy
103131/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should
104132/// be `true` if the item that `unused_generic_params` was invoked on is a closure.
@@ -207,7 +235,8 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
207235 /// a closure, generator or constant).
208236 #[ instrument( level = "debug" , skip( self , def_id, substs) ) ]
209237 fn visit_child_body ( & mut self , def_id : DefId , substs : SubstsRef < ' tcx > ) {
210- let unused = self . tcx . unused_generic_params ( def_id) ;
238+ let instance = ty:: InstanceDef :: Item ( ty:: WithOptConstParam :: unknown ( def_id) ) ;
239+ let unused = self . tcx . unused_generic_params ( instance) ;
211240 debug ! ( ?self . unused_parameters, ?unused) ;
212241 for ( i, arg) in substs. iter ( ) . enumerate ( ) {
213242 let i = i. try_into ( ) . unwrap ( ) ;
0 commit comments