Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uplift CanonicalVarInfo and friends into rustc_type_ir #117582

Merged
merged 2 commits into from
Nov 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading