diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs new file mode 100644 index 00000000000..79cd26f5668 --- /dev/null +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -0,0 +1,257 @@ +use crate::middle::resolve_lifetime::ObjectLifetimeDefault; +use crate::ty; +use crate::ty::subst::{Subst, SubstsRef}; +use rustc_ast as ast; +use rustc_data_structures::fx::FxHashMap; +use rustc_hir as hir; +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: Option, + }, + Const, +} + +impl GenericParamDefKind { + pub fn descr(&self) -> &'static str { + match self { + GenericParamDefKind::Lifetime => "lifetime", + GenericParamDefKind::Type { .. } => "type", + GenericParamDefKind::Const => "constant", + } + } + pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { + match self { + GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, + GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, + GenericParamDefKind::Const => { + ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } + } + } + } +} + +#[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") + } + } +} + +#[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 { + 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 => { + // FIXME(const_generics:defaults) + } + } + } + + 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"), + } + } +} + +/// 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, _)| 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, _)| 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)); + } +} diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 1a8f726d894..88c6a2166df 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -9,12 +9,12 @@ //! //! ["The `ty` module: representing types"]: https://rustc-dev-guide.rust-lang.org/ty.html -// ignore-tidy-filelength pub use self::fold::{TypeFoldable, TypeFolder, TypeVisitor}; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; pub use self::IntVarValue::*; pub use self::Variance::*; +pub use generics::*; pub use upvar::*; use crate::hir::exports::ExportMap; @@ -23,7 +23,6 @@ use crate::hir::place::{ }; use crate::ich::StableHashingContext; use crate::middle::cstore::CrateStoreDyn; -use crate::middle::resolve_lifetime::ObjectLifetimeDefault; use crate::mir::interpret::ErrorHandled; use crate::mir::{Body, GeneratorLayout}; use crate::traits::{self, Reveal}; @@ -112,6 +111,7 @@ mod consts; mod context; mod diagnostics; mod erase_regions; +mod generics; mod instance; mod list; mod structural_impls; @@ -698,252 +698,6 @@ impl ty::EarlyBoundRegion { } } -#[derive(Clone, Debug, TyEncodable, TyDecodable, HashStable)] -pub enum GenericParamDefKind { - Lifetime, - Type { - has_default: bool, - object_lifetime_default: ObjectLifetimeDefault, - synthetic: Option, - }, - Const, -} - -impl GenericParamDefKind { - pub fn descr(&self) -> &'static str { - match self { - GenericParamDefKind::Lifetime => "lifetime", - GenericParamDefKind::Type { .. } => "type", - GenericParamDefKind::Const => "constant", - } - } - pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { - match self { - GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, - GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const => { - ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } - } - } - } -} - -#[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") - } - } -} - -#[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 { - 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 => { - // FIXME(const_generics:defaults) - } - } - } - - 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"), - } - } -} - -/// 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, _)| 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, _)| 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)); - } -} - #[derive(Debug)] crate struct PredicateInner<'tcx> { kind: Binder>,