Auto merge of #117582 - compiler-errors:uplift-canonical-var, r=jackh726
Uplift `CanonicalVarInfo` and friends into `rustc_type_ir` Depends on #117580 and #117578 Uplift `CanonicalVarInfo` and friends into `rustc_type_ir` so they can be consumed by an interner-agnostic `Canonicalizer` implementation for the new trait solver ❤️ r? `@ghost`
This commit is contained in:
commit
739d556826
@ -23,6 +23,8 @@
|
||||
|
||||
use rustc_macros::HashStable;
|
||||
use rustc_type_ir::Canonical as IrCanonical;
|
||||
use rustc_type_ir::CanonicalVarInfo as IrCanonicalVarInfo;
|
||||
pub use rustc_type_ir::{CanonicalTyVarKind, CanonicalVarKind};
|
||||
use smallvec::SmallVec;
|
||||
use std::ops::Index;
|
||||
|
||||
@ -33,6 +35,8 @@
|
||||
|
||||
pub type Canonical<'tcx, V> = IrCanonical<TyCtxt<'tcx>, V>;
|
||||
|
||||
pub type CanonicalVarInfo<'tcx> = IrCanonicalVarInfo<TyCtxt<'tcx>>;
|
||||
|
||||
pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
|
||||
|
||||
impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
|
||||
@ -138,158 +142,6 @@ fn default() -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
/// 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(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub struct CanonicalVarInfo<'tcx> {
|
||||
pub kind: CanonicalVarKind<'tcx>,
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarInfo<'tcx> {
|
||||
pub fn universe(&self) -> ty::UniverseIndex {
|
||||
self.kind.universe()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
|
||||
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 => bug!("expected placeholder: {self:?}"),
|
||||
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.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(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
|
||||
#[derive(TypeFoldable, TypeVisitable)]
|
||||
pub enum CanonicalVarKind<'tcx> {
|
||||
/// Some kind of type inference variable.
|
||||
Ty(CanonicalTyVarKind),
|
||||
|
||||
/// A "placeholder" that represents "any type".
|
||||
PlaceholderTy(ty::PlaceholderType),
|
||||
|
||||
/// Region variable `'?R`.
|
||||
Region(ty::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(ty::PlaceholderRegion),
|
||||
|
||||
/// Some kind of const inference variable.
|
||||
Const(ty::UniverseIndex, Ty<'tcx>),
|
||||
|
||||
/// Effect variable `'?E`.
|
||||
Effect,
|
||||
|
||||
/// A "placeholder" that represents "any const".
|
||||
PlaceholderConst(ty::PlaceholderConst, Ty<'tcx>),
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarKind<'tcx> {
|
||||
pub fn universe(self) -> ty::UniverseIndex {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float | CanonicalTyVarKind::Int) => {
|
||||
ty::UniverseIndex::ROOT
|
||||
}
|
||||
CanonicalVarKind::Effect => ty::UniverseIndex::ROOT,
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
|
||||
CanonicalVarKind::Region(ui) => ui,
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
|
||||
CanonicalVarKind::Const(ui, _) => ui,
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||
}
|
||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
||||
| CanonicalVarKind::Effect => {
|
||||
assert_eq!(ui, ty::UniverseIndex::ROOT);
|
||||
self
|
||||
}
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
|
||||
}
|
||||
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
|
||||
}
|
||||
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
||||
CanonicalVarKind::PlaceholderConst(
|
||||
ty::Placeholder { universe: ui, ..placeholder },
|
||||
ty,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// 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, TyDecodable, TyEncodable, HashStable)]
|
||||
pub enum CanonicalTyVarKind {
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
General(ty::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,
|
||||
}
|
||||
|
||||
/// After we execute a query with a canonicalized key, we get back a
|
||||
/// `Canonical<QueryResponse<..>>`. You can use
|
||||
/// `instantiate_query_result` to access the data in this result.
|
||||
@ -366,7 +218,6 @@ pub fn is_proven(&self) -> bool {
|
||||
|
||||
TrivialTypeTraversalImpls! {
|
||||
crate::infer::canonical::Certainty,
|
||||
crate::infer::canonical::CanonicalTyVarKind,
|
||||
}
|
||||
|
||||
impl<'tcx> CanonicalVarValues<'tcx> {
|
||||
|
@ -94,7 +94,7 @@
|
||||
pub use self::rvalue_scopes::RvalueScopes;
|
||||
pub use self::sty::BoundRegionKind::*;
|
||||
pub use self::sty::{
|
||||
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind, BoundVar,
|
||||
AliasTy, Article, Binder, BoundRegion, BoundRegionKind, BoundTy, BoundTyKind,
|
||||
BoundVariableKind, CanonicalPolyFnSig, ClauseKind, ClosureArgs, ClosureArgsParts, ConstKind,
|
||||
CoroutineArgs, CoroutineArgsParts, EarlyParamRegion, ExistentialPredicate,
|
||||
ExistentialProjection, ExistentialTraitRef, FnSig, GenSig, InlineConstArgs,
|
||||
@ -1517,8 +1517,36 @@ pub struct Placeholder<T> {
|
||||
|
||||
pub type PlaceholderRegion = Placeholder<BoundRegion>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderRegion {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
pub type PlaceholderType = Placeholder<BoundTy>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderType {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
self.bound.var
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
|
||||
#[derive(TyEncodable, TyDecodable, PartialOrd, Ord)]
|
||||
pub struct BoundConst<'tcx> {
|
||||
@ -1528,6 +1556,20 @@ pub struct BoundConst<'tcx> {
|
||||
|
||||
pub type PlaceholderConst = Placeholder<BoundVar>;
|
||||
|
||||
impl rustc_type_ir::Placeholder for PlaceholderConst {
|
||||
fn universe(&self) -> UniverseIndex {
|
||||
self.universe
|
||||
}
|
||||
|
||||
fn var(&self) -> BoundVar {
|
||||
self.bound
|
||||
}
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
||||
Placeholder { universe: ui, ..self }
|
||||
}
|
||||
}
|
||||
|
||||
/// When type checking, we use the `ParamEnv` to track
|
||||
/// details about the set of where-clauses that are in scope at this
|
||||
/// particular point.
|
||||
|
@ -32,6 +32,7 @@
|
||||
use std::ops::{ControlFlow, Deref, Range};
|
||||
use ty::util::IntTypeExt;
|
||||
|
||||
use rustc_type_ir::BoundVar;
|
||||
use rustc_type_ir::ClauseKind as IrClauseKind;
|
||||
use rustc_type_ir::CollectAndApply;
|
||||
use rustc_type_ir::ConstKind as IrConstKind;
|
||||
@ -1621,12 +1622,6 @@ fn index(self) -> usize {
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[derive(HashStable)]
|
||||
#[debug_format = "{}"]
|
||||
pub struct BoundVar {}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, TyEncodable, TyDecodable)]
|
||||
#[derive(HashStable)]
|
||||
pub struct BoundTy {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::{Interner, UniverseIndex};
|
||||
use crate::{Interner, Placeholder, UniverseIndex};
|
||||
|
||||
/// A "canonicalized" type `V` is one where all free inference
|
||||
/// variables have been rewritten to "canonical vars". These are
|
||||
@ -113,3 +113,257 @@ fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> ControlFlow<F::BreakT
|
||||
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 = ""),
|
||||
Hash(bound = ""),
|
||||
Copy(bound = "CanonicalVarKind<I>: Copy"),
|
||||
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 = ""), 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> Copy for CanonicalVarKind<I>
|
||||
where
|
||||
I::PlaceholderTy: Copy,
|
||||
I::PlaceholderRegion: Copy,
|
||||
I::PlaceholderConst: Copy,
|
||||
I::Ty: Copy,
|
||||
{
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
use std::fmt::Debug;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::{DebugWithInfcx, Mutability};
|
||||
use crate::{BoundVar, DebugWithInfcx, Mutability, UniverseIndex};
|
||||
|
||||
pub trait Interner: Sized {
|
||||
type DefId: Clone + Debug + Hash + Ord;
|
||||
@ -26,7 +26,7 @@ pub trait Interner: Sized {
|
||||
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 PlaceholderTy: Clone + Debug + Hash + Ord + Placeholder;
|
||||
|
||||
// Things stored inside of tys
|
||||
type ErrorGuaranteed: Clone + Debug + Hash + Ord;
|
||||
@ -37,7 +37,7 @@ pub trait Interner: Sized {
|
||||
// Kinds of consts
|
||||
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderConst: Clone + Debug + Hash + Ord;
|
||||
type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder;
|
||||
type ParamConst: Clone + Debug + Hash + Ord;
|
||||
type BoundConst: Clone + Debug + Hash + Ord;
|
||||
type ValueConst: Clone + Debug + Hash + Ord;
|
||||
@ -49,7 +49,7 @@ pub trait Interner: Sized {
|
||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||
type LateParamRegion: Clone + Debug + Hash + Ord;
|
||||
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||
type PlaceholderRegion: Clone + Debug + Hash + Ord;
|
||||
type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder;
|
||||
|
||||
// Predicates
|
||||
type Predicate: Clone + Debug + Hash + Eq;
|
||||
@ -64,6 +64,14 @@ pub trait Interner: Sized {
|
||||
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
|
||||
}
|
||||
|
||||
/// Common capabilities of placeholder kinds
|
||||
pub trait Placeholder {
|
||||
fn universe(&self) -> UniverseIndex;
|
||||
fn var(&self) -> BoundVar;
|
||||
|
||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self;
|
||||
}
|
||||
|
||||
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||
/// that produces `T` items. You could combine them with
|
||||
/// `f(&iter.collect::<Vec<_>>())`, but this requires allocating memory for the
|
||||
|
@ -332,3 +332,10 @@ pub fn cannot_name(self, other: UniverseIndex) -> bool {
|
||||
self.private < other.private
|
||||
}
|
||||
}
|
||||
|
||||
rustc_index::newtype_index! {
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||
#[debug_format = "{}"]
|
||||
#[gate_rustc_only]
|
||||
pub struct BoundVar {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user