]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_middle/src/ty/generics.rs
New upstream version 1.69.0+dfsg1
[rustc.git] / compiler / rustc_middle / src / ty / generics.rs
CommitLineData
6a06907d 1use crate::ty;
2b03887a 2use crate::ty::{EarlyBinder, SubstsRef};
6a06907d
XL
3use rustc_ast as ast;
4use rustc_data_structures::fx::FxHashMap;
6a06907d 5use rustc_hir::def_id::DefId;
487cf647 6use rustc_span::symbol::{kw, Symbol};
6a06907d
XL
7use rustc_span::Span;
8
9use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt};
10
11#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
12pub enum GenericParamDefKind {
13 Lifetime,
f2b60f7d 14 Type { has_default: bool, synthetic: bool },
3c0e092e 15 Const { has_default: bool },
6a06907d
XL
16}
17
18impl GenericParamDefKind {
19 pub fn descr(&self) -> &'static str {
20 match self {
21 GenericParamDefKind::Lifetime => "lifetime",
22 GenericParamDefKind::Type { .. } => "type",
cdc7bbd5 23 GenericParamDefKind::Const { .. } => "constant",
6a06907d
XL
24 }
25 }
a2a8927a 26 pub fn to_ord(&self) -> ast::ParamKindOrd {
6a06907d
XL
27 match self {
28 GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
f2b60f7d
FG
29 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
30 ast::ParamKindOrd::TypeOrConst
31 }
6a06907d
XL
32 }
33 }
5099ac24
FG
34
35 pub fn is_ty_or_const(&self) -> bool {
36 match self {
37 GenericParamDefKind::Lifetime => false,
38 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true,
39 }
40 }
923072b8
FG
41
42 pub fn is_synthetic(&self) -> bool {
43 match self {
44 GenericParamDefKind::Type { synthetic, .. } => *synthetic,
45 _ => false,
46 }
47 }
6a06907d
XL
48}
49
50#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
51pub struct GenericParamDef {
52 pub name: Symbol,
53 pub def_id: DefId,
54 pub index: u32,
55
56 /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute
57 /// on generic parameter `'a`/`T`, asserts data behind the parameter
58 /// `'a`/`T` won't be accessed during the parent type's `Drop` impl.
59 pub pure_wrt_drop: bool,
60
61 pub kind: GenericParamDefKind,
62}
63
64impl GenericParamDef {
65 pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion {
66 if let GenericParamDefKind::Lifetime = self.kind {
67 ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name }
68 } else {
69 bug!("cannot convert a non-lifetime parameter def to an early bound region")
70 }
71 }
923072b8 72
487cf647
FG
73 pub fn is_anonymous_lifetime(&self) -> bool {
74 match self.kind {
75 GenericParamDefKind::Lifetime => {
76 self.name == kw::UnderscoreLifetime || self.name == kw::Empty
77 }
78 _ => false,
79 }
80 }
81
923072b8
FG
82 pub fn default_value<'tcx>(
83 &self,
84 tcx: TyCtxt<'tcx>,
85 ) -> Option<EarlyBinder<ty::GenericArg<'tcx>>> {
86 match self.kind {
87 GenericParamDefKind::Type { has_default, .. } if has_default => {
9ffffee4 88 Some(tcx.type_of(self.def_id).map_bound(|t| t.into()))
923072b8
FG
89 }
90 GenericParamDefKind::Const { has_default } if has_default => {
9c376795 91 Some(tcx.const_param_default(self.def_id).map_bound(|c| c.into()))
923072b8
FG
92 }
93 _ => None,
94 }
95 }
487cf647
FG
96
97 pub fn to_error<'tcx>(
98 &self,
99 tcx: TyCtxt<'tcx>,
100 preceding_substs: &[ty::GenericArg<'tcx>],
101 ) -> ty::GenericArg<'tcx> {
102 match &self.kind {
9ffffee4
FG
103 ty::GenericParamDefKind::Lifetime => tcx.mk_re_error_misc().into(),
104 ty::GenericParamDefKind::Type { .. } => tcx.ty_error_misc().into(),
487cf647 105 ty::GenericParamDefKind::Const { .. } => {
9ffffee4 106 tcx.const_error(tcx.type_of(self.def_id).subst(tcx, preceding_substs)).into()
487cf647
FG
107 }
108 }
109 }
6a06907d
XL
110}
111
112#[derive(Default)]
113pub struct GenericParamCount {
114 pub lifetimes: usize,
115 pub types: usize,
116 pub consts: usize,
117}
118
119/// Information about the formal type/lifetime parameters associated
120/// with an item or method. Analogous to `hir::Generics`.
121///
122/// The ordering of parameters is the same as in `Subst` (excluding child generics):
123/// `Self` (optionally), `Lifetime` params..., `Type` params...
124#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
125pub struct Generics {
126 pub parent: Option<DefId>,
127 pub parent_count: usize,
128 pub params: Vec<GenericParamDef>,
129
130 /// Reverse map to the `index` field of each `GenericParamDef`.
131 #[stable_hasher(ignore)]
132 pub param_def_id_to_index: FxHashMap<DefId, u32>,
133
134 pub has_self: bool,
135 pub has_late_bound_regions: Option<Span>,
136}
137
138impl<'tcx> Generics {
f2b60f7d
FG
139 /// Looks through the generics and all parents to find the index of the
140 /// given param def-id. This is in comparison to the `param_def_id_to_index`
141 /// struct member, which only stores information about this item's own
142 /// generics.
143 pub fn param_def_id_to_index(&self, tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<u32> {
144 if let Some(idx) = self.param_def_id_to_index.get(&def_id) {
145 Some(*idx)
146 } else if let Some(parent) = self.parent {
147 let parent = tcx.generics_of(parent);
148 parent.param_def_id_to_index(tcx, def_id)
149 } else {
150 None
151 }
152 }
153
17df50a5 154 #[inline]
6a06907d
XL
155 pub fn count(&self) -> usize {
156 self.parent_count + self.params.len()
157 }
158
159 pub fn own_counts(&self) -> GenericParamCount {
160 // We could cache this as a property of `GenericParamCount`, but
161 // the aim is to refactor this away entirely eventually and the
162 // presence of this method will be a constant reminder.
163 let mut own_counts = GenericParamCount::default();
164
165 for param in &self.params {
166 match param.kind {
167 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
168 GenericParamDefKind::Type { .. } => own_counts.types += 1,
cdc7bbd5 169 GenericParamDefKind::Const { .. } => own_counts.consts += 1,
6a06907d
XL
170 }
171 }
172
173 own_counts
174 }
175
176 pub fn own_defaults(&self) -> GenericParamCount {
177 let mut own_defaults = GenericParamCount::default();
178
179 for param in &self.params {
180 match param.kind {
181 GenericParamDefKind::Lifetime => (),
182 GenericParamDefKind::Type { has_default, .. } => {
183 own_defaults.types += has_default as usize;
184 }
cdc7bbd5
XL
185 GenericParamDefKind::Const { has_default } => {
186 own_defaults.consts += has_default as usize;
6a06907d
XL
187 }
188 }
189 }
190
191 own_defaults
192 }
193
194 pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool {
195 if self.own_requires_monomorphization() {
196 return true;
197 }
198
199 if let Some(parent_def_id) = self.parent {
200 let parent = tcx.generics_of(parent_def_id);
201 parent.requires_monomorphization(tcx)
202 } else {
203 false
204 }
205 }
206
207 pub fn own_requires_monomorphization(&self) -> bool {
208 for param in &self.params {
209 match param.kind {
cdc7bbd5
XL
210 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
211 return true;
212 }
6a06907d
XL
213 GenericParamDefKind::Lifetime => {}
214 }
215 }
216 false
217 }
218
219 /// Returns the `GenericParamDef` with the given index.
220 pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
221 if let Some(index) = param_index.checked_sub(self.parent_count) {
222 &self.params[index]
223 } else {
224 tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
225 .param_at(param_index, tcx)
226 }
227 }
228
9c376795
FG
229 pub fn params_to(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx [GenericParamDef] {
230 if let Some(index) = param_index.checked_sub(self.parent_count) {
231 &self.params[..index]
232 } else {
233 tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
234 .params_to(param_index, tcx)
235 }
236 }
237
6a06907d
XL
238 /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
239 pub fn region_param(
240 &'tcx self,
241 param: &EarlyBoundRegion,
242 tcx: TyCtxt<'tcx>,
243 ) -> &'tcx GenericParamDef {
244 let param = self.param_at(param.index as usize, tcx);
245 match param.kind {
246 GenericParamDefKind::Lifetime => param,
247 _ => bug!("expected lifetime parameter, but found another generic parameter"),
248 }
249 }
250
251 /// Returns the `GenericParamDef` associated with this `ParamTy`.
252 pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
253 let param = self.param_at(param.index as usize, tcx);
254 match param.kind {
255 GenericParamDefKind::Type { .. } => param,
256 _ => bug!("expected type parameter, but found another generic parameter"),
257 }
258 }
259
260 /// Returns the `GenericParamDef` associated with this `ParamConst`.
261 pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
262 let param = self.param_at(param.index as usize, tcx);
263 match param.kind {
cdc7bbd5 264 GenericParamDefKind::Const { .. } => param,
6a06907d
XL
265 _ => bug!("expected const parameter, but found another generic parameter"),
266 }
267 }
94222f64
XL
268
269 /// Returns `true` if `params` has `impl Trait`.
270 pub fn has_impl_trait(&'tcx self) -> bool {
271 self.params.iter().any(|param| {
3c0e092e 272 matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. })
94222f64
XL
273 })
274 }
923072b8
FG
275
276 /// Returns the substs corresponding to the generic parameters
277 /// of this item, excluding `Self`.
278 ///
279 /// **This should only be used for diagnostics purposes.**
280 pub fn own_substs_no_defaults(
281 &'tcx self,
282 tcx: TyCtxt<'tcx>,
283 substs: &'tcx [ty::GenericArg<'tcx>],
284 ) -> &'tcx [ty::GenericArg<'tcx>] {
285 let mut own_params = self.parent_count..self.count();
286 if self.has_self && self.parent.is_none() {
287 own_params.start = 1;
288 }
289
290 // Filter the default arguments.
291 //
292 // This currently uses structural equality instead
f2b60f7d 293 // of semantic equivalence. While not ideal, that's
923072b8
FG
294 // good enough for now as this should only be used
295 // for diagnostics anyways.
296 own_params.end -= self
297 .params
298 .iter()
299 .rev()
300 .take_while(|param| {
301 param.default_value(tcx).map_or(false, |default| {
302 default.subst(tcx, substs) == substs[param.index as usize]
303 })
304 })
305 .count();
306
307 &substs[own_params]
308 }
309
310 /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`.
311 ///
312 /// **This should only be used for diagnostics purposes.**
313 pub fn own_substs(
314 &'tcx self,
315 substs: &'tcx [ty::GenericArg<'tcx>],
316 ) -> &'tcx [ty::GenericArg<'tcx>] {
317 let own = &substs[self.parent_count..][..self.params.len()];
318 if self.has_self && self.parent.is_none() { &own[1..] } else { &own }
319 }
6a06907d
XL
320}
321
322/// Bounds on generics.
323#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
324pub struct GenericPredicates<'tcx> {
325 pub parent: Option<DefId>,
326 pub predicates: &'tcx [(Predicate<'tcx>, Span)],
327}
328
329impl<'tcx> GenericPredicates<'tcx> {
330 pub fn instantiate(
331 &self,
332 tcx: TyCtxt<'tcx>,
333 substs: SubstsRef<'tcx>,
334 ) -> InstantiatedPredicates<'tcx> {
335 let mut instantiated = InstantiatedPredicates::empty();
336 self.instantiate_into(tcx, &mut instantiated, substs);
337 instantiated
338 }
339
340 pub fn instantiate_own(
341 &self,
342 tcx: TyCtxt<'tcx>,
343 substs: SubstsRef<'tcx>,
9c376795
FG
344 ) -> impl Iterator<Item = (Predicate<'tcx>, Span)> + DoubleEndedIterator + ExactSizeIterator
345 {
346 EarlyBinder(self.predicates).subst_iter_copied(tcx, substs)
6a06907d
XL
347 }
348
f2b60f7d 349 #[instrument(level = "debug", skip(self, tcx))]
6a06907d
XL
350 fn instantiate_into(
351 &self,
352 tcx: TyCtxt<'tcx>,
353 instantiated: &mut InstantiatedPredicates<'tcx>,
354 substs: SubstsRef<'tcx>,
355 ) {
356 if let Some(def_id) = self.parent {
357 tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
358 }
04454e1e
FG
359 instantiated
360 .predicates
361 .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)));
6a06907d
XL
362 instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
363 }
364
365 pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> {
366 let mut instantiated = InstantiatedPredicates::empty();
367 self.instantiate_identity_into(tcx, &mut instantiated);
368 instantiated
369 }
370
371 fn instantiate_identity_into(
372 &self,
373 tcx: TyCtxt<'tcx>,
374 instantiated: &mut InstantiatedPredicates<'tcx>,
375 ) {
376 if let Some(def_id) = self.parent {
377 tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
378 }
379 instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p));
380 instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
381 }
382}