From 698f8c2f01ea549d77d7dc3338a12e04c11057b9 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:02:58 +0200 Subject: Adding upstream version 1.64.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_middle/src/ty/generics.rs | 349 +++++++++++++++++++++++++++++++ 1 file changed, 349 insertions(+) create mode 100644 compiler/rustc_middle/src/ty/generics.rs (limited to 'compiler/rustc_middle/src/ty/generics.rs') diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs new file mode 100644 index 000000000..add2df258 --- /dev/null +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -0,0 +1,349 @@ +use crate::middle::resolve_lifetime::ObjectLifetimeDefault; +use crate::ty; +use crate::ty::subst::{Subst, SubstsRef}; +use crate::ty::EarlyBinder; +use rustc_ast as ast; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir::def_id::DefId; +use rustc_span::symbol::Symbol; +use rustc_span::Span; + +use super::{EarlyBoundRegion, InstantiatedPredicates, ParamConst, ParamTy, Predicate, TyCtxt}; + +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] +pub enum GenericParamDefKind { + Lifetime, + Type { has_default: bool, object_lifetime_default: ObjectLifetimeDefault, synthetic: bool }, + Const { has_default: bool }, +} + +impl GenericParamDefKind { + pub fn descr(&self) -> &'static str { + match self { + GenericParamDefKind::Lifetime => "lifetime", + GenericParamDefKind::Type { .. } => "type", + GenericParamDefKind::Const { .. } => "constant", + } + } + pub fn to_ord(&self) -> ast::ParamKindOrd { + match self { + GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, + GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, + GenericParamDefKind::Const { .. } => ast::ParamKindOrd::Const, + } + } + + pub fn is_ty_or_const(&self) -> bool { + match self { + GenericParamDefKind::Lifetime => false, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => true, + } + } + + pub fn is_synthetic(&self) -> bool { + match self { + GenericParamDefKind::Type { synthetic, .. } => *synthetic, + _ => false, + } + } +} + +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] +pub struct GenericParamDef { + pub name: Symbol, + pub def_id: DefId, + pub index: u32, + + /// `pure_wrt_drop`, set by the (unsafe) `#[may_dangle]` attribute + /// on generic parameter `'a`/`T`, asserts data behind the parameter + /// `'a`/`T` won't be accessed during the parent type's `Drop` impl. + pub pure_wrt_drop: bool, + + pub kind: GenericParamDefKind, +} + +impl GenericParamDef { + pub fn to_early_bound_region_data(&self) -> ty::EarlyBoundRegion { + if let GenericParamDefKind::Lifetime = self.kind { + ty::EarlyBoundRegion { def_id: self.def_id, index: self.index, name: self.name } + } else { + bug!("cannot convert a non-lifetime parameter def to an early bound region") + } + } + + pub fn has_default(&self) -> bool { + match self.kind { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => has_default, + GenericParamDefKind::Lifetime => false, + } + } + + pub fn default_value<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + ) -> Option>> { + match self.kind { + GenericParamDefKind::Type { has_default, .. } if has_default => { + Some(tcx.bound_type_of(self.def_id).map_bound(|t| t.into())) + } + GenericParamDefKind::Const { has_default } if has_default => { + Some(tcx.bound_const_param_default(self.def_id).map_bound(|c| c.into())) + } + _ => None, + } + } +} + +#[derive(Default)] +pub struct GenericParamCount { + pub lifetimes: usize, + pub types: usize, + pub consts: usize, +} + +/// Information about the formal type/lifetime parameters associated +/// with an item or method. Analogous to `hir::Generics`. +/// +/// The ordering of parameters is the same as in `Subst` (excluding child generics): +/// `Self` (optionally), `Lifetime` params..., `Type` params... +#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] +pub struct Generics { + pub parent: Option, + pub parent_count: usize, + pub params: Vec, + + /// Reverse map to the `index` field of each `GenericParamDef`. + #[stable_hasher(ignore)] + pub param_def_id_to_index: FxHashMap, + + pub has_self: bool, + pub has_late_bound_regions: Option, +} + +impl<'tcx> Generics { + #[inline] + pub fn count(&self) -> usize { + self.parent_count + self.params.len() + } + + pub fn own_counts(&self) -> GenericParamCount { + // We could cache this as a property of `GenericParamCount`, but + // the aim is to refactor this away entirely eventually and the + // presence of this method will be a constant reminder. + let mut own_counts = GenericParamCount::default(); + + for param in &self.params { + match param.kind { + GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, + GenericParamDefKind::Type { .. } => own_counts.types += 1, + GenericParamDefKind::Const { .. } => own_counts.consts += 1, + } + } + + own_counts + } + + pub fn own_defaults(&self) -> GenericParamCount { + let mut own_defaults = GenericParamCount::default(); + + for param in &self.params { + match param.kind { + GenericParamDefKind::Lifetime => (), + GenericParamDefKind::Type { has_default, .. } => { + own_defaults.types += has_default as usize; + } + GenericParamDefKind::Const { has_default } => { + own_defaults.consts += has_default as usize; + } + } + } + + own_defaults + } + + pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool { + if self.own_requires_monomorphization() { + return true; + } + + if let Some(parent_def_id) = self.parent { + let parent = tcx.generics_of(parent_def_id); + parent.requires_monomorphization(tcx) + } else { + false + } + } + + pub fn own_requires_monomorphization(&self) -> bool { + for param in &self.params { + match param.kind { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + return true; + } + GenericParamDefKind::Lifetime => {} + } + } + false + } + + /// Returns the `GenericParamDef` with the given index. + pub fn param_at(&'tcx self, param_index: usize, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { + if let Some(index) = param_index.checked_sub(self.parent_count) { + &self.params[index] + } else { + tcx.generics_of(self.parent.expect("parent_count > 0 but no parent?")) + .param_at(param_index, tcx) + } + } + + /// Returns the `GenericParamDef` associated with this `EarlyBoundRegion`. + pub fn region_param( + &'tcx self, + param: &EarlyBoundRegion, + tcx: TyCtxt<'tcx>, + ) -> &'tcx GenericParamDef { + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Lifetime => param, + _ => bug!("expected lifetime parameter, but found another generic parameter"), + } + } + + /// Returns the `GenericParamDef` associated with this `ParamTy`. + pub fn type_param(&'tcx self, param: &ParamTy, tcx: TyCtxt<'tcx>) -> &'tcx GenericParamDef { + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Type { .. } => param, + _ => bug!("expected type parameter, but found another generic parameter"), + } + } + + /// Returns the `GenericParamDef` associated with this `ParamConst`. + pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { + let param = self.param_at(param.index as usize, tcx); + match param.kind { + GenericParamDefKind::Const { .. } => param, + _ => bug!("expected const parameter, but found another generic parameter"), + } + } + + /// Returns `true` if `params` has `impl Trait`. + pub fn has_impl_trait(&'tcx self) -> bool { + self.params.iter().any(|param| { + matches!(param.kind, ty::GenericParamDefKind::Type { synthetic: true, .. }) + }) + } + + /// Returns the substs corresponding to the generic parameters + /// of this item, excluding `Self`. + /// + /// **This should only be used for diagnostics purposes.** + pub fn own_substs_no_defaults( + &'tcx self, + tcx: TyCtxt<'tcx>, + substs: &'tcx [ty::GenericArg<'tcx>], + ) -> &'tcx [ty::GenericArg<'tcx>] { + let mut own_params = self.parent_count..self.count(); + if self.has_self && self.parent.is_none() { + own_params.start = 1; + } + + // Filter the default arguments. + // + // This currently uses structural equality instead + // of semantic equivalance. While not ideal, that's + // good enough for now as this should only be used + // for diagnostics anyways. + own_params.end -= self + .params + .iter() + .rev() + .take_while(|param| { + param.default_value(tcx).map_or(false, |default| { + default.subst(tcx, substs) == substs[param.index as usize] + }) + }) + .count(); + + &substs[own_params] + } + + /// Returns the substs corresponding to the generic parameters of this item, excluding `Self`. + /// + /// **This should only be used for diagnostics purposes.** + pub fn own_substs( + &'tcx self, + substs: &'tcx [ty::GenericArg<'tcx>], + ) -> &'tcx [ty::GenericArg<'tcx>] { + let own = &substs[self.parent_count..][..self.params.len()]; + if self.has_self && self.parent.is_none() { &own[1..] } else { &own } + } +} + +/// Bounds on generics. +#[derive(Copy, Clone, Default, Debug, TyEncodable, TyDecodable, HashStable)] +pub struct GenericPredicates<'tcx> { + pub parent: Option, + pub predicates: &'tcx [(Predicate<'tcx>, Span)], +} + +impl<'tcx> GenericPredicates<'tcx> { + pub fn instantiate( + &self, + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + ) -> InstantiatedPredicates<'tcx> { + let mut instantiated = InstantiatedPredicates::empty(); + self.instantiate_into(tcx, &mut instantiated, substs); + instantiated + } + + pub fn instantiate_own( + &self, + tcx: TyCtxt<'tcx>, + substs: SubstsRef<'tcx>, + ) -> InstantiatedPredicates<'tcx> { + InstantiatedPredicates { + predicates: self + .predicates + .iter() + .map(|(p, _)| EarlyBinder(*p).subst(tcx, substs)) + .collect(), + spans: self.predicates.iter().map(|(_, sp)| *sp).collect(), + } + } + + fn instantiate_into( + &self, + tcx: TyCtxt<'tcx>, + instantiated: &mut InstantiatedPredicates<'tcx>, + substs: SubstsRef<'tcx>, + ) { + if let Some(def_id) = self.parent { + tcx.predicates_of(def_id).instantiate_into(tcx, instantiated, substs); + } + instantiated + .predicates + .extend(self.predicates.iter().map(|(p, _)| EarlyBinder(*p).subst(tcx, substs))); + instantiated.spans.extend(self.predicates.iter().map(|(_, sp)| *sp)); + } + + pub fn instantiate_identity(&self, tcx: TyCtxt<'tcx>) -> InstantiatedPredicates<'tcx> { + let mut instantiated = InstantiatedPredicates::empty(); + self.instantiate_identity_into(tcx, &mut instantiated); + instantiated + } + + fn instantiate_identity_into( + &self, + tcx: TyCtxt<'tcx>, + instantiated: &mut InstantiatedPredicates<'tcx>, + ) { + if let Some(def_id) = self.parent { + tcx.predicates_of(def_id).instantiate_identity_into(tcx, instantiated); + } + instantiated.predicates.extend(self.predicates.iter().map(|(p, _)| p)); + instantiated.spans.extend(self.predicates.iter().map(|(_, s)| s)); + } +} -- cgit v1.2.3