Skip to content

Commit

Permalink
Auto merge of #117582 - compiler-errors:uplift-canonical-var, r=jackh726
Browse files Browse the repository at this point in the history
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`
  • Loading branch information
bors committed Nov 22, 2023
2 parents ed10a53 + d1daf0e commit 739d556
Show file tree
Hide file tree
Showing 6 changed files with 322 additions and 165 deletions.
157 changes: 4 additions & 153 deletions compiler/rustc_middle/src/infer/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -33,6 +35,8 @@ use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};

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> {
Expand Down Expand Up @@ -138,158 +142,6 @@ impl<'tcx> Default for OriginalQueryValues<'tcx> {
}
}

/// 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.
Expand Down Expand Up @@ -366,7 +218,6 @@ pub type QueryOutlivesConstraint<'tcx> =

TrivialTypeTraversalImpls! {
crate::infer::canonical::Certainty,
crate::infer::canonical::CanonicalTyVarKind,
}

impl<'tcx> CanonicalVarValues<'tcx> {
Expand Down
44 changes: 43 additions & 1 deletion compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ pub use self::parameterized::ParameterizedOverTcx;
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,
Expand Down Expand Up @@ -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> {
Expand All @@ -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.
Expand Down
7 changes: 1 addition & 6 deletions compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use std::fmt;
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;
Expand Down Expand Up @@ -1621,12 +1622,6 @@ impl Atom for RegionVid {
}
}

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 {
Expand Down
Loading

0 comments on commit 739d556

Please sign in to comment.