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