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