@@ -16,7 +16,7 @@ use rustc_middle::ty::{
1616    fold:: { TypeFoldable ,  TypeVisitor } , 
1717    query:: Providers , 
1818    subst:: SubstsRef , 
19-     Const ,  Ty ,  TyCtxt , 
19+     Const ,  InstanceDef ,   Ty ,  TyCtxt , 
2020} ; 
2121use  rustc_span:: symbol:: sym; 
2222use  std:: convert:: TryInto ; 
@@ -27,21 +27,25 @@ 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` 
30+ /// Determine which generic parameters are used by the `instance`. 
31+ /// 
32+ /// Returns a bitset where bits representing unused parameters are set (`is_empty` 
3233/// indicates all parameters are used). 
33- fn  unused_generic_params ( tcx :  TyCtxt < ' _ > ,  def_id :  DefId )  -> FiniteBitSet < u32 >  { 
34-     debug ! ( "unused_generic_params({:?})" ,  def_id) ; 
34+ fn  unused_generic_params < ' tcx > ( 
35+     tcx :  TyCtxt < ' tcx > , 
36+     instance :  InstanceDef < ' tcx > , 
37+ )  -> FiniteBitSet < u32 >  { 
38+     debug ! ( "unused_generic_params({:?})" ,  instance) ; 
3539
40+     // If polymorphization disabled, then all parameters are used. 
3641    if  !tcx. sess . opts . debugging_opts . polymorphize  { 
37-         // If polymorphization disabled, then all parameters are used. 
3842        return  FiniteBitSet :: new_empty ( ) ; 
3943    } 
4044
41-     // Polymorphization results are stored in cross-crate metadata only when there are unused  
42-     // parameters, so assume that non-local items must have only used parameters (else this query 
43-     // would not be invoked, and the cross-crate metadata used instead). 
44-     if  !def_id . is_local ( )   { 
45+     // Exit early if this instance should not be polymorphized.  
46+     let  def_id = instance . def_id ( ) ; 
47+     if  ! should_polymorphize ( tcx ,  def_id ,  instance )   { 
48+          debug ! ( "unused_generic_params: skipping" ) ; 
4549        return  FiniteBitSet :: new_empty ( ) ; 
4650    } 
4751
@@ -53,36 +57,24 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
5357        return  FiniteBitSet :: new_empty ( ) ; 
5458    } 
5559
56-     // Exit early when there is no MIR available. 
57-     let  context = tcx. hir ( ) . body_const_context ( def_id. expect_local ( ) ) ; 
58-     match  context { 
59-         Some ( ConstContext :: ConstFn )  | None  if  !tcx. is_mir_available ( def_id)  => { 
60-             debug ! ( "unused_generic_params: (no mir available) def_id={:?}" ,  def_id) ; 
61-             return  FiniteBitSet :: new_empty ( ) ; 
62-         } 
63-         Some ( _)  if  !tcx. is_ctfe_mir_available ( def_id)  => { 
64-             debug ! ( "unused_generic_params: (no ctfe mir available) def_id={:?}" ,  def_id) ; 
65-             return  FiniteBitSet :: new_empty ( ) ; 
66-         } 
67-         _ => { } 
68-     } 
69- 
7060    // Create a bitset with N rightmost ones for each parameter. 
7161    let  generics_count:  u32  =
7262        generics. count ( ) . try_into ( ) . expect ( "more generic parameters than can fit into a `u32`" ) ; 
7363    let  mut  unused_parameters = FiniteBitSet :: < u32 > :: new_empty ( ) ; 
7464    unused_parameters. set_range ( 0 ..generics_count) ; 
7565    debug ! ( "unused_generic_params: (start) unused_parameters={:?}" ,  unused_parameters) ; 
66+ 
7667    mark_used_by_default_parameters ( tcx,  def_id,  generics,  & mut  unused_parameters) ; 
7768    debug ! ( "unused_generic_params: (after default) unused_parameters={:?}" ,  unused_parameters) ; 
7869
79-     // Visit MIR and accumululate used generic parameters. 
80-     let  body = match  context { 
70+     let  body = match  tcx. hir ( ) . body_const_context ( def_id. expect_local ( ) )  { 
8171        // Const functions are actually called and should thus be considered for polymorphization 
82-         // via their runtime MIR 
72+         // via their runtime MIR.  
8373        Some ( ConstContext :: ConstFn )  | None  => tcx. optimized_mir ( def_id) , 
8474        Some ( _)  => tcx. mir_for_ctfe ( def_id) , 
8575    } ; 
76+ 
77+     // Visit MIR and accumululate used generic parameters. 
8678    let  mut  vis = MarkUsedGenericParams  {  tcx,  def_id,  unused_parameters :  & mut  unused_parameters } ; 
8779    vis. visit_body ( body) ; 
8880    debug ! ( "unused_generic_params: (after visitor) unused_parameters={:?}" ,  unused_parameters) ; 
@@ -98,6 +90,48 @@ fn unused_generic_params(tcx: TyCtxt<'_>, def_id: DefId) -> FiniteBitSet<u32> {
9890    unused_parameters
9991} 
10092
93+ /// Returns `true` if the `InstanceDef` should be polymorphized. 
94+ fn  should_polymorphize < ' tcx > ( 
95+     tcx :  TyCtxt < ' tcx > , 
96+     def_id :  DefId , 
97+     instance :  ty:: InstanceDef < ' tcx > , 
98+ )  -> bool  { 
99+     // If a instance's MIR body is not polymorphic then the modified substitutions that are derived 
100+     // from polymorphization's result won't make any difference. 
101+     if  !instance. has_polymorphic_mir_body ( )  { 
102+         return  false ; 
103+     } 
104+ 
105+     // Don't polymorphize intrinsics or virtual calls - calling `instance_mir` will panic. 
106+     if  matches ! ( instance,  ty:: InstanceDef :: Intrinsic ( ..)  | ty:: InstanceDef :: Virtual ( ..) )  { 
107+         return  false ; 
108+     } 
109+ 
110+     // Polymorphization results are stored in cross-crate metadata only when there are unused 
111+     // parameters, so assume that non-local items must have only used parameters (else this query 
112+     // would not be invoked, and the cross-crate metadata used instead). 
113+     if  !def_id. is_local ( )  { 
114+         return  false ; 
115+     } 
116+ 
117+     // Foreign items don't have a body to analyze. 
118+     if  tcx. is_foreign_item ( def_id)  { 
119+         return  false ; 
120+     } 
121+ 
122+     // Without available MIR, polymorphization has nothing to analyze. 
123+     match  tcx. hir ( ) . body_const_context ( def_id. expect_local ( ) )  { 
124+         // FIXME(davidtwco): Disable polymorphization for any constant functions which, at the time 
125+         // of writing, can result in an ICE from typeck in one test and a cycle error in another. 
126+         Some ( _)  => false , 
127+         None  if  !tcx. is_mir_available ( def_id)  => { 
128+             debug ! ( "should_polymorphize: (no mir available) def_id={:?}" ,  def_id) ; 
129+             false 
130+         } 
131+         None  => true , 
132+     } 
133+ } 
134+ 
101135/// Some parameters are considered used-by-default, such as non-generic parameters and the dummy 
102136/// generic parameters from closures, this function marks them as used. `leaf_is_closure` should 
103137/// be `true` if the item that `unused_generic_params` was invoked on is a closure. 
@@ -220,7 +254,9 @@ impl<'a, 'tcx> MarkUsedGenericParams<'a, 'tcx> {
220254    /// Invoke `unused_generic_params` on a body contained within the current item (e.g. 
221255/// a closure, generator or constant). 
222256fn  visit_child_body ( & mut  self ,  def_id :  DefId ,  substs :  SubstsRef < ' tcx > )  { 
223-         let  unused = self . tcx . unused_generic_params ( def_id) ; 
257+         let  unused = self 
258+             . tcx 
259+             . unused_generic_params ( ty:: InstanceDef :: Item ( ty:: WithOptConstParam :: unknown ( def_id) ) ) ; 
224260        debug ! ( 
225261            "visit_child_body: unused_parameters={:?} unused={:?}" , 
226262            self . unused_parameters,  unused
0 commit comments