summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_type_ir
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_type_ir')
-rw-r--r--compiler/rustc_type_ir/Cargo.toml21
-rw-r--r--compiler/rustc_type_ir/src/canonical.rs257
-rw-r--r--compiler/rustc_type_ir/src/const_kind.rs133
-rw-r--r--compiler/rustc_type_ir/src/debug.rs44
-rw-r--r--compiler/rustc_type_ir/src/flags.rs18
-rw-r--r--compiler/rustc_type_ir/src/fold.rs34
-rw-r--r--compiler/rustc_type_ir/src/infcx.rs40
-rw-r--r--compiler/rustc_type_ir/src/interner.rs128
-rw-r--r--compiler/rustc_type_ir/src/lib.rs107
-rw-r--r--compiler/rustc_type_ir/src/macros.rs2
-rw-r--r--compiler/rustc_type_ir/src/predicate_kind.rs188
-rw-r--r--compiler/rustc_type_ir/src/region_kind.rs105
-rw-r--r--compiler/rustc_type_ir/src/ty_info.rs12
-rw-r--r--compiler/rustc_type_ir/src/ty_kind.rs243
-rw-r--r--compiler/rustc_type_ir/src/visit.rs6
15 files changed, 810 insertions, 528 deletions
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index b39ba3059..3a08d89cc 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -7,9 +7,20 @@ edition = "2021"
# tidy-alphabetical-start
bitflags = "1.2.1"
derivative = "2.2.0"
-rustc_data_structures = { path = "../rustc_data_structures" }
-rustc_index = { path = "../rustc_index" }
-rustc_macros = { path = "../rustc_macros" }
-rustc_serialize = { path = "../rustc_serialize" }
-smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
+rustc_data_structures = { path = "../rustc_data_structures", optional = true }
+rustc_index = { path = "../rustc_index", default-features = false }
+rustc_macros = { path = "../rustc_macros", optional = true }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
+smallvec = { version = "1.8.1" }
# tidy-alphabetical-end
+
+[features]
+default = ["nightly"]
+nightly = [
+ "smallvec/may_dangle",
+ "smallvec/union",
+ "rustc_index/nightly",
+ "rustc_serialize",
+ "rustc_data_structures",
+ "rustc_macros",
+]
diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs
index ace9eade7..5bc2bfe28 100644
--- a/compiler/rustc_type_ir/src/canonical.rs
+++ b/compiler/rustc_type_ir/src/canonical.rs
@@ -2,18 +2,16 @@ use std::fmt;
use std::hash::Hash;
use std::ops::ControlFlow;
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
-
use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{HashStableContext, Interner, UniverseIndex};
+use crate::{Interner, PlaceholderLike, UniverseIndex};
/// A "canonicalized" type `V` is one where all free inference
/// variables have been rewritten to "canonical vars". These are
/// numbered starting from 0 in order of first appearance.
#[derive(derivative::Derivative)]
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub struct Canonical<I: Interner, V> {
pub value: V,
pub max_universe: UniverseIndex,
@@ -60,17 +58,6 @@ impl<I: Interner, V> Canonical<I, V> {
}
}
-impl<CTX: HashStableContext, I: Interner, V: HashStable<CTX>> HashStable<CTX> for Canonical<I, V>
-where
- I::CanonicalVars: HashStable<CTX>,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- self.value.hash_stable(hcx, hasher);
- self.max_universe.hash_stable(hcx, hasher);
- self.variables.hash_stable(hcx, hasher);
- }
-}
-
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
@@ -126,3 +113,243 @@ where
self.variables.visit_with(folder)
}
}
+
+/// Information about a canonical variable that is included with the
+/// canonical value. This is sufficient information for code to create
+/// a copy of the canonical value in some other inference context,
+/// with fresh inference variables replacing the canonical values.
+#[derive(derivative::Derivative)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub struct CanonicalVarInfo<I: Interner> {
+ pub kind: CanonicalVarKind<I>,
+}
+
+impl<I: Interner> PartialEq for CanonicalVarInfo<I> {
+ fn eq(&self, other: &Self) -> bool {
+ self.kind == other.kind
+ }
+}
+
+impl<I: Interner> Eq for CanonicalVarInfo<I> {}
+
+impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
+where
+ I::Ty: TypeVisitable<I>,
+{
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ self.kind.visit_with(visitor)
+ }
+}
+
+impl<I: Interner> TypeFoldable<I> for CanonicalVarInfo<I>
+where
+ I::Ty: TypeFoldable<I>,
+{
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? })
+ }
+}
+
+impl<I: Interner> CanonicalVarInfo<I> {
+ pub fn universe(self) -> UniverseIndex {
+ self.kind.universe()
+ }
+
+ #[must_use]
+ pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo<I> {
+ CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
+ }
+
+ pub fn is_existential(&self) -> bool {
+ match self.kind {
+ CanonicalVarKind::Ty(_) => true,
+ CanonicalVarKind::PlaceholderTy(_) => false,
+ CanonicalVarKind::Region(_) => true,
+ CanonicalVarKind::PlaceholderRegion(..) => false,
+ CanonicalVarKind::Const(..) => true,
+ CanonicalVarKind::PlaceholderConst(_, _) => false,
+ CanonicalVarKind::Effect => true,
+ }
+ }
+
+ pub fn is_region(&self) -> bool {
+ match self.kind {
+ CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::PlaceholderTy(_)
+ | CanonicalVarKind::Const(_, _)
+ | CanonicalVarKind::PlaceholderConst(_, _)
+ | CanonicalVarKind::Effect => false,
+ }
+ }
+
+ pub fn expect_placeholder_index(self) -> usize {
+ match self.kind {
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::Region(_)
+ | CanonicalVarKind::Const(_, _)
+ | CanonicalVarKind::Effect => panic!("expected placeholder: {self:?}"),
+
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.var().as_usize(),
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.var().as_usize(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.var().as_usize(),
+ }
+ }
+}
+
+/// Describes the "kind" of the canonical variable. This is a "kind"
+/// in the type-theory sense of the term -- i.e., a "meta" type system
+/// that analyzes type-like values.
+#[derive(derivative::Derivative)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum CanonicalVarKind<I: Interner> {
+ /// Some kind of type inference variable.
+ Ty(CanonicalTyVarKind),
+
+ /// A "placeholder" that represents "any type".
+ PlaceholderTy(I::PlaceholderTy),
+
+ /// Region variable `'?R`.
+ Region(UniverseIndex),
+
+ /// A "placeholder" that represents "any region". Created when you
+ /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
+ /// bound region `'a`.
+ PlaceholderRegion(I::PlaceholderRegion),
+
+ /// Some kind of const inference variable.
+ Const(UniverseIndex, I::Ty),
+
+ /// Effect variable `'?E`.
+ Effect,
+
+ /// A "placeholder" that represents "any const".
+ PlaceholderConst(I::PlaceholderConst, I::Ty),
+}
+
+impl<I: Interner> PartialEq for CanonicalVarKind<I> {
+ fn eq(&self, other: &Self) -> bool {
+ match (self, other) {
+ (Self::Ty(l0), Self::Ty(r0)) => l0 == r0,
+ (Self::PlaceholderTy(l0), Self::PlaceholderTy(r0)) => l0 == r0,
+ (Self::Region(l0), Self::Region(r0)) => l0 == r0,
+ (Self::PlaceholderRegion(l0), Self::PlaceholderRegion(r0)) => l0 == r0,
+ (Self::Const(l0, l1), Self::Const(r0, r1)) => l0 == r0 && l1 == r1,
+ (Self::PlaceholderConst(l0, l1), Self::PlaceholderConst(r0, r1)) => {
+ l0 == r0 && l1 == r1
+ }
+ _ => std::mem::discriminant(self) == std::mem::discriminant(other),
+ }
+ }
+}
+
+impl<I: Interner> Eq for CanonicalVarKind<I> {}
+
+impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
+where
+ I::Ty: TypeVisitable<I>,
+{
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
+ match self {
+ CanonicalVarKind::Ty(_)
+ | CanonicalVarKind::PlaceholderTy(_)
+ | CanonicalVarKind::Region(_)
+ | CanonicalVarKind::PlaceholderRegion(_)
+ | CanonicalVarKind::Effect => ControlFlow::Continue(()),
+ CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
+ ty.visit_with(visitor)
+ }
+ }
+ }
+}
+
+impl<I: Interner> TypeFoldable<I> for CanonicalVarKind<I>
+where
+ I::Ty: TypeFoldable<I>,
+{
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(match self {
+ CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind),
+ CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind),
+ CanonicalVarKind::Const(kind, ty) => {
+ CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?)
+ }
+ CanonicalVarKind::PlaceholderTy(placeholder) => {
+ CanonicalVarKind::PlaceholderTy(placeholder)
+ }
+ CanonicalVarKind::PlaceholderRegion(placeholder) => {
+ CanonicalVarKind::PlaceholderRegion(placeholder)
+ }
+ CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+ CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?)
+ }
+ CanonicalVarKind::Effect => CanonicalVarKind::Effect,
+ })
+ }
+}
+
+impl<I: Interner> CanonicalVarKind<I> {
+ pub fn universe(self) -> UniverseIndex {
+ match self {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
+ CanonicalVarKind::Region(ui) => ui,
+ CanonicalVarKind::Const(ui, _) => ui,
+ CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
+ CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
+ CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),
+ CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
+ UniverseIndex::ROOT
+ }
+ CanonicalVarKind::Effect => UniverseIndex::ROOT,
+ }
+ }
+
+ /// Replaces the universe of this canonical variable with `ui`.
+ ///
+ /// In case this is a float or int variable, this causes an ICE if
+ /// the updated universe is not the root.
+ pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind<I> {
+ match self {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
+ CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
+ }
+ CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
+ CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
+
+ CanonicalVarKind::PlaceholderTy(placeholder) => {
+ CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
+ }
+ CanonicalVarKind::PlaceholderRegion(placeholder) => {
+ CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
+ }
+ CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
+ CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
+ }
+ CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
+ | CanonicalVarKind::Effect => {
+ assert_eq!(ui, UniverseIndex::ROOT);
+ self
+ }
+ }
+ }
+}
+
+/// Rust actually has more than one category of type variables;
+/// notably, the type variables we create for literals (e.g., 22 or
+/// 22.) can only be instantiated with integral/float types (e.g.,
+/// usize or f32). In order to faithfully reproduce a type, we need to
+/// know what set of types a given type variable can be unified with.
+#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
+pub enum CanonicalTyVarKind {
+ /// General type variable `?T` that can be unified with arbitrary types.
+ General(UniverseIndex),
+
+ /// Integral type variable `?I` (that can only be unified with integral types).
+ Int,
+
+ /// Floating-point type variable `?F` (that can only be unified with float types).
+ Float,
+}
diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs
index 33782b13c..0aaaad5af 100644
--- a/compiler/rustc_type_ir/src/const_kind.rs
+++ b/compiler/rustc_type_ir/src/const_kind.rs
@@ -1,8 +1,8 @@
-use rustc_data_structures::stable_hasher::HashStable;
-use rustc_data_structures::stable_hasher::StableHasher;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt;
-use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
use self::ConstKind::*;
@@ -10,19 +10,20 @@ use self::ConstKind::*;
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
+ Copy(bound = ""),
PartialOrd(bound = ""),
PartialOrd = "feature_allow_slow_enum",
Ord(bound = ""),
Ord = "feature_allow_slow_enum",
Hash(bound = "")
)]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ConstKind<I: Interner> {
/// A const generic parameter.
Param(I::ParamConst),
/// Infer the value of the const.
- Infer(I::InferConst),
+ Infer(InferConst),
/// Bound const variable, used only when preparing a trait query.
Bound(DebruijnIndex, I::BoundConst),
@@ -47,48 +48,6 @@ pub enum ConstKind<I: Interner> {
Expr(I::ExprConst),
}
-const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
- match value {
- Param(_) => 0,
- Infer(_) => 1,
- Bound(_, _) => 2,
- Placeholder(_) => 3,
- Unevaluated(_) => 4,
- Value(_) => 5,
- Error(_) => 6,
- Expr(_) => 7,
- }
-}
-
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
-where
- I::ParamConst: HashStable<CTX>,
- I::InferConst: HashStable<CTX>,
- I::BoundConst: HashStable<CTX>,
- I::PlaceholderConst: HashStable<CTX>,
- I::AliasConst: HashStable<CTX>,
- I::ValueConst: HashStable<CTX>,
- I::ErrorGuaranteed: HashStable<CTX>,
- I::ExprConst: HashStable<CTX>,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- const_kind_discriminant(self).hash_stable(hcx, hasher);
- match self {
- Param(p) => p.hash_stable(hcx, hasher),
- Infer(i) => i.hash_stable(hcx, hasher),
- Bound(d, b) => {
- d.hash_stable(hcx, hasher);
- b.hash_stable(hcx, hasher);
- }
- Placeholder(p) => p.hash_stable(hcx, hasher),
- Unevaluated(u) => u.hash_stable(hcx, hasher),
- Value(v) => v.hash_stable(hcx, hasher),
- Error(e) => e.hash_stable(hcx, hasher),
- Expr(e) => e.hash_stable(hcx, hasher),
- }
- }
-}
-
impl<I: Interner> PartialEq for ConstKind<I> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -123,7 +82,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
match this.data {
Param(param) => write!(f, "{param:?}"),
Infer(var) => write!(f, "{:?}", &this.wrap(var)),
- Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
+ Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
Unevaluated(uv) => {
write!(f, "{:?}", &this.wrap(uv))
@@ -134,3 +93,81 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
}
}
}
+
+rustc_index::newtype_index! {
+ /// A **`const`** **v**ariable **ID**.
+ #[encodable]
+ #[orderable]
+ #[debug_format = "?{}c"]
+ #[gate_rustc_only]
+ pub struct ConstVid {}
+}
+
+rustc_index::newtype_index! {
+ /// An **effect** **v**ariable **ID**.
+ ///
+ /// Handling effect infer variables happens separately from const infer variables
+ /// because we do not want to reuse any of the const infer machinery. If we try to
+ /// relate an effect variable with a normal one, we would ICE, which can catch bugs
+ /// where we are not correctly using the effect var for an effect param. Fallback
+ /// is also implemented on top of having separate effect and normal const variables.
+ #[encodable]
+ #[orderable]
+ #[debug_format = "?{}e"]
+ #[gate_rustc_only]
+ pub struct EffectVid {}
+}
+
+/// An inference variable for a const, for use in const generics.
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
+pub enum InferConst {
+ /// Infer the value of the const.
+ Var(ConstVid),
+ /// Infer the value of the effect.
+ ///
+ /// For why this is separate from the `Var` variant above, see the
+ /// documentation on `EffectVid`.
+ EffectVar(EffectVid),
+ /// A fresh const variable. See `infer::freshen` for more details.
+ Fresh(u32),
+}
+
+impl fmt::Debug for InferConst {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match self {
+ InferConst::Var(var) => write!(f, "{var:?}"),
+ InferConst::EffectVar(var) => write!(f, "{var:?}"),
+ InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
+ }
+ }
+}
+impl<I: Interner> DebugWithInfcx<I> for InferConst {
+ fn fmt<Infcx: InferCtxtLike<Interner = I>>(
+ this: WithInfcx<'_, Infcx, &Self>,
+ f: &mut core::fmt::Formatter<'_>,
+ ) -> core::fmt::Result {
+ match *this.data {
+ InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) {
+ None => write!(f, "{:?}", this.data),
+ Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
+ },
+ InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
+ InferConst::Fresh(_) => {
+ unreachable!()
+ }
+ }
+ }
+}
+
+#[cfg(feature = "nightly")]
+impl<CTX> HashStable<CTX> for InferConst {
+ fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
+ match self {
+ InferConst::Var(_) | InferConst::EffectVar(_) => {
+ panic!("const variables should not be hashed: {self:?}")
+ }
+ InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
+ }
+ }
+}
diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs
index 4ea3eb3e8..9c8e45b43 100644
--- a/compiler/rustc_type_ir/src/debug.rs
+++ b/compiler/rustc_type_ir/src/debug.rs
@@ -1,36 +1,46 @@
-use crate::{Interner, UniverseIndex};
+use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};
use core::fmt;
use std::marker::PhantomData;
-pub trait InferCtxtLike {
- type Interner: Interner;
+pub struct NoInfcx<I>(PhantomData<I>);
- fn universe_of_ty(&self, ty: <Self::Interner as Interner>::InferTy) -> Option<UniverseIndex>;
+impl<I: Interner> InferCtxtLike for NoInfcx<I> {
+ type Interner = I;
- fn universe_of_lt(
- &self,
- lt: <Self::Interner as Interner>::InferRegion,
- ) -> Option<UniverseIndex>;
+ fn interner(&self) -> Self::Interner {
+ unreachable!()
+ }
- fn universe_of_ct(&self, ct: <Self::Interner as Interner>::InferConst)
- -> Option<UniverseIndex>;
-}
+ fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
+ None
+ }
-pub struct NoInfcx<I>(PhantomData<I>);
+ fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
+ None
+ }
-impl<I: Interner> InferCtxtLike for NoInfcx<I> {
- type Interner = I;
+ fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
+ None
+ }
- fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
+ fn root_ty_var(&self, vid: TyVid) -> TyVid {
+ vid
+ }
+
+ fn probe_ty_var(&self, _vid: TyVid) -> Option<I::Ty> {
None
}
- fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
+ fn opportunistic_resolve_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
None
}
- fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
+ fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
+ vid
+ }
+
+ fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
None
}
}
diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs
index 8472a0845..af741a0a3 100644
--- a/compiler/rustc_type_ir/src/flags.rs
+++ b/compiler/rustc_type_ir/src/flags.rs
@@ -8,7 +8,7 @@ bitflags! {
// required.
/// Does this have `Param`?
const HAS_TY_PARAM = 1 << 0;
- /// Does this have `ReEarlyBound`?
+ /// Does this have `ReEarlyParam`?
const HAS_RE_PARAM = 1 << 1;
/// Does this have `ConstKind::Param`?
const HAS_CT_PARAM = 1 << 2;
@@ -85,20 +85,20 @@ bitflags! {
const HAS_ERROR = 1 << 14;
/// Does this have any region that "appears free" in the type?
- /// Basically anything but `ReLateBound` and `ReErased`.
+ /// Basically anything but `ReBound` and `ReErased`.
const HAS_FREE_REGIONS = 1 << 15;
- /// Does this have any `ReLateBound` regions?
- const HAS_RE_LATE_BOUND = 1 << 16;
+ /// Does this have any `ReBound` regions?
+ const HAS_RE_BOUND = 1 << 16;
/// Does this have any `Bound` types?
- const HAS_TY_LATE_BOUND = 1 << 17;
+ const HAS_TY_BOUND = 1 << 17;
/// Does this have any `ConstKind::Bound` consts?
- const HAS_CT_LATE_BOUND = 1 << 18;
+ const HAS_CT_BOUND = 1 << 18;
/// Does this have any bound variables?
/// Used to check if a global bound is safe to evaluate.
- const HAS_LATE_BOUND = TypeFlags::HAS_RE_LATE_BOUND.bits
- | TypeFlags::HAS_TY_LATE_BOUND.bits
- | TypeFlags::HAS_CT_LATE_BOUND.bits;
+ const HAS_BOUND_VARS = TypeFlags::HAS_RE_BOUND.bits
+ | TypeFlags::HAS_TY_BOUND.bits
+ | TypeFlags::HAS_CT_BOUND.bits;
/// Does this have any `ReErased` regions?
const HAS_RE_ERASED = 1 << 19;
diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs
index fc56400df..8d4025883 100644
--- a/compiler/rustc_type_ir/src/fold.rs
+++ b/compiler/rustc_type_ir/src/fold.rs
@@ -45,12 +45,18 @@
//! - u.fold_with(folder)
//! ```
-use rustc_data_structures::sync::Lrc;
use rustc_index::{Idx, IndexVec};
use std::mem;
+use crate::Lrc;
use crate::{visit::TypeVisitable, Interner};
+#[cfg(feature = "nightly")]
+type Never = !;
+
+#[cfg(not(feature = "nightly"))]
+type Never = std::convert::Infallible;
+
/// This trait is implemented for every type that can be folded,
/// providing the skeleton of the traversal.
///
@@ -79,7 +85,10 @@ pub trait TypeFoldable<I: Interner>: TypeVisitable<I> {
/// folders. Do not override this method, to ensure coherence with
/// `try_fold_with`.
fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
- self.try_fold_with(folder).into_ok()
+ match self.try_fold_with(folder) {
+ Ok(t) => t,
+ Err(e) => match e {},
+ }
}
}
@@ -100,7 +109,10 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
/// infallible folders. Do not override this method, to ensure coherence
/// with `try_super_fold_with`.
fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
- self.try_super_fold_with(folder).into_ok()
+ match self.try_super_fold_with(folder) {
+ Ok(t) => t,
+ Err(e) => match e {},
+ }
}
}
@@ -113,7 +125,7 @@ pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
/// A blanket implementation of [`FallibleTypeFolder`] will defer to
/// the infallible methods of this trait to ensure that the two APIs
/// are coherent.
-pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = !> {
+pub trait TypeFolder<I: Interner>: FallibleTypeFolder<I, Error = Never> {
fn interner(&self) -> I;
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
@@ -208,13 +220,13 @@ impl<I: Interner, F> FallibleTypeFolder<I> for F
where
F: TypeFolder<I>,
{
- type Error = !;
+ type Error = Never;
fn interner(&self) -> I {
TypeFolder::interner(self)
}
- fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, !>
+ fn try_fold_binder<T>(&mut self, t: I::Binder<T>) -> Result<I::Binder<T>, Never>
where
T: TypeFoldable<I>,
I::Binder<T>: TypeSuperFoldable<I>,
@@ -222,25 +234,25 @@ where
Ok(self.fold_binder(t))
}
- fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, !>
+ fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Never>
where
I::Ty: TypeSuperFoldable<I>,
{
Ok(self.fold_ty(t))
}
- fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, !> {
+ fn try_fold_region(&mut self, r: I::Region) -> Result<I::Region, Never> {
Ok(self.fold_region(r))
}
- fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, !>
+ fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Never>
where
I::Const: TypeSuperFoldable<I>,
{
Ok(self.fold_const(c))
}
- fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, !>
+ fn try_fold_predicate(&mut self, p: I::Predicate) -> Result<I::Predicate, Never>
where
I::Predicate: TypeSuperFoldable<I>,
{
@@ -311,7 +323,7 @@ impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Lrc<T> {
// Call to `Lrc::make_mut` above guarantees that `unique` is the
// sole reference to the contained value, so we can avoid doing
// a checked `get_mut` here.
- let slot = Lrc::get_mut_unchecked(&mut unique);
+ let slot = Lrc::get_mut(&mut unique).unwrap_unchecked();
// Semantically move the contained type out from `unique`, fold
// it, then move the folded value back into `unique`. Should
diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs
new file mode 100644
index 000000000..28b71f0ea
--- /dev/null
+++ b/compiler/rustc_type_ir/src/infcx.rs
@@ -0,0 +1,40 @@
+use crate::{ConstVid, Interner, TyVid, UniverseIndex};
+
+pub trait InferCtxtLike {
+ type Interner: Interner;
+
+ fn interner(&self) -> Self::Interner;
+
+ fn universe_of_ty(&self, ty: TyVid) -> Option<UniverseIndex>;
+
+ /// Resolve `TyVid` to its root `TyVid`.
+ fn root_ty_var(&self, vid: TyVid) -> TyVid;
+
+ /// Resolve `TyVid` to its inferred type, if it has been equated with a non-infer type.
+ fn probe_ty_var(&self, vid: TyVid) -> Option<<Self::Interner as Interner>::Ty>;
+
+ fn universe_of_lt(
+ &self,
+ lt: <Self::Interner as Interner>::InferRegion,
+ ) -> Option<UniverseIndex>;
+
+ /// Resolve `InferRegion` to its inferred region, if it has been equated with
+ /// a non-infer region.
+ ///
+ /// FIXME: This has slightly different semantics than `{probe,resolve}_{ty,ct}_var`,
+ /// that has to do with the fact unlike `Ty` or `Const` vars, in rustc, we may
+ /// not always be able to *name* the root region var from the universe of the
+ /// var we're trying to resolve. That's why it's called *opportunistic*.
+ fn opportunistic_resolve_lt_var(
+ &self,
+ vid: <Self::Interner as Interner>::InferRegion,
+ ) -> Option<<Self::Interner as Interner>::Region>;
+
+ fn universe_of_ct(&self, ct: ConstVid) -> Option<UniverseIndex>;
+
+ /// Resolve `ConstVid` to its root `ConstVid`.
+ fn root_ct_var(&self, vid: ConstVid) -> ConstVid;
+
+ /// Resolve `ConstVid` to its inferred type, if it has been equated with a non-infer type.
+ fn probe_ct_var(&self, vid: ConstVid) -> Option<<Self::Interner as Interner>::Const>;
+}
diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs
index 7f75e5b35..188910ecc 100644
--- a/compiler/rustc_type_ir/src/interner.rs
+++ b/compiler/rustc_type_ir/src/interner.rs
@@ -2,68 +2,110 @@ use smallvec::SmallVec;
use std::fmt::Debug;
use std::hash::Hash;
-use crate::{DebugWithInfcx, Mutability};
+use crate::{
+ BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, RegionKind, TyKind,
+ UniverseIndex,
+};
pub trait Interner: Sized {
- type DefId: Clone + Debug + Hash + Ord;
- type AdtDef: Clone + Debug + Hash + Ord;
+ type DefId: Copy + Debug + Hash + Ord;
+ type AdtDef: Copy + Debug + Hash + Ord;
- type GenericArgs: Clone
+ type GenericArgs: Copy
+ DebugWithInfcx<Self>
+ Hash
+ Ord
+ IntoIterator<Item = Self::GenericArg>;
- type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type Term: Clone + Debug + Hash + Ord;
+ type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type Term: Copy + Debug + Hash + Ord;
type Binder<T>;
- type TypeAndMut: Clone + Debug + Hash + Ord;
- type CanonicalVars: Clone + Debug + Hash + Eq;
+ type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
// Kinds of tys
- type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
- type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type ParamTy: Clone + Debug + Hash + Ord;
- type BoundTy: Clone + Debug + Hash + Ord;
- type PlaceholderTy: Clone + Debug + Hash + Ord;
- type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
+ type Ty: Copy
+ + DebugWithInfcx<Self>
+ + Hash
+ + Ord
+ + Into<Self::GenericArg>
+ + IntoKind<Kind = TyKind<Self>>;
+ type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
+ type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type ParamTy: Copy + Debug + Hash + Ord;
+ type BoundTy: Copy + Debug + Hash + Ord;
+ type PlaceholderTy: Copy + Debug + Hash + Ord + PlaceholderLike;
// Things stored inside of tys
- type ErrorGuaranteed: Clone + Debug + Hash + Ord;
- type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type AllocId: Clone + Debug + Hash + Ord;
+ type ErrorGuaranteed: Copy + Debug + Hash + Ord;
+ type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type AllocId: Copy + Debug + Hash + Ord;
// Kinds of consts
- type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type PlaceholderConst: Clone + Debug + Hash + Ord;
- type ParamConst: Clone + Debug + Hash + Ord;
- type BoundConst: Clone + Debug + Hash + Ord;
- type ValueConst: Clone + Debug + Hash + Ord;
- type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
+ type Const: Copy
+ + DebugWithInfcx<Self>
+ + Hash
+ + Ord
+ + Into<Self::GenericArg>
+ + IntoKind<Kind = ConstKind<Self>>
+ + ConstTy<Self>;
+ type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
+ type ParamConst: Copy + Debug + Hash + Ord;
+ type BoundConst: Copy + Debug + Hash + Ord;
+ type ValueConst: Copy + Debug + Hash + Ord;
+ type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
// Kinds of regions
- type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type EarlyBoundRegion: Clone + Debug + Hash + Ord;
- type BoundRegion: Clone + Debug + Hash + Ord;
- type FreeRegion: Clone + Debug + Hash + Ord;
- type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
- type PlaceholderRegion: Clone + Debug + Hash + Ord;
+ type Region: Copy
+ + DebugWithInfcx<Self>
+ + Hash
+ + Ord
+ + Into<Self::GenericArg>
+ + IntoKind<Kind = RegionKind<Self>>;
+ type EarlyParamRegion: Copy + Debug + Hash + Ord;
+ type LateParamRegion: Copy + Debug + Hash + Ord;
+ type BoundRegion: Copy + Debug + Hash + Ord;
+ type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Ord;
+ type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike;
// Predicates
- type Predicate: Clone + Debug + Hash + Eq;
- type TraitPredicate: Clone + Debug + Hash + Eq;
- type RegionOutlivesPredicate: Clone + Debug + Hash + Eq;
- type TypeOutlivesPredicate: Clone + Debug + Hash + Eq;
- type ProjectionPredicate: Clone + Debug + Hash + Eq;
- type SubtypePredicate: Clone + Debug + Hash + Eq;
- type CoercePredicate: Clone + Debug + Hash + Eq;
- type ClosureKind: Clone + Debug + Hash + Eq;
-
- fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
+ type Predicate: Copy + Debug + Hash + Eq;
+ type TraitPredicate: Copy + Debug + Hash + Eq;
+ type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
+ type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
+ type ProjectionPredicate: Copy + Debug + Hash + Eq;
+ type NormalizesTo: Copy + Debug + Hash + Eq;
+ type SubtypePredicate: Copy + Debug + Hash + Eq;
+ type CoercePredicate: Copy + Debug + Hash + Eq;
+ type ClosureKind: Copy + Debug + Hash + Eq;
+
+ fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
+
+ // FIXME: We should not have all these constructors on `Interner`, but as functions on some trait.
+ fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty;
+ fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region;
+ fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const;
+}
+
+/// Common capabilities of placeholder kinds
+pub trait PlaceholderLike {
+ fn universe(self) -> UniverseIndex;
+ fn var(self) -> BoundVar;
+
+ fn with_updated_universe(self, ui: UniverseIndex) -> Self;
+
+ fn new(ui: UniverseIndex, var: BoundVar) -> Self;
+}
+
+pub trait IntoKind {
+ type Kind;
+
+ fn kind(self) -> Self::Kind;
+}
+
+pub trait ConstTy<I: Interner> {
+ fn ty(self) -> I::Ty;
}
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index e8785fff2..bff938596 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,25 +1,29 @@
-#![feature(associated_type_defaults)]
-#![feature(fmt_helpers_for_derive)]
-#![feature(get_mut_unchecked)]
-#![feature(min_specialization)]
-#![feature(never_type)]
-#![feature(new_uninit)]
-#![feature(rustc_attrs)]
-#![feature(unwrap_infallible)]
+#![cfg_attr(
+ feature = "nightly",
+ feature(associated_type_defaults, min_specialization, never_type, rustc_attrs)
+)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-#![allow(internal_features)]
+#![allow(rustc::usage_of_ty_tykind)]
+#![cfg_attr(feature = "nightly", allow(internal_features))]
+#[cfg(feature = "nightly")]
extern crate self as rustc_type_ir;
#[macro_use]
extern crate bitflags;
+#[cfg(feature = "nightly")]
#[macro_use]
extern crate rustc_macros;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::sync::Lrc;
use std::fmt;
use std::hash::Hash;
+#[cfg(not(feature = "nightly"))]
+use std::sync::Arc as Lrc;
+#[cfg(feature = "nightly")]
pub mod codec;
pub mod fold;
pub mod ty_info;
@@ -32,23 +36,28 @@ mod canonical;
mod const_kind;
mod debug;
mod flags;
+mod infcx;
mod interner;
mod predicate_kind;
mod region_kind;
pub use canonical::*;
+#[cfg(feature = "nightly")]
pub use codec::*;
pub use const_kind::*;
-pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
+pub use debug::{DebugWithInfcx, WithInfcx};
pub use flags::*;
+pub use infcx::InferCtxtLike;
pub use interner::*;
pub use predicate_kind::*;
pub use region_kind::*;
pub use ty_info::*;
pub use ty_kind::*;
-
-/// Needed so we can use #[derive(HashStable_Generic)]
-pub trait HashStableContext {}
+pub use AliasKind::*;
+pub use DynKind::*;
+pub use InferTy::*;
+pub use RegionKind::*;
+pub use TyKind::*;
rustc_index::newtype_index! {
/// A [De Bruijn index][dbi] is a standard means of representing
@@ -90,8 +99,11 @@ rustc_index::newtype_index! {
/// is the outer fn.
///
/// [dbi]: https://en.wikipedia.org/wiki/De_Bruijn_index
- #[derive(HashStable_Generic)]
+ #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+ #[encodable]
+ #[orderable]
#[debug_format = "DebruijnIndex({})"]
+ #[gate_rustc_only]
pub struct DebruijnIndex {
const INNERMOST = 0;
}
@@ -173,8 +185,9 @@ pub fn debug_bound_var<T: std::fmt::Write>(
}
}
-#[derive(Copy, Clone, PartialEq, Eq, Decodable, Encodable, Hash, HashStable_Generic)]
-#[rustc_pass_by_value]
+#[derive(Copy, Clone, PartialEq, Eq)]
+#[cfg_attr(feature = "nightly", derive(Decodable, Encodable, Hash, HashStable_NoContext))]
+#[cfg_attr(feature = "nightly", rustc_pass_by_value)]
pub enum Variance {
Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
@@ -289,8 +302,11 @@ rustc_index::newtype_index! {
/// declared, but a type name in a non-zero universe is a placeholder
/// type -- an idealized representative of "types in general" that we
/// use for checking generic functions.
- #[derive(HashStable_Generic)]
+ #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+ #[encodable]
+ #[orderable]
#[debug_format = "U{}"]
+ #[gate_rustc_only]
pub struct UniverseIndex {}
}
@@ -328,3 +344,60 @@ impl UniverseIndex {
self.private < other.private
}
}
+
+impl Default for UniverseIndex {
+ fn default() -> Self {
+ Self::ROOT
+ }
+}
+
+rustc_index::newtype_index! {
+ #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+ #[encodable]
+ #[orderable]
+ #[debug_format = "{}"]
+ #[gate_rustc_only]
+ pub struct BoundVar {}
+}
+
+/// Represents the various closure traits in the language. This
+/// will determine the type of the environment (`self`, in the
+/// desugaring) argument that the closure expects.
+///
+/// You can get the environment type of a closure using
+/// `tcx.closure_env_ty()`.
+#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Hash, Debug)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
+pub enum ClosureKind {
+ // Warning: Ordering is significant here! The ordering is chosen
+ // because the trait Fn is a subtrait of FnMut and so in turn, and
+ // hence we order it so that Fn < FnMut < FnOnce.
+ Fn,
+ FnMut,
+ FnOnce,
+}
+
+impl ClosureKind {
+ /// This is the initial value used when doing upvar inference.
+ pub const LATTICE_BOTTOM: ClosureKind = ClosureKind::Fn;
+
+ pub const fn as_str(self) -> &'static str {
+ match self {
+ ClosureKind::Fn => "Fn",
+ ClosureKind::FnMut => "FnMut",
+ ClosureKind::FnOnce => "FnOnce",
+ }
+ }
+
+ /// Returns `true` if a type that impls this closure kind
+ /// must also implement `other`.
+ pub fn extends(self, other: ClosureKind) -> bool {
+ self <= other
+ }
+}
+
+impl fmt::Display for ClosureKind {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ self.as_str().fmt(f)
+ }
+}
diff --git a/compiler/rustc_type_ir/src/macros.rs b/compiler/rustc_type_ir/src/macros.rs
index cfed84a35..82bb1bf29 100644
--- a/compiler/rustc_type_ir/src/macros.rs
+++ b/compiler/rustc_type_ir/src/macros.rs
@@ -51,4 +51,6 @@ TrivialTypeTraversalImpls! {
crate::DebruijnIndex,
crate::AliasRelationDirection,
crate::UniverseIndex,
+ crate::Mutability,
+ crate::Movability,
}
diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs
index 48662d426..8c4d0fda6 100644
--- a/compiler/rustc_type_ir/src/predicate_kind.rs
+++ b/compiler/rustc_type_ir/src/predicate_kind.rs
@@ -1,16 +1,15 @@
-use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt;
use std::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{HashStableContext, Interner};
+use crate::Interner;
/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Hash(bound = ""))]
-#[derive(TyEncodable, TyDecodable)]
+#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ClauseKind<I: Interner> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
@@ -38,18 +37,6 @@ pub enum ClauseKind<I: Interner> {
ConstEvaluatable(I::Const),
}
-impl<I: Interner> Copy for ClauseKind<I>
-where
- I::Ty: Copy,
- I::Const: Copy,
- I::GenericArg: Copy,
- I::TraitPredicate: Copy,
- I::ProjectionPredicate: Copy,
- I::TypeOutlivesPredicate: Copy,
- I::RegionOutlivesPredicate: Copy,
-{
-}
-
impl<I: Interner> PartialEq for ClauseKind<I> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
@@ -67,45 +54,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
impl<I: Interner> Eq for ClauseKind<I> {}
-fn clause_kind_discriminant<I: Interner>(value: &ClauseKind<I>) -> usize {
- match value {
- ClauseKind::Trait(_) => 0,
- ClauseKind::RegionOutlives(_) => 1,
- ClauseKind::TypeOutlives(_) => 2,
- ClauseKind::Projection(_) => 3,
- ClauseKind::ConstArgHasType(_, _) => 4,
- ClauseKind::WellFormed(_) => 5,
- ClauseKind::ConstEvaluatable(_) => 6,
- }
-}
-
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ClauseKind<I>
-where
- I::Ty: HashStable<CTX>,
- I::Const: HashStable<CTX>,
- I::GenericArg: HashStable<CTX>,
- I::TraitPredicate: HashStable<CTX>,
- I::ProjectionPredicate: HashStable<CTX>,
- I::TypeOutlivesPredicate: HashStable<CTX>,
- I::RegionOutlivesPredicate: HashStable<CTX>,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- clause_kind_discriminant(self).hash_stable(hcx, hasher);
- match self {
- ClauseKind::Trait(p) => p.hash_stable(hcx, hasher),
- ClauseKind::RegionOutlives(p) => p.hash_stable(hcx, hasher),
- ClauseKind::TypeOutlives(p) => p.hash_stable(hcx, hasher),
- ClauseKind::Projection(p) => p.hash_stable(hcx, hasher),
- ClauseKind::ConstArgHasType(c, t) => {
- c.hash_stable(hcx, hasher);
- t.hash_stable(hcx, hasher);
- }
- ClauseKind::WellFormed(t) => t.hash_stable(hcx, hasher),
- ClauseKind::ConstEvaluatable(c) => c.hash_stable(hcx, hasher),
- }
- }
-}
-
impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
where
I::Ty: TypeFoldable<I>,
@@ -160,8 +108,14 @@ where
}
#[derive(derivative::Derivative)]
-#[derivative(Clone(bound = ""), Hash(bound = ""))]
-#[derive(TyEncodable, TyDecodable)]
+#[derivative(
+ Clone(bound = ""),
+ Copy(bound = ""),
+ Hash(bound = ""),
+ PartialEq(bound = ""),
+ Eq(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum PredicateKind<I: Interner> {
/// Prove a clause
Clause(ClauseKind<I>),
@@ -169,11 +123,6 @@ pub enum PredicateKind<I: Interner> {
/// Trait must be object-safe.
ObjectSafe(I::DefId),
- /// No direct syntax. May be thought of as `where T: FnFoo<...>`
- /// for some generic args `...` and `T` being a closure type.
- /// Satisfied (or refuted) once we know the closure's kind.
- ClosureKind(I::DefId, I::GenericArgs, I::ClosureKind),
-
/// `T1 <: T2`
///
/// This obligation is created most often when we have two
@@ -198,6 +147,15 @@ pub enum PredicateKind<I: Interner> {
/// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
Ambiguous,
+ /// The alias normalizes to `term`. Unlike `Projection`, this always fails if the alias
+ /// cannot be normalized in the current context.
+ ///
+ /// `Projection(<T as Trait>::Assoc, ?x)` results in `?x == <T as Trait>::Assoc` while
+ /// `NormalizesTo(<T as Trait>::Assoc, ?x)` results in `NoSolution`.
+ ///
+ /// Only used in the new solver.
+ NormalizesTo(I::NormalizesTo),
+
/// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
/// This predicate requires two terms to be equal to eachother.
///
@@ -205,90 +163,6 @@ pub enum PredicateKind<I: Interner> {
AliasRelate(I::Term, I::Term, AliasRelationDirection),
}
-impl<I: Interner> Copy for PredicateKind<I>
-where
- I::DefId: Copy,
- I::Const: Copy,
- I::GenericArgs: Copy,
- I::Term: Copy,
- I::CoercePredicate: Copy,
- I::SubtypePredicate: Copy,
- I::ClosureKind: Copy,
- ClauseKind<I>: Copy,
-{
-}
-
-impl<I: Interner> PartialEq for PredicateKind<I> {
- fn eq(&self, other: &Self) -> bool {
- match (self, other) {
- (Self::Clause(l0), Self::Clause(r0)) => l0 == r0,
- (Self::ObjectSafe(l0), Self::ObjectSafe(r0)) => l0 == r0,
- (Self::ClosureKind(l0, l1, l2), Self::ClosureKind(r0, r1, r2)) => {
- l0 == r0 && l1 == r1 && l2 == r2
- }
- (Self::Subtype(l0), Self::Subtype(r0)) => l0 == r0,
- (Self::Coerce(l0), Self::Coerce(r0)) => l0 == r0,
- (Self::ConstEquate(l0, l1), Self::ConstEquate(r0, r1)) => l0 == r0 && l1 == r1,
- (Self::AliasRelate(l0, l1, l2), Self::AliasRelate(r0, r1, r2)) => {
- l0 == r0 && l1 == r1 && l2 == r2
- }
- _ => core::mem::discriminant(self) == core::mem::discriminant(other),
- }
- }
-}
-
-impl<I: Interner> Eq for PredicateKind<I> {}
-
-fn predicate_kind_discriminant<I: Interner>(value: &PredicateKind<I>) -> usize {
- match value {
- PredicateKind::Clause(_) => 0,
- PredicateKind::ObjectSafe(_) => 1,
- PredicateKind::ClosureKind(_, _, _) => 2,
- PredicateKind::Subtype(_) => 3,
- PredicateKind::Coerce(_) => 4,
- PredicateKind::ConstEquate(_, _) => 5,
- PredicateKind::Ambiguous => 6,
- PredicateKind::AliasRelate(_, _, _) => 7,
- }
-}
-
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for PredicateKind<I>
-where
- I::DefId: HashStable<CTX>,
- I::Const: HashStable<CTX>,
- I::GenericArgs: HashStable<CTX>,
- I::Term: HashStable<CTX>,
- I::CoercePredicate: HashStable<CTX>,
- I::SubtypePredicate: HashStable<CTX>,
- I::ClosureKind: HashStable<CTX>,
- ClauseKind<I>: HashStable<CTX>,
-{
- fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
- predicate_kind_discriminant(self).hash_stable(hcx, hasher);
- match self {
- PredicateKind::Clause(p) => p.hash_stable(hcx, hasher),
- PredicateKind::ObjectSafe(d) => d.hash_stable(hcx, hasher),
- PredicateKind::ClosureKind(d, g, k) => {
- d.hash_stable(hcx, hasher);
- g.hash_stable(hcx, hasher);
- k.hash_stable(hcx, hasher);
- }
- PredicateKind::Subtype(p) => p.hash_stable(hcx, hasher),
- PredicateKind::Coerce(p) => p.hash_stable(hcx, hasher),
- PredicateKind::ConstEquate(c1, c2) => {
- c1.hash_stable(hcx, hasher);
- c2.hash_stable(hcx, hasher);
- }
- PredicateKind::Ambiguous => {}
- PredicateKind::AliasRelate(t1, t2, r) => {
- t1.hash_stable(hcx, hasher);
- t2.hash_stable(hcx, hasher);
- r.hash_stable(hcx, hasher);
- }
- }
- }
-}
-
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
where
I::DefId: TypeFoldable<I>,
@@ -297,24 +171,20 @@ where
I::Term: TypeFoldable<I>,
I::CoercePredicate: TypeFoldable<I>,
I::SubtypePredicate: TypeFoldable<I>,
- I::ClosureKind: TypeFoldable<I>,
+ I::NormalizesTo: TypeFoldable<I>,
ClauseKind<I>: TypeFoldable<I>,
{
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
Ok(match self {
PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
- PredicateKind::ClosureKind(d, g, k) => PredicateKind::ClosureKind(
- d.try_fold_with(folder)?,
- g.try_fold_with(folder)?,
- k.try_fold_with(folder)?,
- ),
PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
PredicateKind::ConstEquate(a, b) => {
PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
}
PredicateKind::Ambiguous => PredicateKind::Ambiguous,
+ PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?),
PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
a.try_fold_with(folder)?,
b.try_fold_with(folder)?,
@@ -332,18 +202,13 @@ where
I::Term: TypeVisitable<I>,
I::CoercePredicate: TypeVisitable<I>,
I::SubtypePredicate: TypeVisitable<I>,
- I::ClosureKind: TypeVisitable<I>,
+ I::NormalizesTo: TypeVisitable<I>,
ClauseKind<I>: TypeVisitable<I>,
{
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
match self {
PredicateKind::Clause(p) => p.visit_with(visitor),
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
- PredicateKind::ClosureKind(d, g, k) => {
- d.visit_with(visitor)?;
- g.visit_with(visitor)?;
- k.visit_with(visitor)
- }
PredicateKind::Subtype(s) => s.visit_with(visitor),
PredicateKind::Coerce(s) => s.visit_with(visitor),
PredicateKind::ConstEquate(a, b) => {
@@ -351,6 +216,7 @@ where
b.visit_with(visitor)
}
PredicateKind::Ambiguous => ControlFlow::Continue(()),
+ PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
PredicateKind::AliasRelate(a, b, d) => {
a.visit_with(visitor)?;
b.visit_with(visitor)?;
@@ -361,7 +227,7 @@ where
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))]
pub enum AliasRelationDirection {
Equate,
Subtype,
@@ -403,11 +269,9 @@ impl<I: Interner> fmt::Debug for PredicateKind<I> {
PredicateKind::ObjectSafe(trait_def_id) => {
write!(f, "ObjectSafe({trait_def_id:?})")
}
- PredicateKind::ClosureKind(closure_def_id, closure_args, kind) => {
- write!(f, "ClosureKind({closure_def_id:?}, {closure_args:?}, {kind:?})")
- }
PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
PredicateKind::Ambiguous => write!(f, "Ambiguous"),
+ PredicateKind::NormalizesTo(p) => p.fmt(f),
PredicateKind::AliasRelate(t1, t2, dir) => {
write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
}
diff --git a/compiler/rustc_type_ir/src/region_kind.rs b/compiler/rustc_type_ir/src/region_kind.rs
index 69ed5bada..3b5e41e8d 100644
--- a/compiler/rustc_type_ir/src/region_kind.rs
+++ b/compiler/rustc_type_ir/src/region_kind.rs
@@ -1,8 +1,8 @@
-use rustc_data_structures::stable_hasher::HashStable;
-use rustc_data_structures::stable_hasher::StableHasher;
+#[cfg(feature = "nightly")]
+use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::fmt;
-use crate::{DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, WithInfcx};
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, Interner, WithInfcx};
use self::RegionKind::*;
@@ -22,8 +22,8 @@ use self::RegionKind::*;
/// ```text
/// static ----------+-----...------+ (greatest)
/// | | |
-/// early-bound and | |
-/// free regions | |
+/// param regions | |
+/// | | |
/// | | |
/// | | |
/// empty(root) placeholder(U1) |
@@ -88,8 +88,8 @@ use self::RegionKind::*;
/// To do this, we replace the bound regions with placeholder markers,
/// which don't satisfy any relation not explicitly provided.
///
-/// There are two kinds of placeholder regions in rustc: `ReFree` and
-/// `RePlaceholder`. When checking an item's body, `ReFree` is supposed
+/// There are two kinds of placeholder regions in rustc: `ReLateParam` and
+/// `RePlaceholder`. When checking an item's body, `ReLateParam` is supposed
/// to be used. These also support explicit bounds: both the internally-stored
/// *scope*, which the region is assumed to outlive, as well as other
/// relations stored in the `FreeRegionMap`. Note that these relations
@@ -115,27 +115,44 @@ use self::RegionKind::*;
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
+ Copy(bound = ""),
PartialOrd(bound = ""),
PartialOrd = "feature_allow_slow_enum",
Ord(bound = ""),
Ord = "feature_allow_slow_enum",
Hash(bound = "")
)]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum RegionKind<I: Interner> {
- /// Region bound in a type or fn declaration which will be
- /// substituted 'early' -- that is, at the same time when type
- /// parameters are substituted.
- ReEarlyBound(I::EarlyBoundRegion),
+ /// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
+ ///
+ /// There are some important differences between region and type parameters.
+ /// Not all region parameters in the source are represented via `ReEarlyParam`:
+ /// late-bound function parameters are instead lowered to a `ReBound`. Late-bound
+ /// regions get eagerly replaced with `ReLateParam` which behaves in the same way as
+ /// `ReEarlyParam`. Region parameters are also sometimes implicit,
+ /// e.g. in `impl Trait for &()`.
+ ReEarlyParam(I::EarlyParamRegion),
- /// Region bound in a function scope, which will be substituted when the
- /// function is called.
- ReLateBound(DebruijnIndex, I::BoundRegion),
+ /// A higher-ranked region. These represent either late-bound function parameters
+ /// or bound variables from a `for<'a>`-binder.
+ ///
+ /// While inside of a function, e.g. during typeck, the late-bound function parameters
+ /// can be converted to `ReLateParam` by calling `tcx.liberate_late_bound_regions`.
+ ///
+ /// Bound regions inside of types **must not** be erased, as they impact trait
+ /// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and
+ /// `fn(&'static ())` are different types and have to be treated as such.
+ ReBound(DebruijnIndex, I::BoundRegion),
- /// When checking a function body, the types of all arguments and so forth
- /// that refer to bound region parameters are modified to refer to free
- /// region parameters.
- ReFree(I::FreeRegion),
+ /// Late-bound function parameters are represented using a `ReBound`. When
+ /// inside of a function, we convert these bound variables to placeholder
+ /// parameters via `tcx.liberate_late_bound_regions`. They are then treated
+ /// the same way as `ReEarlyParam` while inside of the function.
+ ///
+ /// See <https://rustc-dev-guide.rust-lang.org/early-late-bound-summary.html> for
+ /// more info about early and late bound lifetime parameters.
+ ReLateParam(I::LateParamRegion),
/// Static data that has an "infinite" lifetime. Top in the region lattice.
ReStatic,
@@ -143,8 +160,11 @@ pub enum RegionKind<I: Interner> {
/// A region variable. Should not exist outside of type inference.
ReVar(I::InferRegion),
- /// A placeholder region -- basically, the higher-ranked version of `ReFree`.
+ /// A placeholder region -- the higher-ranked version of `ReLateParam`.
/// Should not exist outside of type inference.
+ ///
+ /// Used when instantiating a `forall` binder via
+ /// `infcx.instantiate_binder_with_placeholders`.
RePlaceholder(I::PlaceholderRegion),
/// Erased region, used by trait selection, in MIR and during codegen.
@@ -159,9 +179,9 @@ pub enum RegionKind<I: Interner> {
#[inline]
const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
match value {
- ReEarlyBound(_) => 0,
- ReLateBound(_, _) => 1,
- ReFree(_) => 2,
+ ReEarlyParam(_) => 0,
+ ReBound(_, _) => 1,
+ ReLateParam(_) => 2,
ReStatic => 3,
ReVar(_) => 4,
RePlaceholder(_) => 5,
@@ -170,27 +190,15 @@ const fn regionkind_discriminant<I: Interner>(value: &RegionKind<I>) -> usize {
}
}
-// This is manually implemented because a derive would require `I: Copy`
-impl<I: Interner> Copy for RegionKind<I>
-where
- I::EarlyBoundRegion: Copy,
- I::BoundRegion: Copy,
- I::FreeRegion: Copy,
- I::InferRegion: Copy,
- I::PlaceholderRegion: Copy,
- I::ErrorGuaranteed: Copy,
-{
-}
-
// This is manually implemented because a derive would require `I: PartialEq`
impl<I: Interner> PartialEq for RegionKind<I> {
#[inline]
fn eq(&self, other: &RegionKind<I>) -> bool {
regionkind_discriminant(self) == regionkind_discriminant(other)
&& match (self, other) {
- (ReEarlyBound(a_r), ReEarlyBound(b_r)) => a_r == b_r,
- (ReLateBound(a_d, a_r), ReLateBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
- (ReFree(a_r), ReFree(b_r)) => a_r == b_r,
+ (ReEarlyParam(a_r), ReEarlyParam(b_r)) => a_r == b_r,
+ (ReBound(a_d, a_r), ReBound(b_d, b_r)) => a_d == b_d && a_r == b_r,
+ (ReLateParam(a_r), ReLateParam(b_r)) => a_r == b_r,
(ReStatic, ReStatic) => true,
(ReVar(a_r), ReVar(b_r)) => a_r == b_r,
(RePlaceholder(a_r), RePlaceholder(b_r)) => a_r == b_r,
@@ -216,13 +224,13 @@ impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
match this.data {
- ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
+ ReEarlyParam(data) => write!(f, "ReEarlyParam({data:?})"),
- ReLateBound(binder_id, bound_region) => {
- write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
+ ReBound(binder_id, bound_region) => {
+ write!(f, "ReBound({binder_id:?}, {bound_region:?})")
}
- ReFree(fr) => write!(f, "{fr:?}"),
+ ReLateParam(fr) => write!(f, "{fr:?}"),
ReStatic => f.write_str("ReStatic"),
@@ -242,12 +250,13 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
}
}
+#[cfg(feature = "nightly")]
// This is not a derived impl because a derive would require `I: HashStable`
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for RegionKind<I>
+impl<CTX, I: Interner> HashStable<CTX> for RegionKind<I>
where
- I::EarlyBoundRegion: HashStable<CTX>,
+ I::EarlyParamRegion: HashStable<CTX>,
I::BoundRegion: HashStable<CTX>,
- I::FreeRegion: HashStable<CTX>,
+ I::LateParamRegion: HashStable<CTX>,
I::InferRegion: HashStable<CTX>,
I::PlaceholderRegion: HashStable<CTX>,
{
@@ -258,14 +267,14 @@ where
ReErased | ReStatic | ReError(_) => {
// No variant fields to hash for these ...
}
- ReLateBound(d, r) => {
+ ReBound(d, r) => {
d.hash_stable(hcx, hasher);
r.hash_stable(hcx, hasher);
}
- ReEarlyBound(r) => {
+ ReEarlyParam(r) => {
r.hash_stable(hcx, hasher);
}
- ReFree(r) => {
+ ReLateParam(r) => {
r.hash_stable(hcx, hasher);
}
RePlaceholder(r) => {
diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs
index d986e310c..0e4930552 100644
--- a/compiler/rustc_type_ir/src/ty_info.rs
+++ b/compiler/rustc_type_ir/src/ty_info.rs
@@ -1,4 +1,6 @@
+#[cfg(feature = "nightly")]
use rustc_data_structures::fingerprint::Fingerprint;
+#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use std::cmp::Ordering;
use std::hash::{Hash, Hasher};
@@ -16,6 +18,8 @@ use crate::{DebruijnIndex, TypeFlags};
#[derive(Copy, Clone)]
pub struct WithCachedTypeInfo<T> {
pub internee: T,
+
+ #[cfg(feature = "nightly")]
pub stable_hash: Fingerprint,
/// This field provides fast access to information that is also contained
@@ -81,14 +85,16 @@ impl<T> Deref for WithCachedTypeInfo<T> {
impl<T: Hash> Hash for WithCachedTypeInfo<T> {
#[inline]
fn hash<H: Hasher>(&self, s: &mut H) {
+ #[cfg(feature = "nightly")]
if self.stable_hash != Fingerprint::ZERO {
- self.stable_hash.hash(s)
- } else {
- self.internee.hash(s)
+ return self.stable_hash.hash(s);
}
+
+ self.internee.hash(s)
}
}
+#[cfg(feature = "nightly")]
impl<T: HashStable<CTX>, CTX> HashStable<CTX> for WithCachedTypeInfo<T> {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
if self.stable_hash == Fingerprint::ZERO || cfg!(debug_assertions) {
diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs
index 09a9a3322..70adfbee2 100644
--- a/compiler/rustc_type_ir/src/ty_kind.rs
+++ b/compiler/rustc_type_ir/src/ty_kind.rs
@@ -1,11 +1,11 @@
-#![allow(rustc::usage_of_ty_tykind)]
-
+#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
+#[cfg(feature = "nightly")]
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
use std::fmt;
-use std::mem::discriminant;
-use crate::HashStableContext;
+use crate::fold::{FallibleTypeFolder, TypeFoldable};
+use crate::visit::{TypeVisitable, TypeVisitor};
use crate::Interner;
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
@@ -13,8 +13,8 @@ use self::TyKind::*;
/// The movability of a coroutine / closure literal:
/// whether a coroutine contains self-references, causing it to be `!Unpin`.
-#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable, Debug, Copy)]
-#[derive(HashStable_Generic)]
+#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum Movability {
/// May contain self-references, `!Unpin`.
Static,
@@ -23,7 +23,7 @@ pub enum Movability {
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
-#[derive(HashStable_Generic, Encodable, Decodable)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum Mutability {
// N.B. Order is deliberate, so that Not < Mut
Not,
@@ -75,7 +75,7 @@ impl Mutability {
/// Specifies how a trait object is represented.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum DynKind {
/// An unsized `dyn Trait` object
Dyn,
@@ -89,7 +89,7 @@ pub enum DynKind {
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum AliasKind {
/// A projection `<Type as Trait>::AssocType`.
/// Can get normalized away if monomorphic enough.
@@ -109,17 +109,18 @@ pub enum AliasKind {
///
/// Types written by the user start out as `hir::TyKind` and get
/// converted to this representation using `AstConv::ast_ty_to_ty`.
-#[rustc_diagnostic_item = "IrTyKind"]
+#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
#[derive(derivative::Derivative)]
#[derivative(
Clone(bound = ""),
+ Copy(bound = ""),
PartialOrd(bound = ""),
PartialOrd = "feature_allow_slow_enum",
Ord(bound = ""),
Ord = "feature_allow_slow_enum",
Hash(bound = "")
)]
-#[derive(TyEncodable, TyDecodable)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum TyKind<I: Interner> {
/// The primitive boolean type. Written as `bool`.
Bool,
@@ -159,7 +160,7 @@ pub enum TyKind<I: Interner> {
Slice(I::Ty),
/// A raw pointer. Written as `*mut T` or `*const T`
- RawPtr(I::TypeAndMut),
+ RawPtr(TypeAndMut<I>),
/// A reference; a pointer with an associated lifetime. Written as
/// `&'a mut T` or `&'a T`.
@@ -281,7 +282,7 @@ pub enum TyKind<I: Interner> {
/// correctly deal with higher ranked types. Though unlike placeholders,
/// that universe is stored in the `InferCtxt` instead of directly
/// inside of the type.
- Infer(I::InferTy),
+ Infer(InferTy),
/// A placeholder for a type which could not be computed; this is
/// propagated to avoid useless error messages.
@@ -394,7 +395,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
Float(float) => write!(f, "{float:?}"),
Adt(d, s) => {
write!(f, "{d:?}")?;
- let mut s = s.clone().into_iter();
+ let mut s = s.into_iter();
let first = s.next();
match first {
Some(first) => write!(f, "<{:?}", first)?,
@@ -407,12 +408,11 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
write!(f, ">")
}
- Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
+ Foreign(d) => f.debug_tuple("Foreign").field(d).finish(),
Str => write!(f, "str"),
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
- RawPtr(p) => {
- let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
+ RawPtr(TypeAndMut { ty, mutbl }) => {
match mutbl {
Mutability::Mut => write!(f, "*mut "),
Mutability::Not => write!(f, "*const "),
@@ -423,7 +423,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
Mutability::Mut => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
Mutability::Not => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
},
- FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
+ FnDef(d, s) => f.debug_tuple("FnDef").field(d).field(&this.wrap(s)).finish(),
FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
Dynamic(p, r, repr) => match repr {
DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
@@ -431,16 +431,18 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
}
},
- Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
- Coroutine(d, s, m) => f.debug_tuple_field3_finish("Coroutine", d, &this.wrap(s), m),
+ Closure(d, s) => f.debug_tuple("Closure").field(d).field(&this.wrap(s)).finish(),
+ Coroutine(d, s, m) => {
+ f.debug_tuple("Coroutine").field(d).field(&this.wrap(s)).field(m).finish()
+ }
CoroutineWitness(d, s) => {
- f.debug_tuple_field2_finish("CoroutineWitness", d, &this.wrap(s))
+ f.debug_tuple("CoroutineWitness").field(d).field(&this.wrap(s)).finish()
}
Never => write!(f, "!"),
Tuple(t) => {
write!(f, "(")?;
let mut count = 0;
- for ty in t.clone() {
+ for ty in *t {
if count > 0 {
write!(f, ", ")?;
}
@@ -453,7 +455,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
}
write!(f, ")")
}
- Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)),
+ Alias(i, a) => f.debug_tuple("Alias").field(i).field(&this.wrap(a)).finish(),
Param(p) => write!(f, "{p:?}"),
Bound(d, b) => crate::debug_bound_var(f, *d, b),
Placeholder(p) => write!(f, "{p:?}"),
@@ -470,120 +472,8 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
}
}
-// This is not a derived impl because a derive would require `I: HashStable`
-#[allow(rustc::usage_of_ty_tykind)]
-impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for TyKind<I>
-where
- I::AdtDef: HashStable<CTX>,
- I::DefId: HashStable<CTX>,
- I::GenericArgs: HashStable<CTX>,
- I::Ty: HashStable<CTX>,
- I::Const: HashStable<CTX>,
- I::TypeAndMut: HashStable<CTX>,
- I::PolyFnSig: HashStable<CTX>,
- I::BoundExistentialPredicates: HashStable<CTX>,
- I::Region: HashStable<CTX>,
- I::Tys: HashStable<CTX>,
- I::AliasTy: HashStable<CTX>,
- I::BoundTy: HashStable<CTX>,
- I::ParamTy: HashStable<CTX>,
- I::PlaceholderTy: HashStable<CTX>,
- I::InferTy: HashStable<CTX>,
- I::ErrorGuaranteed: HashStable<CTX>,
-{
- #[inline]
- fn hash_stable(&self, __hcx: &mut CTX, __hasher: &mut StableHasher) {
- std::mem::discriminant(self).hash_stable(__hcx, __hasher);
- match self {
- Bool => {}
- Char => {}
- Int(i) => {
- i.hash_stable(__hcx, __hasher);
- }
- Uint(u) => {
- u.hash_stable(__hcx, __hasher);
- }
- Float(f) => {
- f.hash_stable(__hcx, __hasher);
- }
- Adt(adt, args) => {
- adt.hash_stable(__hcx, __hasher);
- args.hash_stable(__hcx, __hasher);
- }
- Foreign(def_id) => {
- def_id.hash_stable(__hcx, __hasher);
- }
- Str => {}
- Array(t, c) => {
- t.hash_stable(__hcx, __hasher);
- c.hash_stable(__hcx, __hasher);
- }
- Slice(t) => {
- t.hash_stable(__hcx, __hasher);
- }
- RawPtr(tam) => {
- tam.hash_stable(__hcx, __hasher);
- }
- Ref(r, t, m) => {
- r.hash_stable(__hcx, __hasher);
- t.hash_stable(__hcx, __hasher);
- m.hash_stable(__hcx, __hasher);
- }
- FnDef(def_id, args) => {
- def_id.hash_stable(__hcx, __hasher);
- args.hash_stable(__hcx, __hasher);
- }
- FnPtr(polyfnsig) => {
- polyfnsig.hash_stable(__hcx, __hasher);
- }
- Dynamic(l, r, repr) => {
- l.hash_stable(__hcx, __hasher);
- r.hash_stable(__hcx, __hasher);
- repr.hash_stable(__hcx, __hasher);
- }
- Closure(def_id, args) => {
- def_id.hash_stable(__hcx, __hasher);
- args.hash_stable(__hcx, __hasher);
- }
- Coroutine(def_id, args, m) => {
- def_id.hash_stable(__hcx, __hasher);
- args.hash_stable(__hcx, __hasher);
- m.hash_stable(__hcx, __hasher);
- }
- CoroutineWitness(def_id, args) => {
- def_id.hash_stable(__hcx, __hasher);
- args.hash_stable(__hcx, __hasher);
- }
- Never => {}
- Tuple(args) => {
- args.hash_stable(__hcx, __hasher);
- }
- Alias(k, p) => {
- k.hash_stable(__hcx, __hasher);
- p.hash_stable(__hcx, __hasher);
- }
- Param(p) => {
- p.hash_stable(__hcx, __hasher);
- }
- Bound(d, b) => {
- d.hash_stable(__hcx, __hasher);
- b.hash_stable(__hcx, __hasher);
- }
- Placeholder(p) => {
- p.hash_stable(__hcx, __hasher);
- }
- Infer(i) => {
- i.hash_stable(__hcx, __hasher);
- }
- Error(d) => {
- d.hash_stable(__hcx, __hasher);
- }
- }
- }
-}
-
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum IntTy {
Isize,
I8,
@@ -641,7 +531,7 @@ impl IntTy {
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Copy)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum UintTy {
Usize,
U8,
@@ -699,7 +589,7 @@ impl UintTy {
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
-#[derive(Encodable, Decodable, HashStable_Generic)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
pub enum FloatTy {
F32,
F64,
@@ -732,19 +622,28 @@ pub struct FloatVarValue(pub FloatTy);
rustc_index::newtype_index! {
/// A **ty**pe **v**ariable **ID**.
+ #[encodable]
+ #[orderable]
#[debug_format = "?{}t"]
+ #[gate_rustc_only]
pub struct TyVid {}
}
rustc_index::newtype_index! {
/// An **int**egral (`u32`, `i32`, `usize`, etc.) type **v**ariable **ID**.
+ #[encodable]
+ #[orderable]
#[debug_format = "?{}i"]
+ #[gate_rustc_only]
pub struct IntVid {}
}
rustc_index::newtype_index! {
/// A **float**ing-point (`f32` or `f64`) type **v**ariable **ID**.
+ #[encodable]
+ #[orderable]
#[debug_format = "?{}f"]
+ #[gate_rustc_only]
pub struct FloatVid {}
}
@@ -753,7 +652,8 @@ rustc_index::newtype_index! {
/// E.g., if we have an empty array (`[]`), then we create a fresh
/// type variable for the element type since we won't know until it's
/// used what the element type is supposed to be.
-#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Encodable, Decodable)]
+#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
+#[cfg_attr(feature = "nightly", derive(Encodable, Decodable))]
pub enum InferTy {
/// A type variable.
TyVar(TyVid),
@@ -786,6 +686,7 @@ pub enum InferTy {
/// Raw `TyVid` are used as the unification key for `sub_relations`;
/// they carry no values.
+#[cfg(feature = "nightly")]
impl UnifyKey for TyVid {
type Value = ();
#[inline]
@@ -801,8 +702,10 @@ impl UnifyKey for TyVid {
}
}
+#[cfg(feature = "nightly")]
impl EqUnifyValue for IntVarValue {}
+#[cfg(feature = "nightly")]
impl UnifyKey for IntVid {
type Value = Option<IntVarValue>;
#[inline] // make this function eligible for inlining - it is quite hot.
@@ -818,8 +721,10 @@ impl UnifyKey for IntVid {
}
}
+#[cfg(feature = "nightly")]
impl EqUnifyValue for FloatVarValue {}
+#[cfg(feature = "nightly")]
impl UnifyKey for FloatVid {
type Value = Option<FloatVarValue>;
#[inline]
@@ -835,10 +740,11 @@ impl UnifyKey for FloatVid {
}
}
+#[cfg(feature = "nightly")]
impl<CTX> HashStable<CTX> for InferTy {
fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
use InferTy::*;
- discriminant(self).hash_stable(ctx, hasher);
+ std::mem::discriminant(self).hash_stable(ctx, hasher);
match self {
TyVar(_) | IntVar(_) | FloatVar(_) => {
panic!("type variables should not be hashed: {self:?}")
@@ -909,20 +815,59 @@ impl fmt::Debug for InferTy {
}
}
-impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
+impl<I: Interner> DebugWithInfcx<I> for InferTy {
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
this: WithInfcx<'_, Infcx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
- use InferTy::*;
- match this.infcx.universe_of_ty(*this.data) {
- None => write!(f, "{:?}", this.data),
- Some(universe) => match *this.data {
- TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
- IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
- unreachable!()
+ match this.data {
+ InferTy::TyVar(vid) => {
+ if let Some(universe) = this.infcx.universe_of_ty(*vid) {
+ write!(f, "?{}_{}t", vid.index(), universe.index())
+ } else {
+ write!(f, "{:?}", this.data)
}
- },
+ }
+ _ => write!(f, "{:?}", this.data),
}
}
}
+
+#[derive(derivative::Derivative)]
+#[derivative(
+ Clone(bound = ""),
+ Copy(bound = ""),
+ PartialOrd(bound = ""),
+ Ord(bound = ""),
+ PartialEq(bound = ""),
+ Eq(bound = ""),
+ Hash(bound = ""),
+ Debug(bound = "")
+)]
+#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
+pub struct TypeAndMut<I: Interner> {
+ pub ty: I::Ty,
+ pub mutbl: Mutability,
+}
+
+impl<I: Interner> TypeFoldable<I> for TypeAndMut<I>
+where
+ I::Ty: TypeFoldable<I>,
+{
+ fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
+ Ok(TypeAndMut {
+ ty: self.ty.try_fold_with(folder)?,
+ mutbl: self.mutbl.try_fold_with(folder)?,
+ })
+ }
+}
+
+impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
+where
+ I::Ty: TypeVisitable<I>,
+{
+ fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> std::ops::ControlFlow<V::BreakTy> {
+ self.ty.visit_with(visitor)?;
+ self.mutbl.visit_with(visitor)
+ }
+}
diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs
index 9c7b8156b..7aa990046 100644
--- a/compiler/rustc_type_ir/src/visit.rs
+++ b/compiler/rustc_type_ir/src/visit.rs
@@ -41,12 +41,12 @@
//! - u.visit_with(visitor)
//! ```
-use rustc_data_structures::sync::Lrc;
use rustc_index::{Idx, IndexVec};
use std::fmt;
use std::ops::ControlFlow;
use crate::Interner;
+use crate::Lrc;
/// This trait is implemented for every type that can be visited,
/// providing the skeleton of the traversal.
@@ -82,8 +82,12 @@ pub trait TypeSuperVisitable<I: Interner>: TypeVisitable<I> {
/// method defined for every type of interest. Each such method has a default
/// that recurses into the type's fields in a non-custom fashion.
pub trait TypeVisitor<I: Interner>: Sized {
+ #[cfg(feature = "nightly")]
type BreakTy = !;
+ #[cfg(not(feature = "nightly"))]
+ type BreakTy;
+
fn visit_binder<T: TypeVisitable<I>>(&mut self, t: &I::Binder<T>) -> ControlFlow<Self::BreakTy>
where
I::Binder<T>: TypeSuperVisitable<I>,