@@ -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