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