2 use crate::ty
::{EarlyBinder, GenericArgsRef}
;
4 use rustc_data_structures
::fx
::FxHashMap
;
5 use rustc_hir
::def_id
::DefId
;
6 use rustc_span
::symbol
::{kw, Symbol}
;
9 use super::{Clause, EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Ty, TyCtxt}
;
11 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
12 pub enum GenericParamDefKind
{
14 Type { has_default: bool, synthetic: bool }
,
15 Const { has_default: bool, is_host_effect: bool }
,
18 impl GenericParamDefKind
{
19 pub fn descr(&self) -> &'
static str {
21 GenericParamDefKind
::Lifetime
=> "lifetime",
22 GenericParamDefKind
::Type { .. }
=> "type",
23 GenericParamDefKind
::Const { .. }
=> "constant",
26 pub fn to_ord(&self) -> ast
::ParamKindOrd
{
28 GenericParamDefKind
::Lifetime
=> ast
::ParamKindOrd
::Lifetime
,
29 GenericParamDefKind
::Type { .. }
| GenericParamDefKind
::Const { .. }
=> {
30 ast
::ParamKindOrd
::TypeOrConst
35 pub fn is_ty_or_const(&self) -> bool
{
37 GenericParamDefKind
::Lifetime
=> false,
38 GenericParamDefKind
::Type { .. }
| GenericParamDefKind
::Const { .. }
=> true,
42 pub fn is_synthetic(&self) -> bool
{
44 GenericParamDefKind
::Type { synthetic, .. }
=> *synthetic
,
50 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
51 pub struct GenericParamDef
{
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
,
61 pub kind
: GenericParamDefKind
,
64 impl 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 }
69 bug
!("cannot convert a non-lifetime parameter def to an early bound region")
73 pub fn is_anonymous_lifetime(&self) -> bool
{
75 GenericParamDefKind
::Lifetime
=> {
76 self.name
== kw
::UnderscoreLifetime
|| self.name
== kw
::Empty
82 pub fn is_host_effect(&self) -> bool
{
83 matches
!(self.kind
, GenericParamDefKind
::Const { is_host_effect: true, .. }
)
86 pub fn default_value
<'tcx
>(
89 ) -> Option
<EarlyBinder
<ty
::GenericArg
<'tcx
>>> {
91 GenericParamDefKind
::Type { has_default, .. }
if has_default
=> {
92 Some(tcx
.type_of(self.def_id
).map_bound(|t
| t
.into()))
94 GenericParamDefKind
::Const { has_default, .. }
if has_default
=> {
95 Some(tcx
.const_param_default(self.def_id
).map_bound(|c
| c
.into()))
101 pub fn to_error
<'tcx
>(
104 preceding_args
: &[ty
::GenericArg
<'tcx
>],
105 ) -> ty
::GenericArg
<'tcx
> {
107 ty
::GenericParamDefKind
::Lifetime
=> ty
::Region
::new_error_misc(tcx
).into(),
108 ty
::GenericParamDefKind
::Type { .. }
=> Ty
::new_misc_error(tcx
).into(),
109 ty
::GenericParamDefKind
::Const { .. }
=> ty
::Const
::new_misc_error(
111 tcx
.type_of(self.def_id
).instantiate(tcx
, preceding_args
),
119 pub struct GenericParamCount
{
120 pub lifetimes
: usize,
125 /// Information about the formal type/lifetime parameters associated
126 /// with an item or method. Analogous to `hir::Generics`.
128 /// The ordering of parameters is the same as in `Subst` (excluding child generics):
129 /// `Self` (optionally), `Lifetime` params..., `Type` params...
130 #[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)]
131 pub struct Generics
{
132 pub parent
: Option
<DefId
>,
133 pub parent_count
: usize,
134 pub params
: Vec
<GenericParamDef
>,
136 /// Reverse map to the `index` field of each `GenericParamDef`.
137 #[stable_hasher(ignore)]
138 pub param_def_id_to_index
: FxHashMap
<DefId
, u32>,
141 pub has_late_bound_regions
: Option
<Span
>,
143 // The index of the host effect when substituted. (i.e. might be index to parent args)
144 pub host_effect_index
: Option
<usize>,
147 impl<'tcx
> Generics
{
148 /// Looks through the generics and all parents to find the index of the
149 /// given param def-id. This is in comparison to the `param_def_id_to_index`
150 /// struct member, which only stores information about this item's own
152 pub fn param_def_id_to_index(&self, tcx
: TyCtxt
<'tcx
>, def_id
: DefId
) -> Option
<u32> {
153 if let Some(idx
) = self.param_def_id_to_index
.get(&def_id
) {
155 } else if let Some(parent
) = self.parent
{
156 let parent
= tcx
.generics_of(parent
);
157 parent
.param_def_id_to_index(tcx
, def_id
)
164 pub fn count(&self) -> usize {
165 self.parent_count
+ self.params
.len()
168 pub fn own_counts(&self) -> GenericParamCount
{
169 // We could cache this as a property of `GenericParamCount`, but
170 // the aim is to refactor this away entirely eventually and the
171 // presence of this method will be a constant reminder.
172 let mut own_counts
= GenericParamCount
::default();
174 for param
in &self.params
{
176 GenericParamDefKind
::Lifetime
=> own_counts
.lifetimes
+= 1,
177 GenericParamDefKind
::Type { .. }
=> own_counts
.types
+= 1,
178 GenericParamDefKind
::Const { .. }
=> own_counts
.consts
+= 1,
185 pub fn own_defaults(&self) -> GenericParamCount
{
186 let mut own_defaults
= GenericParamCount
::default();
188 for param
in &self.params
{
190 GenericParamDefKind
::Lifetime
=> (),
191 GenericParamDefKind
::Type { has_default, .. }
=> {
192 own_defaults
.types
+= has_default
as usize;
194 GenericParamDefKind
::Const { has_default, .. }
=> {
195 own_defaults
.consts
+= has_default
as usize;
203 pub fn requires_monomorphization(&self, tcx
: TyCtxt
<'tcx
>) -> bool
{
204 if self.own_requires_monomorphization() {
208 if let Some(parent_def_id
) = self.parent
{
209 let parent
= tcx
.generics_of(parent_def_id
);
210 parent
.requires_monomorphization(tcx
)
216 pub fn own_requires_monomorphization(&self) -> bool
{
217 for param
in &self.params
{
219 GenericParamDefKind
::Type { .. }
220 | GenericParamDefKind
::Const { is_host_effect: false, .. }
=> {
223 GenericParamDefKind
::Lifetime
224 | GenericParamDefKind
::Const { is_host_effect: true, .. }
=> {}
230 /// Returns the `GenericParamDef` with the given index.
231 pub fn param_at(&'tcx
self, param_index
: usize, tcx
: TyCtxt
<'tcx
>) -> &'tcx GenericParamDef
{
232 if let Some(index
) = param_index
.checked_sub(self.parent_count
) {
235 tcx
.generics_of(self.parent
.expect("parent_count > 0 but no parent?"))
236 .param_at(param_index
, tcx
)
240 /// Returns the `GenericParamDef` with the given index if available.
245 ) -> Option
<&'tcx GenericParamDef
> {
246 if let Some(index
) = param_index
.checked_sub(self.parent_count
) {
247 self.params
.get(index
)
249 tcx
.generics_of(self.parent
.expect("parent_count > 0 but no parent?"))
250 .opt_param_at(param_index
, tcx
)
254 pub fn params_to(&'tcx
self, param_index
: usize, tcx
: TyCtxt
<'tcx
>) -> &'tcx
[GenericParamDef
] {
255 if let Some(index
) = param_index
.checked_sub(self.parent_count
) {
256 &self.params
[..index
]
258 tcx
.generics_of(self.parent
.expect("parent_count > 0 but no parent?"))
259 .params_to(param_index
, tcx
)
263 /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`.
266 param
: &EarlyBoundRegion
,
268 ) -> &'tcx GenericParamDef
{
269 let param
= self.param_at(param
.index
as usize, tcx
);
271 GenericParamDefKind
::Lifetime
=> param
,
272 _
=> bug
!("expected lifetime parameter, but found another generic parameter"),
276 /// Returns the `GenericParamDef` associated with this `ParamTy`.
277 pub fn type_param(&'tcx
self, param
: &ParamTy
, tcx
: TyCtxt
<'tcx
>) -> &'tcx GenericParamDef
{
278 let param
= self.param_at(param
.index
as usize, tcx
);
280 GenericParamDefKind
::Type { .. }
=> param
,
281 _
=> bug
!("expected type parameter, but found another generic parameter"),
285 /// Returns the `GenericParamDef` associated with this `ParamTy` if it belongs to this
287 pub fn opt_type_param(
291 ) -> Option
<&'tcx GenericParamDef
> {
292 let param
= self.opt_param_at(param
.index
as usize, tcx
)?
;
294 GenericParamDefKind
::Type { .. }
=> Some(param
),
299 /// Returns the `GenericParamDef` associated with this `ParamConst`.
300 pub fn const_param(&'tcx
self, param
: &ParamConst
, tcx
: TyCtxt
<'tcx
>) -> &GenericParamDef
{
301 let param
= self.param_at(param
.index
as usize, tcx
);
303 GenericParamDefKind
::Const { .. }
=> param
,
304 _
=> bug
!("expected const parameter, but found another generic parameter"),
308 /// Returns `true` if `params` has `impl Trait`.
309 pub fn has_impl_trait(&'tcx
self) -> bool
{
310 self.params
.iter().any(|param
| {
311 matches
!(param
.kind
, ty
::GenericParamDefKind
::Type { synthetic: true, .. }
)
315 /// Returns the args corresponding to the generic parameters
316 /// of this item, excluding `Self`.
318 /// **This should only be used for diagnostics purposes.**
319 pub fn own_args_no_defaults(
322 args
: &'tcx
[ty
::GenericArg
<'tcx
>],
323 ) -> &'tcx
[ty
::GenericArg
<'tcx
>] {
324 let mut own_params
= self.parent_count
..self.count();
325 if self.has_self
&& self.parent
.is_none() {
326 own_params
.start
= 1;
329 // Filter the default arguments.
331 // This currently uses structural equality instead
332 // of semantic equivalence. While not ideal, that's
333 // good enough for now as this should only be used
334 // for diagnostics anyways.
335 own_params
.end
-= self
339 .take_while(|param
| {
340 param
.default_value(tcx
).is_some_and(|default| {
341 default.instantiate(tcx
, args
) == args
[param
.index
as usize]
349 /// Returns the args corresponding to the generic parameters of this item, excluding `Self`.
351 /// **This should only be used for diagnostics purposes.**
354 args
: &'tcx
[ty
::GenericArg
<'tcx
>],
355 ) -> &'tcx
[ty
::GenericArg
<'tcx
>] {
356 let own
= &args
[self.parent_count
..][..self.params
.len()];
357 if self.has_self
&& self.parent
.is_none() { &own[1..] }
else { &own }
361 /// Bounds on generics.
362 #[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)]
363 pub struct GenericPredicates
<'tcx
> {
364 pub parent
: Option
<DefId
>,
365 pub predicates
: &'tcx
[(Clause
<'tcx
>, Span
)],
368 impl<'tcx
> GenericPredicates
<'tcx
> {
372 args
: GenericArgsRef
<'tcx
>,
373 ) -> InstantiatedPredicates
<'tcx
> {
374 let mut instantiated
= InstantiatedPredicates
::empty();
375 self.instantiate_into(tcx
, &mut instantiated
, args
);
379 pub fn instantiate_own(
382 args
: GenericArgsRef
<'tcx
>,
383 ) -> impl Iterator
<Item
= (Clause
<'tcx
>, Span
)> + DoubleEndedIterator
+ ExactSizeIterator
{
384 EarlyBinder
::bind(self.predicates
).iter_instantiated_copied(tcx
, args
)
387 #[instrument(level = "debug", skip(self, tcx))]
391 instantiated
: &mut InstantiatedPredicates
<'tcx
>,
392 args
: GenericArgsRef
<'tcx
>,
394 if let Some(def_id
) = self.parent
{
395 tcx
.predicates_of(def_id
).instantiate_into(tcx
, instantiated
, args
);
397 instantiated
.predicates
.extend(
398 self.predicates
.iter().map(|(p
, _
)| EarlyBinder
::bind(*p
).instantiate(tcx
, args
)),
400 instantiated
.spans
.extend(self.predicates
.iter().map(|(_
, sp
)| *sp
));
403 pub fn instantiate_identity(&self, tcx
: TyCtxt
<'tcx
>) -> InstantiatedPredicates
<'tcx
> {
404 let mut instantiated
= InstantiatedPredicates
::empty();
405 self.instantiate_identity_into(tcx
, &mut instantiated
);
409 fn instantiate_identity_into(
412 instantiated
: &mut InstantiatedPredicates
<'tcx
>,
414 if let Some(def_id
) = self.parent
{
415 tcx
.predicates_of(def_id
).instantiate_identity_into(tcx
, instantiated
);
417 instantiated
.predicates
.extend(self.predicates
.iter().map(|(p
, _
)| p
));
418 instantiated
.spans
.extend(self.predicates
.iter().map(|(_
, s
)| s
));