]>
Commit | Line | Data |
---|---|---|
6a06907d XL |
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 as hir; | |
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, | |
16 | Type { | |
17 | has_default: bool, | |
18 | object_lifetime_default: ObjectLifetimeDefault, | |
19 | synthetic: Option<hir::SyntheticTyParamKind>, | |
20 | }, | |
cdc7bbd5 XL |
21 | Const { |
22 | has_default: bool, | |
23 | }, | |
6a06907d XL |
24 | } |
25 | ||
26 | impl GenericParamDefKind { | |
27 | pub fn descr(&self) -> &'static str { | |
28 | match self { | |
29 | GenericParamDefKind::Lifetime => "lifetime", | |
30 | GenericParamDefKind::Type { .. } => "type", | |
cdc7bbd5 | 31 | GenericParamDefKind::Const { .. } => "constant", |
6a06907d XL |
32 | } |
33 | } | |
34 | pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { | |
35 | match self { | |
36 | GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, | |
37 | GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, | |
cdc7bbd5 XL |
38 | GenericParamDefKind::Const { .. } => { |
39 | ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() } | |
6a06907d XL |
40 | } |
41 | } | |
42 | } | |
43 | } | |
44 | ||
45 | #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] | |
46 | pub struct GenericParamDef { | |
47 | pub name: Symbol, | |
48 | pub def_id: DefId, | |
49 | pub index: u32, | |
50 | ||
51 | /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute | |
52 | /// on generic parameter `'a`/`T`, asserts data behind the parameter | |
53 | /// `'a`/`T` won't be accessed during the parent type's `Drop` impl. | |
54 | pub pure_wrt_drop: bool, | |
55 | ||
56 | pub kind: GenericParamDefKind, | |
57 | } | |
58 | ||
59 | impl GenericParamDef { | |
60 | pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { | |
61 | if let GenericParamDefKind::Lifetime = self.kind { | |
62 | ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name } | |
63 | } else { | |
64 | bug!("cannot convert a non-lifetime parameter def to an early bound region") | |
65 | } | |
66 | } | |
67 | } | |
68 | ||
69 | #[derive(Default)] | |
70 | pub struct GenericParamCount { | |
71 | pub lifetimes: usize, | |
72 | pub types: usize, | |
73 | pub consts: usize, | |
74 | } | |
75 | ||
76 | /// Information about the formal type/lifetime parameters associated | |
77 | /// with an item or method. Analogous to `hir::Generics`. | |
78 | /// | |
79 | /// The ordering of parameters is the same as in `Subst` (excluding child generics): | |
80 | /// `Self` (optionally), `Lifetime` params..., `Type` params... | |
81 | #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] | |
82 | pub struct Generics { | |
83 | pub parent: Option<DefId>, | |
84 | pub parent_count: usize, | |
85 | pub params: Vec<GenericParamDef>, | |
86 | ||
87 | /// Reverse map to the `index` field of each `GenericParamDef`. | |
88 | #[stable_hasher(ignore)] | |
89 | pub param_def_id_to_index: FxHashMap<DefId, u32>, | |
90 | ||
91 | pub has_self: bool, | |
92 | pub has_late_bound_regions: Option<Span>, | |
93 | } | |
94 | ||
95 | impl<'tcx> Generics { | |
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 | } | |
200 | } | |
201 | ||
202 | /// Bounds on generics. | |
203 | #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] | |
204 | pub struct GenericPredicates<'tcx> { | |
205 | pub parent: Option<DefId>, | |
206 | pub predicates: &'tcx [(Predicate<'tcx>, Span)], | |
207 | } | |
208 | ||
209 | impl<'tcx> GenericPredicates<'tcx> { | |
210 | pub fn instantiate( | |
211 | &self, | |
212 | tcx: TyCtxt<'tcx>, | |
213 | substs: SubstsRef<'tcx>, | |
214 | ) -> InstantiatedPredicates<'tcx> { | |
215 | let mut instantiated = InstantiatedPredicates::empty(); | |
216 | self.instantiate_into(tcx, &mut instantiated, substs); | |
217 | instantiated | |
218 | } | |
219 | ||
220 | pub fn instantiate_own( | |
221 | &self, | |
222 | tcx: TyCtxt<'tcx>, | |
223 | substs: SubstsRef<'tcx>, | |
224 | ) -> InstantiatedPredicates<'tcx> { | |
225 | InstantiatedPredicates { | |
226 | predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(), | |
227 | spans: self.predicates.iter().map(|(_, sp)| *sp).collect(), | |
228 | } | |
229 | } | |
230 | ||
231 | fn instantiate_into( | |
232 | &self, | |
233 | tcx: TyCtxt<'tcx>, | |
234 | instantiated: &mut InstantiatedPredicates<'tcx>, | |
235 | substs: SubstsRef<'tcx>, | |
236 | ) { | |
237 | if let Some(def_id) = self.parent { | |
238 | tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); | |
239 | } | |
240 | instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p.subst(tcx, substs))); | |
241 | instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); | |
242 | } | |
243 | ||
244 | pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { | |
245 | let mut instantiated = InstantiatedPredicates::empty(); | |
246 | self.instantiate_identity_into(tcx, &mut instantiated); | |
247 | instantiated | |
248 | } | |
249 | ||
250 | fn instantiate_identity_into( | |
251 | &self, | |
252 | tcx: TyCtxt<'tcx>, | |
253 | instantiated: &mut InstantiatedPredicates<'tcx>, | |
254 | ) { | |
255 | if let Some(def_id) = self.parent { | |
256 | tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); | |
257 | } | |
258 | instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p)); | |
259 | instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); | |
260 | } | |
261 | } |