]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_middle/src/ty/generics.rs
Rollup merge of #82846 - GuillaumeGomez:doc-alias-list, r=jyn514
[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 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     },
21     Const,
22 }
23
24 impl GenericParamDefKind {
25     pub fn descr(&self) -> &'static str {
26         match self {
27             GenericParamDefKind::Lifetime => "lifetime",
28             GenericParamDefKind::Type { .. } => "type",
29             GenericParamDefKind::Const => "constant",
30         }
31     }
32     pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd {
33         match self {
34             GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
35             GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
36             GenericParamDefKind::Const => {
37                 ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
38             }
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     pub fn count(&self) -> usize {
95         self.parent_count + self.params.len()
96     }
97
98     pub fn own_counts(&self) -> GenericParamCount {
99         // We could cache this as a property of `GenericParamCount`, but
100         // the aim is to refactor this away entirely eventually and the
101         // presence of this method will be a constant reminder.
102         let mut own_counts = GenericParamCount::default();
103
104         for param in &self.params {
105             match param.kind {
106                 GenericParamDefKind::Lifetime => own_counts.lifetimes += 1,
107                 GenericParamDefKind::Type { .. } => own_counts.types += 1,
108                 GenericParamDefKind::Const => own_counts.consts += 1,
109             }
110         }
111
112         own_counts
113     }
114
115     pub fn own_defaults(&self) -> GenericParamCount {
116         let mut own_defaults = GenericParamCount::default();
117
118         for param in &self.params {
119             match param.kind {
120                 GenericParamDefKind::Lifetime => (),
121                 GenericParamDefKind::Type { has_default, .. } => {
122                     own_defaults.types += has_default as usize;
123                 }
124                 GenericParamDefKind::Const => {
125                     // FIXME(const_generics:defaults)
126                 }
127             }
128         }
129
130         own_defaults
131     }
132
133     pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool {
134         if self.own_requires_monomorphization() {
135             return true;
136         }
137
138         if let Some(parent_def_id) = self.parent {
139             let parent = tcx.generics_of(parent_def_id);
140             parent.requires_monomorphization(tcx)
141         } else {
142             false
143         }
144     }
145
146     pub fn own_requires_monomorphization(&self) -> bool {
147         for param in &self.params {
148             match param.kind {
149                 GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true,
150                 GenericParamDefKind::Lifetime => {}
151             }
152         }
153         false
154     }
155
156     /// Returns the `GenericParamDef` with the given index.
157     pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
158         if let Some(index) = param_index.checked_sub(self.parent_count) {
159             &self.params[index]
160         } else {
161             tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?"))
162                 .param_at(param_index, tcx)
163         }
164     }
165
166     /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
167     pub fn region_param(
168         &'tcx self,
169         param: &EarlyBoundRegion,
170         tcx: TyCtxt<'tcx>,
171     ) -> &'tcx GenericParamDef {
172         let param = self.param_at(param.index as usize, tcx);
173         match param.kind {
174             GenericParamDefKind::Lifetime => param,
175             _ => bug!("expected lifetime parameter, but found another generic parameter"),
176         }
177     }
178
179     /// Returns the `GenericParamDef` associated with this `ParamTy`.
180     pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef {
181         let param = self.param_at(param.index as usize, tcx);
182         match param.kind {
183             GenericParamDefKind::Type { .. } => param,
184             _ => bug!("expected type parameter, but found another generic parameter"),
185         }
186     }
187
188     /// Returns the `GenericParamDef` associated with this `ParamConst`.
189     pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef {
190         let param = self.param_at(param.index as usize, tcx);
191         match param.kind {
192             GenericParamDefKind::Const => param,
193             _ => bug!("expected const parameter, but found another generic parameter"),
194         }
195     }
196 }
197
198 /// Bounds on generics.
199 #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
200 pub struct GenericPredicates<'tcx> {
201     pub parent: Option<DefId>,
202     pub predicates: &'tcx [(Predicate<'tcx>, Span)],
203 }
204
205 impl<'tcx> GenericPredicates<'tcx> {
206     pub fn instantiate(
207         &self,
208         tcx: TyCtxt<'tcx>,
209         substs: SubstsRef<'tcx>,
210     ) -> InstantiatedPredicates<'tcx> {
211         let mut instantiated = InstantiatedPredicates::empty();
212         self.instantiate_into(tcx, &mut instantiated, substs);
213         instantiated
214     }
215
216     pub fn instantiate_own(
217         &self,
218         tcx: TyCtxt<'tcx>,
219         substs: SubstsRef<'tcx>,
220     ) -> InstantiatedPredicates<'tcx> {
221         InstantiatedPredicates {
222             predicates: self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)).collect(),
223             spans: self.predicates.iter().map(|(_, sp)| *sp).collect(),
224         }
225     }
226
227     fn instantiate_into(
228         &self,
229         tcx: TyCtxt<'tcx>,
230         instantiated: &mut InstantiatedPredicates<'tcx>,
231         substs: SubstsRef<'tcx>,
232     ) {
233         if let Some(def_id) = self.parent {
234             tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs);
235         }
236         instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p.subst(tcx, substs)));
237         instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp));
238     }
239
240     pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> {
241         let mut instantiated = InstantiatedPredicates::empty();
242         self.instantiate_identity_into(tcx, &mut instantiated);
243         instantiated
244     }
245
246     fn instantiate_identity_into(
247         &self,
248         tcx: TyCtxt<'tcx>,
249         instantiated: &mut InstantiatedPredicates<'tcx>,
250     ) {
251         if let Some(def_id) = self.parent {
252             tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated);
253         }
254         instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p));
255         instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s));
256     }
257 }