|
1 | 1 | use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; |
2 | 2 | use crate::ty::print::{FmtPrinter, Printer}; |
| 3 | +use crate::ty::subst::InternalSubsts; |
3 | 4 | use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeFoldable}; |
4 | 5 | use rustc_errors::ErrorReported; |
5 | 6 | use rustc_hir::def::Namespace; |
@@ -106,32 +107,9 @@ pub enum InstanceDef<'tcx> { |
106 | 107 | } |
107 | 108 |
|
108 | 109 | impl<'tcx> Instance<'tcx> { |
109 | | - /// Returns the `Ty` corresponding to this `Instance`, |
110 | | - /// with generic substitutions applied and lifetimes erased. |
111 | | - /// |
112 | | - /// This method can only be called when the 'substs' for this Instance |
113 | | - /// are fully monomorphic (no `ty::Param`'s are present). |
114 | | - /// This is usually the case (e.g. during codegen). |
115 | | - /// However, during constant evaluation, we may want |
116 | | - /// to try to resolve a `Instance` using generic parameters |
117 | | - /// (e.g. when we are attempting to to do const-propagation). |
118 | | - /// In this case, `Instance.ty_env` should be used to provide |
119 | | - /// the `ParamEnv` for our generic context. |
120 | | - pub fn monomorphic_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> { |
121 | | - let ty = tcx.type_of(self.def.def_id()); |
122 | | - // There shouldn't be any params - if there are, then |
123 | | - // Instance.ty_env should have been used to provide the proper |
124 | | - // ParamEnv |
125 | | - if self.substs.has_param_types_or_consts() { |
126 | | - bug!("Instance.ty called for type {:?} with params in substs: {:?}", ty, self.substs); |
127 | | - } |
128 | | - tcx.subst_and_normalize_erasing_regions(self.substs, ty::ParamEnv::reveal_all(), &ty) |
129 | | - } |
130 | | - |
131 | | - /// Like `Instance.ty`, but allows a `ParamEnv` to be specified for use during |
132 | | - /// normalization. This method is only really useful during constant evaluation, |
133 | | - /// where we are dealing with potentially generic types. |
134 | | - pub fn ty_env(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { |
| 110 | + /// Returns the `Ty` corresponding to this `Instance`, with generic substitutions applied and |
| 111 | + /// lifetimes erased, allowing a `ParamEnv` to be specified for use during normalization. |
| 112 | + pub fn ty(&self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> Ty<'tcx> { |
135 | 113 | let ty = tcx.type_of(self.def.def_id()); |
136 | 114 | tcx.subst_and_normalize_erasing_regions(self.substs, param_env, &ty) |
137 | 115 | } |
@@ -486,6 +464,42 @@ impl<'tcx> Instance<'tcx> { |
486 | 464 | | InstanceDef::VtableShim(..) => Some(self.substs), |
487 | 465 | } |
488 | 466 | } |
| 467 | + |
| 468 | + /// Returns a new `Instance` where generic parameters in `instance.substs` are replaced by |
| 469 | + /// identify parameters if they are determined to be unused in `instance.def`. |
| 470 | + pub fn polymorphize(self, tcx: TyCtxt<'tcx>) -> Self { |
| 471 | + debug!("polymorphize: running polymorphization analysis"); |
| 472 | + if !tcx.sess.opts.debugging_opts.polymorphize { |
| 473 | + return self; |
| 474 | + } |
| 475 | + |
| 476 | + if let InstanceDef::Item(def) = self.def { |
| 477 | + let results = tcx.unused_generic_params(def.did); |
| 478 | + |
| 479 | + if results == 0 { |
| 480 | + // Exit early if every parameter was used. |
| 481 | + return self; |
| 482 | + } |
| 483 | + |
| 484 | + debug!("polymorphize: results={:064b}", results); |
| 485 | + let polymorphized_substs = |
| 486 | + InternalSubsts::for_item(tcx, def.did, |param, _| match param.kind { |
| 487 | + // If parameter is a const or type parameter.. |
| 488 | + ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if |
| 489 | + // ..and is within range and unused.. |
| 490 | + param.index < 64 && ((results >> param.index) & 1) == 1 => |
| 491 | + // ..then use the identity for this parameter. |
| 492 | + tcx.mk_param_from_def(param), |
| 493 | + // Otherwise, use the parameter as before. |
| 494 | + _ => self.substs[param.index as usize], |
| 495 | + }); |
| 496 | + |
| 497 | + debug!("polymorphize: self={:?} polymorphized_substs={:?}", self, polymorphized_substs); |
| 498 | + Self { def: self.def, substs: polymorphized_substs } |
| 499 | + } else { |
| 500 | + self |
| 501 | + } |
| 502 | + } |
489 | 503 | } |
490 | 504 |
|
491 | 505 | fn needs_fn_once_adapter_shim( |
|
0 commit comments