1 use crate::middle::resolve_lifetime::ObjectLifetimeDefault; 2 use crate::ty; 3 use crate::ty::subst::{Subst, SubstsRef}; 4 use rustc_ast as ast; 5 use rustc_data_structures::fx::FxHashMap; 6 use rustc_hir::def_id::DefId; 7 use rustc_span::symbol::Symbol; 8 use rustc_span::Span; 9 10 use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; 11 12 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] 13 pub enum GenericParamDefKind { 14 Lifetime, 15 Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, 16 Const { has_default: bool }, 17 } 18 19 impl GenericParamDefKind { descr(&self) -> &'static str20 pub fn descr(&self) -> &'static str { 21 match self { 22 GenericParamDefKind::Lifetime => "lifetime", 23 GenericParamDefKind::Type { .. } => "type", 24 GenericParamDefKind::Const { .. } => "constant", 25 } 26 } to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd27 pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { 28 match self { 29 GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, 30 GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, 31 GenericParamDefKind::Const { .. } => { 32 ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } 33 } 34 } 35 } 36 } 37 38 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] 39 pub struct GenericParamDef { 40 pub name: Symbol, 41 pub def_id: DefId, 42 pub index: u32, 43 44 /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute 45 /// on generic parameter `'a`/`T`, asserts data behind the parameter 46 /// `'a`/`T` won't be accessed during the parent type's `Drop` impl. 47 pub pure_wrt_drop: bool, 48 49 pub kind: GenericParamDefKind, 50 } 51 52 impl GenericParamDef { to_early_bound_region_data(&self) -> ty::EarlyBoundRegion53 pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { 54 if let GenericParamDefKind::Lifetime = self.kind { 55 ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name } 56 } else { 57 bug!("cannot convert a non-lifetime parameter def to an early bound region") 58 } 59 } 60 } 61 62 #[derive(Default)] 63 pub struct GenericParamCount { 64 pub lifetimes: usize, 65 pub types: usize, 66 pub consts: usize, 67 } 68 69 /// Information about the formal type/lifetime parameters associated 70 /// with an item or method. Analogous to `hir::Generics`. 71 /// 72 /// The ordering of parameters is the same as in `Subst` (excluding child generics): 73 /// `Self` (optionally), `Lifetime` params..., `Type` params... 74 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] 75 pub struct Generics { 76 pub parent: Option<DefId>, 77 pub parent_count: usize, 78 pub params: Vec<GenericParamDef>, 79 80 /// Reverse map to the `index` field of each `GenericParamDef`. 81 #[stable_hasher(ignore)] 82 pub param_def_id_to_index: FxHashMap<DefId, u32>, 83 84 pub has_self: bool, 85 pub has_late_bound_regions: Option<Span>, 86 } 87 88 impl<'tcx> Generics { 89 #[inline] count(&self) -> usize90 pub fn count(&self) -> usize { 91 self.parent_count + self.params.len() 92 } 93 own_counts(&self) -> GenericParamCount94 pub fn own_counts(&self) -> GenericParamCount { 95 // We could cache this as a property of `GenericParamCount`, but 96 // the aim is to refactor this away entirely eventually and the 97 // presence of this method will be a constant reminder. 98 let mut own_counts = GenericParamCount::default(); 99 100 for param in &self.params { 101 match param.kind { 102 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, 103 GenericParamDefKind::Type { .. } => own_counts.types += 1, 104 GenericParamDefKind::Const { .. } => own_counts.consts += 1, 105 } 106 } 107 108 own_counts 109 } 110 own_defaults(&self) -> GenericParamCount111 pub fn own_defaults(&self) -> GenericParamCount { 112 let mut own_defaults = GenericParamCount::default(); 113 114 for param in &self.params { 115 match param.kind { 116 GenericParamDefKind::Lifetime => (), 117 GenericParamDefKind::Type { has_default, .. } => { 118 own_defaults.types += has_default as usize; 119 } 120 GenericParamDefKind::Const { has_default } => { 121 own_defaults.consts += has_default as usize; 122 } 123 } 124 } 125 126 own_defaults 127 } 128 requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool129 pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool { 130 if self.own_requires_monomorphization() { 131 return true; 132 } 133 134 if let Some(parent_def_id) = self.parent { 135 let parent = tcx.generics_of(parent_def_id); 136 parent.requires_monomorphization(tcx) 137 } else { 138 false 139 } 140 } 141 own_requires_monomorphization(&self) -> bool142 pub fn own_requires_monomorphization(&self) -> bool { 143 for param in &self.params { 144 match param.kind { 145 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { 146 return true; 147 } 148 GenericParamDefKind::Lifetime => {} 149 } 150 } 151 false 152 } 153 154 /// Returns the `GenericParamDef` with the given index. param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef155 pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { 156 if let Some(index) = param_index.checked_sub(self.parent_count) { 157 &self.params[index] 158 } else { 159 tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) 160 .param_at(param_index, tcx) 161 } 162 } 163 164 /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. region_param( &'tcx self, param: &EarlyBoundRegion, tcx: TyCtxt<'tcx>, ) -> &'tcx GenericParamDef165 pub fn region_param( 166 &'tcx self, 167 param: &EarlyBoundRegion, 168 tcx: TyCtxt<'tcx>, 169 ) -> &'tcx GenericParamDef { 170 let param = self.param_at(param.index as usize, tcx); 171 match param.kind { 172 GenericParamDefKind::Lifetime => param, 173 _ => bug!("expected lifetime parameter, but found another generic parameter"), 174 } 175 } 176 177 /// Returns the `GenericParamDef` associated with this `ParamTy`. type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef178 pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { 179 let param = self.param_at(param.index as usize, tcx); 180 match param.kind { 181 GenericParamDefKind::Type { .. } => param, 182 _ => bug!("expected type parameter, but found another generic parameter"), 183 } 184 } 185 186 /// Returns the `GenericParamDef` associated with this `ParamConst`. const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef187 pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { 188 let param = self.param_at(param.index as usize, tcx); 189 match param.kind { 190 GenericParamDefKind::Const { .. } => param, 191 _ => bug!("expected const parameter, but found another generic parameter"), 192 } 193 } 194 195 /// Returns `true` if `params` has `impl Trait`. has_impl_trait(&'tcx self) -> bool196 pub fn has_impl_trait(&'tcx self) -> bool { 197 self.params.iter().any(|param| { 198 matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) 199 }) 200 } 201 } 202 203 /// Bounds on generics. 204 #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] 205 pub struct GenericPredicates<'tcx> { 206 pub parent: Option<DefId>, 207 pub predicates: &'tcx [(Predicate<'tcx>, Span)], 208 } 209 210 impl<'tcx> GenericPredicates<'tcx> { instantiate( &self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, ) -> InstantiatedPredicates<'tcx>211 pub fn instantiate( 212 &self, 213 tcx: TyCtxt<'tcx>, 214 substs: SubstsRef<'tcx>, 215 ) -> InstantiatedPredicates<'tcx> { 216 let mut instantiated = InstantiatedPredicates::empty(); 217 self.instantiate_into(tcx, &mut instantiated, substs); 218 instantiated 219 } 220 instantiate_own( &self, tcx: TyCtxt<'tcx>, substs: SubstsRef<'tcx>, ) -> InstantiatedPredicates<'tcx>221 pub fn instantiate_own( 222 &self, 223 tcx: TyCtxt<'tcx>, 224 substs: SubstsRef<'tcx>, 225 ) -> InstantiatedPredicates<'tcx> { 226 InstantiatedPredicates { 227 predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(), 228 spans: self.predicates.iter().map(|(_, sp)| *sp).collect(), 229 } 230 } 231 instantiate_into( &self, tcx: TyCtxt<'tcx>, instantiated: &mut InstantiatedPredicates<'tcx>, substs: SubstsRef<'tcx>, )232 fn instantiate_into( 233 &self, 234 tcx: TyCtxt<'tcx>, 235 instantiated: &mut InstantiatedPredicates<'tcx>, 236 substs: SubstsRef<'tcx>, 237 ) { 238 if let Some(def_id) = self.parent { 239 tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); 240 } 241 instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p.subst(tcx, substs))); 242 instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); 243 } 244 instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx>245 pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { 246 let mut instantiated = InstantiatedPredicates::empty(); 247 self.instantiate_identity_into(tcx, &mut instantiated); 248 instantiated 249 } 250 instantiate_identity_into( &self, tcx: TyCtxt<'tcx>, instantiated: &mut InstantiatedPredicates<'tcx>, )251 fn instantiate_identity_into( 252 &self, 253 tcx: TyCtxt<'tcx>, 254 instantiated: &mut InstantiatedPredicates<'tcx>, 255 ) { 256 if let Some(def_id) = self.parent { 257 tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); 258 } 259 instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p)); 260 instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); 261 } 262 } 263