Uplift canonicalizer into new trait solver crate
This commit is contained in:
parent
ae612bedcb
commit
cb41509601
20 changed files with 507 additions and 273 deletions
|
@ -4303,6 +4303,13 @@ dependencies = [
|
||||||
"tracing",
|
"tracing",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc_next_trait_solver"
|
||||||
|
version = "0.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"rustc_type_ir",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_parse"
|
name = "rustc_parse"
|
||||||
version = "0.0.0"
|
version = "0.0.0"
|
||||||
|
@ -4571,6 +4578,7 @@ dependencies = [
|
||||||
"rustc_infer",
|
"rustc_infer",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_middle",
|
"rustc_middle",
|
||||||
|
"rustc_next_trait_solver",
|
||||||
"rustc_parse_format",
|
"rustc_parse_format",
|
||||||
"rustc_query_system",
|
"rustc_query_system",
|
||||||
"rustc_session",
|
"rustc_session",
|
||||||
|
|
|
@ -345,37 +345,61 @@ pub struct InferCtxt<'tcx> {
|
||||||
impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> {
|
||||||
type Interner = TyCtxt<'tcx>;
|
type Interner = TyCtxt<'tcx>;
|
||||||
|
|
||||||
fn universe_of_ty(&self, ty: ty::InferTy) -> Option<ty::UniverseIndex> {
|
fn interner(&self) -> TyCtxt<'tcx> {
|
||||||
use InferTy::*;
|
self.tcx
|
||||||
match ty {
|
}
|
||||||
// FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
|
|
||||||
// ty infers will give you the universe of the var it resolved to not the universe
|
fn universe_of_ty(&self, vid: TyVid) -> Option<ty::UniverseIndex> {
|
||||||
// it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
|
// FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
|
||||||
// try to print out `?0.1` it will just print `?0`.
|
// ty infers will give you the universe of the var it resolved to not the universe
|
||||||
TyVar(ty_vid) => match self.probe_ty_var(ty_vid) {
|
// it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
|
||||||
Err(universe) => Some(universe),
|
// try to print out `?0.1` it will just print `?0`.
|
||||||
Ok(_) => None,
|
match self.probe_ty_var(vid) {
|
||||||
},
|
Err(universe) => Some(universe),
|
||||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None,
|
Ok(_) => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_ct(&self, ct: ty::InferConst) -> Option<ty::UniverseIndex> {
|
fn universe_of_ct(&self, ct: ConstVid) -> Option<ty::UniverseIndex> {
|
||||||
use ty::InferConst::*;
|
// Same issue as with `universe_of_ty`
|
||||||
match ct {
|
match self.probe_const_var(ct) {
|
||||||
// Same issue as with `universe_of_ty`
|
Err(universe) => Some(universe),
|
||||||
Var(ct_vid) => match self.probe_const_var(ct_vid) {
|
Ok(_) => None,
|
||||||
Err(universe) => Some(universe),
|
|
||||||
Ok(_) => None,
|
|
||||||
},
|
|
||||||
EffectVar(_) => None,
|
|
||||||
Fresh(_) => None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
|
||||||
Some(self.universe_of_region_vid(lt))
|
Some(self.universe_of_region_vid(lt))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn root_ty_var(&self, vid: TyVid) -> TyVid {
|
||||||
|
self.root_var(vid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_ty_var(&self, vid: TyVid) -> Option<Ty<'tcx>> {
|
||||||
|
self.probe_ty_var(vid).ok()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_lt_var(&self, vid: ty::RegionVid) -> ty::RegionVid {
|
||||||
|
self.root_region_var(vid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_lt_var(&self, vid: ty::RegionVid) -> Option<ty::Region<'tcx>> {
|
||||||
|
let re = self
|
||||||
|
.inner
|
||||||
|
.borrow_mut()
|
||||||
|
.unwrap_region_constraints()
|
||||||
|
.opportunistic_resolve_var(self.tcx, vid);
|
||||||
|
if re.is_var() { None } else { Some(re) }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
|
||||||
|
self.root_const_var(vid)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_ct_var(&self, vid: ConstVid) -> Option<ty::Const<'tcx>> {
|
||||||
|
self.probe_const_var(vid).ok()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See the `error_reporting` module for more details.
|
/// See the `error_reporting` module for more details.
|
||||||
|
@ -1347,6 +1371,10 @@ impl<'tcx> InferCtxt<'tcx> {
|
||||||
self.inner.borrow_mut().type_variables().root_var(var)
|
self.inner.borrow_mut().type_variables().root_var(var)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_region_var(&self, var: ty::RegionVid) -> ty::RegionVid {
|
||||||
|
self.inner.borrow_mut().unwrap_region_constraints().root_var(var)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
pub fn root_const_var(&self, var: ty::ConstVid) -> ty::ConstVid {
|
||||||
self.inner.borrow_mut().const_unification_table().find(var).vid
|
self.inner.borrow_mut().const_unification_table().find(var).vid
|
||||||
}
|
}
|
||||||
|
|
|
@ -623,6 +623,11 @@ impl<'tcx> RegionConstraintCollector<'_, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn root_var(&mut self, vid: ty::RegionVid) -> ty::RegionVid {
|
||||||
|
let mut ut = self.unification_table_mut(); // FIXME(rust-lang/ena#42): unnecessary mut
|
||||||
|
ut.find(vid).vid
|
||||||
|
}
|
||||||
|
|
||||||
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
|
fn combine_map(&mut self, t: CombineMapType) -> &mut CombineMap<'tcx> {
|
||||||
match t {
|
match t {
|
||||||
Glb => &mut self.glbs,
|
Glb => &mut self.glbs,
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustc_hir as hir;
|
||||||
use rustc_hir::def::{DefKind, Res};
|
use rustc_hir::def::{DefKind, Res};
|
||||||
use rustc_hir::def_id::LocalDefId;
|
use rustc_hir::def_id::LocalDefId;
|
||||||
use rustc_macros::HashStable;
|
use rustc_macros::HashStable;
|
||||||
use rustc_type_ir::{TypeFlags, WithCachedTypeInfo};
|
use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo};
|
||||||
|
|
||||||
mod int;
|
mod int;
|
||||||
mod kind;
|
mod kind;
|
||||||
|
@ -26,6 +26,20 @@ use super::sty::ConstKind;
|
||||||
#[rustc_pass_by_value]
|
#[rustc_pass_by_value]
|
||||||
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
|
pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo<ConstData<'tcx>>>);
|
||||||
|
|
||||||
|
impl<'tcx> IntoKind for Const<'tcx> {
|
||||||
|
type Kind = ConstKind<'tcx>;
|
||||||
|
|
||||||
|
fn kind(&self) -> ConstKind<'tcx> {
|
||||||
|
(*self).kind().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ConstTy<TyCtxt<'tcx>> for Const<'tcx> {
|
||||||
|
fn ty(&self) -> Ty<'tcx> {
|
||||||
|
(*self).ty()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Typed constant value.
|
/// Typed constant value.
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
|
||||||
pub struct ConstData<'tcx> {
|
pub struct ConstData<'tcx> {
|
||||||
|
|
|
@ -131,6 +131,42 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
|
||||||
) -> (Self::Ty, ty::Mutability) {
|
) -> (Self::Ty, ty::Mutability) {
|
||||||
(ty, mutbl)
|
(ty, mutbl)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn mk_canonical_var_infos(
|
||||||
|
&self,
|
||||||
|
infos: &[rustc_type_ir::CanonicalVarInfo<Self>],
|
||||||
|
) -> Self::CanonicalVars {
|
||||||
|
(*self).mk_canonical_var_infos(infos)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_bound_ty(
|
||||||
|
&self,
|
||||||
|
debruijn: rustc_type_ir::DebruijnIndex,
|
||||||
|
var: rustc_type_ir::BoundVar,
|
||||||
|
) -> Self::Ty {
|
||||||
|
Ty::new_bound(*self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_bound_region(
|
||||||
|
&self,
|
||||||
|
debruijn: rustc_type_ir::DebruijnIndex,
|
||||||
|
var: rustc_type_ir::BoundVar,
|
||||||
|
) -> Self::Region {
|
||||||
|
Region::new_bound(
|
||||||
|
*self,
|
||||||
|
debruijn,
|
||||||
|
ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mk_bound_const(
|
||||||
|
&self,
|
||||||
|
debruijn: rustc_type_ir::DebruijnIndex,
|
||||||
|
var: rustc_type_ir::BoundVar,
|
||||||
|
ty: Self::Ty,
|
||||||
|
) -> Self::Const {
|
||||||
|
Const::new_bound(*self, debruijn, var, ty)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
type InternedSet<'tcx, T> = ShardedHashMap<InternedInSet<'tcx, T>, ()>;
|
||||||
|
|
|
@ -474,6 +474,14 @@ pub struct CReaderCacheKey {
|
||||||
#[rustc_pass_by_value]
|
#[rustc_pass_by_value]
|
||||||
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
|
pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo<TyKind<'tcx>>>);
|
||||||
|
|
||||||
|
impl<'tcx> IntoKind for Ty<'tcx> {
|
||||||
|
type Kind = TyKind<'tcx>;
|
||||||
|
|
||||||
|
fn kind(&self) -> TyKind<'tcx> {
|
||||||
|
(*self).kind().clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl EarlyParamRegion {
|
impl EarlyParamRegion {
|
||||||
/// Does this early bound region have a name? Early bound regions normally
|
/// Does this early bound region have a name? Early bound regions normally
|
||||||
/// always have names except when using anonymous lifetimes (`'_`).
|
/// always have names except when using anonymous lifetimes (`'_`).
|
||||||
|
@ -1554,8 +1562,12 @@ impl rustc_type_ir::Placeholder for PlaceholderRegion {
|
||||||
self.bound.var
|
self.bound.var
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
fn with_updated_universe(&self, ui: UniverseIndex) -> Self {
|
||||||
Placeholder { universe: ui, ..self }
|
Placeholder { universe: ui, ..*self }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||||
|
Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1570,8 +1582,12 @@ impl rustc_type_ir::Placeholder for PlaceholderType {
|
||||||
self.bound.var
|
self.bound.var
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
fn with_updated_universe(&self, ui: UniverseIndex) -> Self {
|
||||||
Placeholder { universe: ui, ..self }
|
Placeholder { universe: ui, ..*self }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||||
|
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1593,8 +1609,12 @@ impl rustc_type_ir::Placeholder for PlaceholderConst {
|
||||||
self.bound
|
self.bound
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self {
|
fn with_updated_universe(&self, ui: UniverseIndex) -> Self {
|
||||||
Placeholder { universe: ui, ..self }
|
Placeholder { universe: ui, ..*self }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn new(ui: UniverseIndex, var: BoundVar) -> Self {
|
||||||
|
Placeholder { universe: ui, bound: var }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::infer::canonical::Canonical;
|
||||||
use crate::ty::visit::ValidateBoundVars;
|
use crate::ty::visit::ValidateBoundVars;
|
||||||
use crate::ty::InferTy::*;
|
use crate::ty::InferTy::*;
|
||||||
use crate::ty::{
|
use crate::ty::{
|
||||||
self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
|
self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable,
|
||||||
TypeVisitableExt, TypeVisitor,
|
TypeVisitableExt, TypeVisitor,
|
||||||
};
|
};
|
||||||
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
use crate::ty::{GenericArg, GenericArgs, GenericArgsRef};
|
||||||
|
@ -1477,6 +1477,14 @@ impl ParamConst {
|
||||||
#[rustc_pass_by_value]
|
#[rustc_pass_by_value]
|
||||||
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
|
pub struct Region<'tcx>(pub Interned<'tcx, RegionKind<'tcx>>);
|
||||||
|
|
||||||
|
impl<'tcx> IntoKind for Region<'tcx> {
|
||||||
|
type Kind = RegionKind<'tcx>;
|
||||||
|
|
||||||
|
fn kind(&self) -> RegionKind<'tcx> {
|
||||||
|
**self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> Region<'tcx> {
|
impl<'tcx> Region<'tcx> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new_early_param(
|
pub fn new_early_param(
|
||||||
|
|
7
compiler/rustc_next_trait_solver/Cargo.toml
Normal file
7
compiler/rustc_next_trait_solver/Cargo.toml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
[package]
|
||||||
|
name = "rustc_next_trait_solver"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
rustc_type_ir = { path = "../rustc_type_ir" }
|
|
@ -1,17 +1,11 @@
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
|
|
||||||
use crate::infer::InferCtxt;
|
use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
||||||
use rustc_middle::infer::canonical::Canonical;
|
use rustc_type_ir::{
|
||||||
use rustc_middle::infer::canonical::CanonicalTyVarKind;
|
BoundVar, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstKind,
|
||||||
use rustc_middle::infer::canonical::CanonicalVarInfo;
|
ConstTy, DebruijnIndex, InferConst, InferCtxtLike, InferTy, Interner, IntoKind, Placeholder,
|
||||||
use rustc_middle::infer::canonical::CanonicalVarInfos;
|
RegionKind, TyKind, UniverseIndex, INNERMOST,
|
||||||
use rustc_middle::infer::canonical::CanonicalVarKind;
|
};
|
||||||
use rustc_middle::ty::BoundRegionKind::BrAnon;
|
|
||||||
use rustc_middle::ty::BoundTyKind;
|
|
||||||
use rustc_middle::ty::TyCtxt;
|
|
||||||
use rustc_middle::ty::TypeVisitableExt;
|
|
||||||
use rustc_middle::ty::{self, Ty};
|
|
||||||
use rustc_middle::ty::{TypeFoldable, TypeFolder, TypeSuperFoldable};
|
|
||||||
|
|
||||||
/// Whether we're canonicalizing a query input or the query response.
|
/// Whether we're canonicalizing a query input or the query response.
|
||||||
///
|
///
|
||||||
|
@ -38,46 +32,46 @@ pub enum CanonicalizeMode {
|
||||||
///
|
///
|
||||||
/// This doesn't work for universes created inside of the query so
|
/// This doesn't work for universes created inside of the query so
|
||||||
/// we do remember their universe in the response.
|
/// we do remember their universe in the response.
|
||||||
max_input_universe: ty::UniverseIndex,
|
max_input_universe: UniverseIndex,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Canonicalizer<'a, 'tcx> {
|
pub struct Canonicalizer<'a, Infcx: InferCtxtLike> {
|
||||||
infcx: &'a InferCtxt<'tcx>,
|
infcx: &'a Infcx,
|
||||||
canonicalize_mode: CanonicalizeMode,
|
canonicalize_mode: CanonicalizeMode,
|
||||||
|
|
||||||
variables: &'a mut Vec<ty::GenericArg<'tcx>>,
|
variables: &'a mut Vec<<Infcx::Interner as Interner>::GenericArg>,
|
||||||
primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>,
|
primitive_var_infos: Vec<CanonicalVarInfo<Infcx::Interner>>,
|
||||||
binder_index: ty::DebruijnIndex,
|
binder_index: DebruijnIndex,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infcx> {
|
||||||
#[instrument(level = "debug", skip(infcx), ret)]
|
pub fn canonicalize<T: TypeFoldable<I>>(
|
||||||
pub fn canonicalize<T: TypeFoldable<TyCtxt<'tcx>>>(
|
infcx: &'a Infcx,
|
||||||
infcx: &'a InferCtxt<'tcx>,
|
|
||||||
canonicalize_mode: CanonicalizeMode,
|
canonicalize_mode: CanonicalizeMode,
|
||||||
variables: &'a mut Vec<ty::GenericArg<'tcx>>,
|
variables: &'a mut Vec<<I as Interner>::GenericArg>,
|
||||||
value: T,
|
value: T,
|
||||||
) -> Canonical<'tcx, T> {
|
) -> Canonical<I, T> {
|
||||||
let mut canonicalizer = Canonicalizer {
|
let mut canonicalizer = Canonicalizer {
|
||||||
infcx,
|
infcx,
|
||||||
canonicalize_mode,
|
canonicalize_mode,
|
||||||
|
|
||||||
variables,
|
variables,
|
||||||
primitive_var_infos: Vec::new(),
|
primitive_var_infos: Vec::new(),
|
||||||
binder_index: ty::INNERMOST,
|
binder_index: INNERMOST,
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = value.fold_with(&mut canonicalizer);
|
let value = value.fold_with(&mut canonicalizer);
|
||||||
assert!(!value.has_infer(), "unexpected infer in {value:?}");
|
// FIXME: Restore these assertions. Should we uplift type flags?
|
||||||
assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
|
// assert!(!value.has_infer(), "unexpected infer in {value:?}");
|
||||||
|
// assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}");
|
||||||
|
|
||||||
let (max_universe, variables) = canonicalizer.finalize();
|
let (max_universe, variables) = canonicalizer.finalize();
|
||||||
|
|
||||||
Canonical { max_universe, variables, value }
|
Canonical { max_universe, variables, value }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) {
|
fn finalize(self) -> (UniverseIndex, <I as Interner>::CanonicalVars) {
|
||||||
let mut var_infos = self.primitive_var_infos;
|
let mut var_infos = self.primitive_var_infos;
|
||||||
// See the rustc-dev-guide section about how we deal with universes
|
// See the rustc-dev-guide section about how we deal with universes
|
||||||
// during canonicalization in the new solver.
|
// during canonicalization in the new solver.
|
||||||
|
@ -94,18 +88,17 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||||
CanonicalizeMode::Response { max_input_universe } => {
|
CanonicalizeMode::Response { max_input_universe } => {
|
||||||
for var in var_infos.iter_mut() {
|
for var in var_infos.iter_mut() {
|
||||||
let uv = var.universe();
|
let uv = var.universe();
|
||||||
let new_uv = ty::UniverseIndex::from(
|
let new_uv =
|
||||||
uv.index().saturating_sub(max_input_universe.index()),
|
UniverseIndex::from(uv.index().saturating_sub(max_input_universe.index()));
|
||||||
);
|
|
||||||
*var = var.with_updated_universe(new_uv);
|
*var = var.with_updated_universe(new_uv);
|
||||||
}
|
}
|
||||||
let max_universe = var_infos
|
let max_universe = var_infos
|
||||||
.iter()
|
.iter()
|
||||||
.map(|info| info.universe())
|
.map(|info| info.universe())
|
||||||
.max()
|
.max()
|
||||||
.unwrap_or(ty::UniverseIndex::ROOT);
|
.unwrap_or(UniverseIndex::ROOT);
|
||||||
|
|
||||||
let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
|
let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos);
|
||||||
return (max_universe, var_infos);
|
return (max_universe, var_infos);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,11 +120,11 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||||
//
|
//
|
||||||
// This algorithm runs in `O(n²)` where `n` is the number of different universe
|
// This algorithm runs in `O(n²)` where `n` is the number of different universe
|
||||||
// indices in the input. This should be fine as `n` is expected to be small.
|
// indices in the input. This should be fine as `n` is expected to be small.
|
||||||
let mut curr_compressed_uv = ty::UniverseIndex::ROOT;
|
let mut curr_compressed_uv = UniverseIndex::ROOT;
|
||||||
let mut existential_in_new_uv = false;
|
let mut existential_in_new_uv = false;
|
||||||
let mut next_orig_uv = Some(ty::UniverseIndex::ROOT);
|
let mut next_orig_uv = Some(UniverseIndex::ROOT);
|
||||||
while let Some(orig_uv) = next_orig_uv.take() {
|
while let Some(orig_uv) = next_orig_uv.take() {
|
||||||
let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| {
|
let mut update_uv = |var: &mut CanonicalVarInfo<I>, orig_uv, is_existential| {
|
||||||
let uv = var.universe();
|
let uv = var.universe();
|
||||||
match uv.cmp(&orig_uv) {
|
match uv.cmp(&orig_uv) {
|
||||||
Ordering::Less => (), // Already updated
|
Ordering::Less => (), // Already updated
|
||||||
|
@ -183,23 +176,25 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
|
||||||
for var in var_infos.iter_mut() {
|
for var in var_infos.iter_mut() {
|
||||||
if var.is_region() {
|
if var.is_region() {
|
||||||
assert!(var.is_existential());
|
assert!(var.is_existential());
|
||||||
*var = var.with_updated_universe(curr_compressed_uv);
|
let compressed_var = var.with_updated_universe(curr_compressed_uv);
|
||||||
|
*var = compressed_var;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let var_infos = self.infcx.tcx.mk_canonical_var_infos(&var_infos);
|
let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos);
|
||||||
(curr_compressed_uv, var_infos)
|
(curr_compressed_uv, var_infos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
impl<Infcx: InferCtxtLike<Interner = I>, I: Interner> TypeFolder<I> for Canonicalizer<'_, Infcx> {
|
||||||
fn interner(&self) -> TyCtxt<'tcx> {
|
fn interner(&self) -> I {
|
||||||
self.infcx.tcx
|
self.infcx.interner()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
|
fn fold_binder<T>(&mut self, t: I::Binder<T>) -> I::Binder<T>
|
||||||
where
|
where
|
||||||
T: TypeFoldable<TyCtxt<'tcx>>,
|
T: TypeFoldable<I>,
|
||||||
|
I::Binder<T>: TypeSuperFoldable<I>,
|
||||||
{
|
{
|
||||||
self.binder_index.shift_in(1);
|
self.binder_index.shift_in(1);
|
||||||
let t = t.super_fold_with(self);
|
let t = t.super_fold_with(self);
|
||||||
|
@ -207,22 +202,9 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||||
t
|
t
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
|
fn fold_region(&mut self, r: I::Region) -> I::Region {
|
||||||
if let ty::ReVar(vid) = *r {
|
let kind = match r.kind() {
|
||||||
let resolved_region = self
|
RegionKind::ReBound(..) => return r,
|
||||||
.infcx
|
|
||||||
.inner
|
|
||||||
.borrow_mut()
|
|
||||||
.unwrap_region_constraints()
|
|
||||||
.opportunistic_resolve_var(self.infcx.tcx, vid);
|
|
||||||
assert_eq!(
|
|
||||||
r, resolved_region,
|
|
||||||
"region var should have been resolved, {r} -> {resolved_region}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let kind = match *r {
|
|
||||||
ty::ReBound(..) => return r,
|
|
||||||
|
|
||||||
// We may encounter `ReStatic` in item signatures or the hidden type
|
// We may encounter `ReStatic` in item signatures or the hidden type
|
||||||
// of an opaque. `ReErased` should only be encountered in the hidden
|
// of an opaque. `ReErased` should only be encountered in the hidden
|
||||||
|
@ -232,197 +214,212 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
|
||||||
// FIXME: We should investigate the perf implications of not uniquifying
|
// FIXME: We should investigate the perf implications of not uniquifying
|
||||||
// `ReErased`. We may be able to short-circuit registering region
|
// `ReErased`. We may be able to short-circuit registering region
|
||||||
// obligations if we encounter a `ReErased` on one side, for example.
|
// obligations if we encounter a `ReErased` on one side, for example.
|
||||||
ty::ReStatic | ty::ReErased => match self.canonicalize_mode {
|
RegionKind::ReStatic | RegionKind::ReErased => match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT),
|
||||||
CanonicalizeMode::Response { .. } => return r,
|
CanonicalizeMode::Response { .. } => return r,
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::ReLateParam(_) | ty::ReEarlyParam(_) => match self.canonicalize_mode {
|
RegionKind::ReEarlyParam(_) | RegionKind::ReLateParam(_) => {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"),
|
CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT),
|
||||||
},
|
CanonicalizeMode::Response { .. } => {
|
||||||
|
panic!("unexpected region in response: {r:?}")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
|
RegionKind::RePlaceholder(placeholder) => match self.canonicalize_mode {
|
||||||
// We canonicalize placeholder regions as existentials in query inputs.
|
// We canonicalize placeholder regions as existentials in query inputs.
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT),
|
||||||
CanonicalizeMode::Response { max_input_universe } => {
|
CanonicalizeMode::Response { max_input_universe } => {
|
||||||
// If we have a placeholder region inside of a query, it must be from
|
// If we have a placeholder region inside of a query, it must be from
|
||||||
// a new universe.
|
// a new universe.
|
||||||
if max_input_universe.can_name(placeholder.universe) {
|
if max_input_universe.can_name(placeholder.universe()) {
|
||||||
bug!("new placeholder in universe {max_input_universe:?}: {r:?}");
|
panic!("new placeholder in universe {max_input_universe:?}: {r:?}");
|
||||||
}
|
}
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder)
|
CanonicalVarKind::PlaceholderRegion(placeholder)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ty::ReVar(_) => match self.canonicalize_mode {
|
RegionKind::ReVar(vid) => {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
|
assert_eq!(
|
||||||
CanonicalizeMode::Response { .. } => {
|
self.infcx.root_lt_var(vid.clone()),
|
||||||
CanonicalVarKind::Region(self.infcx.universe_of_region(r))
|
vid,
|
||||||
}
|
"region vid should have been resolved fully before canonicalization"
|
||||||
},
|
);
|
||||||
|
assert_eq!(
|
||||||
|
self.infcx.probe_lt_var(vid.clone()),
|
||||||
|
None,
|
||||||
|
"region vid should have been resolved fully before canonicalization"
|
||||||
|
);
|
||||||
|
|
||||||
ty::ReError(_) => return r,
|
match self.canonicalize_mode {
|
||||||
|
CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT),
|
||||||
|
CanonicalizeMode::Response { .. } => {
|
||||||
|
CanonicalVarKind::Region(self.infcx.universe_of_lt(vid).unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RegionKind::ReError(_) => return r,
|
||||||
};
|
};
|
||||||
|
|
||||||
let existing_bound_var = match self.canonicalize_mode {
|
let existing_bound_var = match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => None,
|
CanonicalizeMode::Input => None,
|
||||||
CanonicalizeMode::Response { .. } => {
|
CanonicalizeMode::Response { .. } => {
|
||||||
self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from)
|
let r = r.clone().into();
|
||||||
|
self.variables.iter().position(|v| v == &r).map(BoundVar::from)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let var = existing_bound_var.unwrap_or_else(|| {
|
let var = existing_bound_var.unwrap_or_else(|| {
|
||||||
let var = ty::BoundVar::from(self.variables.len());
|
let var = BoundVar::from(self.variables.len());
|
||||||
self.variables.push(r.into());
|
self.variables.push(r.into());
|
||||||
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
||||||
var
|
var
|
||||||
});
|
});
|
||||||
let br = ty::BoundRegion { var, kind: BrAnon };
|
|
||||||
ty::Region::new_bound(self.interner(), self.binder_index, br)
|
self.interner().mk_bound_region(self.binder_index, var)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
fn fold_ty(&mut self, t: I::Ty) -> I::Ty
|
||||||
let kind = match *t.kind() {
|
where
|
||||||
ty::Infer(ty::TyVar(vid)) => {
|
I::Ty: TypeSuperFoldable<I>,
|
||||||
assert_eq!(self.infcx.root_var(vid), vid, "ty vid should have been resolved");
|
{
|
||||||
let Err(ui) = self.infcx.probe_ty_var(vid) else {
|
let kind = match t.kind() {
|
||||||
bug!("ty var should have been resolved: {t}");
|
TyKind::Infer(i) => match i {
|
||||||
};
|
InferTy::TyVar(vid) => {
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
assert_eq!(
|
||||||
}
|
self.infcx.root_ty_var(vid),
|
||||||
ty::Infer(ty::IntVar(vid)) => {
|
vid,
|
||||||
assert_eq!(self.infcx.opportunistic_resolve_int_var(vid), t);
|
"ty vid should have been resolved fully before canonicalization"
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int)
|
);
|
||||||
}
|
assert_eq!(
|
||||||
ty::Infer(ty::FloatVar(vid)) => {
|
self.infcx.probe_ty_var(vid),
|
||||||
assert_eq!(self.infcx.opportunistic_resolve_float_var(vid), t);
|
None,
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Float)
|
"ty vid should have been resolved fully before canonicalization"
|
||||||
}
|
);
|
||||||
ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
|
|
||||||
bug!("fresh var during canonicalization: {t:?}")
|
CanonicalVarKind::Ty(CanonicalTyVarKind::General(
|
||||||
}
|
self.infcx
|
||||||
ty::Placeholder(placeholder) => match self.canonicalize_mode {
|
.universe_of_ty(vid)
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
.unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
|
||||||
universe: placeholder.universe,
|
))
|
||||||
bound: ty::BoundTy {
|
}
|
||||||
var: ty::BoundVar::from_usize(self.variables.len()),
|
InferTy::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
|
||||||
kind: ty::BoundTyKind::Anon,
|
InferTy::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
|
||||||
},
|
InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => {
|
||||||
}),
|
todo!()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
TyKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||||
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(Placeholder::new(
|
||||||
|
placeholder.universe(),
|
||||||
|
self.variables.len().into(),
|
||||||
|
)),
|
||||||
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
|
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
|
||||||
},
|
},
|
||||||
ty::Param(_) => match self.canonicalize_mode {
|
TyKind::Param(_) => match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder {
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(Placeholder::new(
|
||||||
universe: ty::UniverseIndex::ROOT,
|
UniverseIndex::ROOT,
|
||||||
bound: ty::BoundTy {
|
self.variables.len().into(),
|
||||||
var: ty::BoundVar::from_usize(self.variables.len()),
|
)),
|
||||||
kind: ty::BoundTyKind::Anon,
|
CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"),
|
||||||
},
|
|
||||||
}),
|
|
||||||
CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"),
|
|
||||||
},
|
},
|
||||||
ty::Bool
|
TyKind::Bool
|
||||||
| ty::Char
|
| TyKind::Char
|
||||||
| ty::Int(_)
|
| TyKind::Int(_)
|
||||||
| ty::Uint(_)
|
| TyKind::Uint(_)
|
||||||
| ty::Float(_)
|
| TyKind::Float(_)
|
||||||
| ty::Adt(_, _)
|
| TyKind::Adt(_, _)
|
||||||
| ty::Foreign(_)
|
| TyKind::Foreign(_)
|
||||||
| ty::Str
|
| TyKind::Str
|
||||||
| ty::Array(_, _)
|
| TyKind::Array(_, _)
|
||||||
| ty::Slice(_)
|
| TyKind::Slice(_)
|
||||||
| ty::RawPtr(_)
|
| TyKind::RawPtr(_)
|
||||||
| ty::Ref(_, _, _)
|
| TyKind::Ref(_, _, _)
|
||||||
| ty::FnDef(_, _)
|
| TyKind::FnDef(_, _)
|
||||||
| ty::FnPtr(_)
|
| TyKind::FnPtr(_)
|
||||||
| ty::Dynamic(_, _, _)
|
| TyKind::Dynamic(_, _, _)
|
||||||
| ty::Closure(_, _)
|
| TyKind::Closure(_, _)
|
||||||
| ty::Coroutine(_, _, _)
|
| TyKind::Coroutine(_, _, _)
|
||||||
| ty::CoroutineWitness(..)
|
| TyKind::CoroutineWitness(..)
|
||||||
| ty::Never
|
| TyKind::Never
|
||||||
| ty::Tuple(_)
|
| TyKind::Tuple(_)
|
||||||
| ty::Alias(_, _)
|
| TyKind::Alias(_, _)
|
||||||
| ty::Bound(_, _)
|
| TyKind::Bound(_, _)
|
||||||
| ty::Error(_) => return t.super_fold_with(self),
|
| TyKind::Error(_) => return t.super_fold_with(self),
|
||||||
};
|
};
|
||||||
|
|
||||||
let var = ty::BoundVar::from(
|
let t = t.clone().into();
|
||||||
self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| {
|
let var =
|
||||||
|
BoundVar::from(self.variables.iter().position(|v| v == &t).unwrap_or_else(|| {
|
||||||
let var = self.variables.len();
|
let var = self.variables.len();
|
||||||
self.variables.push(t.into());
|
self.variables.push(t);
|
||||||
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
||||||
var
|
var
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
let bt = ty::BoundTy { var, kind: BoundTyKind::Anon };
|
self.interner().mk_bound_ty(self.binder_index, var)
|
||||||
Ty::new_bound(self.infcx.tcx, self.binder_index, bt)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> {
|
fn fold_const(&mut self, c: I::Const) -> I::Const
|
||||||
|
where
|
||||||
|
I::Const: TypeSuperFoldable<I>,
|
||||||
|
{
|
||||||
let kind = match c.kind() {
|
let kind = match c.kind() {
|
||||||
ty::ConstKind::Infer(ty::InferConst::Var(vid)) => {
|
ConstKind::Infer(i) => {
|
||||||
assert_eq!(
|
// FIXME: we should fold the ty too eventually
|
||||||
self.infcx.root_const_var(vid),
|
match i {
|
||||||
vid,
|
InferConst::Var(vid) => {
|
||||||
"const var should have been resolved"
|
assert_eq!(
|
||||||
);
|
self.infcx.root_ct_var(vid),
|
||||||
let Err(ui) = self.infcx.probe_const_var(vid) else {
|
vid,
|
||||||
bug!("const var should have been resolved");
|
"region vid should have been resolved fully before canonicalization"
|
||||||
};
|
);
|
||||||
// FIXME: we should fold this ty eventually
|
assert_eq!(
|
||||||
CanonicalVarKind::Const(ui, c.ty())
|
self.infcx.probe_ct_var(vid),
|
||||||
|
None,
|
||||||
|
"region vid should have been resolved fully before canonicalization"
|
||||||
|
);
|
||||||
|
CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
|
||||||
|
}
|
||||||
|
InferConst::EffectVar(_) => CanonicalVarKind::Effect,
|
||||||
|
InferConst::Fresh(_) => todo!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => {
|
ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
||||||
assert_eq!(
|
|
||||||
self.infcx.root_effect_var(vid),
|
|
||||||
vid,
|
|
||||||
"effect var should have been resolved"
|
|
||||||
);
|
|
||||||
let None = self.infcx.probe_effect_var(vid) else {
|
|
||||||
bug!("effect var should have been resolved");
|
|
||||||
};
|
|
||||||
CanonicalVarKind::Effect
|
|
||||||
}
|
|
||||||
ty::ConstKind::Infer(ty::InferConst::Fresh(_)) => {
|
|
||||||
bug!("fresh var during canonicalization: {c:?}")
|
|
||||||
}
|
|
||||||
ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
|
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||||
ty::Placeholder {
|
Placeholder::new(placeholder.universe(), self.variables.len().into()),
|
||||||
universe: placeholder.universe,
|
|
||||||
bound: ty::BoundVar::from(self.variables.len()),
|
|
||||||
},
|
|
||||||
c.ty(),
|
c.ty(),
|
||||||
),
|
),
|
||||||
CanonicalizeMode::Response { .. } => {
|
CanonicalizeMode::Response { .. } => {
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
|
CanonicalVarKind::PlaceholderConst(placeholder, c.ty())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ty::ConstKind::Param(_) => match self.canonicalize_mode {
|
ConstKind::Param(_) => match self.canonicalize_mode {
|
||||||
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
|
||||||
ty::Placeholder {
|
Placeholder::new(UniverseIndex::ROOT, self.variables.len().into()),
|
||||||
universe: ty::UniverseIndex::ROOT,
|
|
||||||
bound: ty::BoundVar::from(self.variables.len()),
|
|
||||||
},
|
|
||||||
c.ty(),
|
c.ty(),
|
||||||
),
|
),
|
||||||
CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"),
|
CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"),
|
||||||
},
|
},
|
||||||
ty::ConstKind::Bound(_, _)
|
ConstKind::Bound(_, _)
|
||||||
| ty::ConstKind::Unevaluated(_)
|
| ConstKind::Unevaluated(_)
|
||||||
| ty::ConstKind::Value(_)
|
| ConstKind::Value(_)
|
||||||
| ty::ConstKind::Error(_)
|
| ConstKind::Error(_)
|
||||||
| ty::ConstKind::Expr(_) => return c.super_fold_with(self),
|
| ConstKind::Expr(_) => return c.super_fold_with(self),
|
||||||
};
|
};
|
||||||
|
|
||||||
let var = ty::BoundVar::from(
|
let ty = c.ty();
|
||||||
self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| {
|
let c = c.clone().into();
|
||||||
|
let var =
|
||||||
|
BoundVar::from(self.variables.iter().position(|v| v == &c).unwrap_or_else(|| {
|
||||||
let var = self.variables.len();
|
let var = self.variables.len();
|
||||||
self.variables.push(c.into());
|
self.variables.push(c);
|
||||||
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
self.primitive_var_infos.push(CanonicalVarInfo { kind });
|
||||||
var
|
var
|
||||||
}),
|
}));
|
||||||
);
|
|
||||||
ty::Const::new_bound(self.infcx.tcx, self.binder_index, var, c.ty())
|
self.interner().mk_bound_const(self.binder_index, var, ty)
|
||||||
}
|
}
|
||||||
}
|
}
|
1
compiler/rustc_next_trait_solver/src/lib.rs
Normal file
1
compiler/rustc_next_trait_solver/src/lib.rs
Normal file
|
@ -0,0 +1 @@
|
||||||
|
pub mod canonicalizer;
|
|
@ -15,6 +15,7 @@ rustc_index = { path = "../rustc_index" }
|
||||||
rustc_infer = { path = "../rustc_infer" }
|
rustc_infer = { path = "../rustc_infer" }
|
||||||
rustc_macros = { path = "../rustc_macros" }
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
rustc_middle = { path = "../rustc_middle" }
|
rustc_middle = { path = "../rustc_middle" }
|
||||||
|
rustc_next_trait_solver = { path = "../rustc_next_trait_solver" }
|
||||||
rustc_parse_format = { path = "../rustc_parse_format" }
|
rustc_parse_format = { path = "../rustc_parse_format" }
|
||||||
rustc_query_system = { path = "../rustc_query_system" }
|
rustc_query_system = { path = "../rustc_query_system" }
|
||||||
rustc_session = { path = "../rustc_session" }
|
rustc_session = { path = "../rustc_session" }
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
//!
|
//!
|
||||||
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
|
//! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html
|
||||||
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
use super::{CanonicalInput, Certainty, EvalCtxt, Goal};
|
||||||
use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer};
|
|
||||||
use crate::solve::{
|
use crate::solve::{
|
||||||
inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
|
inspect, response_no_constraints_raw, CanonicalResponse, QueryResult, Response,
|
||||||
};
|
};
|
||||||
|
@ -27,6 +26,7 @@ use rustc_middle::traits::solve::{
|
||||||
};
|
};
|
||||||
use rustc_middle::traits::ObligationCause;
|
use rustc_middle::traits::ObligationCause;
|
||||||
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
|
use rustc_middle::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable};
|
||||||
|
use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
|
@ -30,7 +30,6 @@ use rustc_middle::ty::{
|
||||||
|
|
||||||
mod alias_relate;
|
mod alias_relate;
|
||||||
mod assembly;
|
mod assembly;
|
||||||
mod canonicalize;
|
|
||||||
mod eval_ctxt;
|
mod eval_ctxt;
|
||||||
mod fulfill;
|
mod fulfill;
|
||||||
pub mod inspect;
|
pub mod inspect;
|
||||||
|
|
|
@ -162,7 +162,7 @@ impl<I: Interner> CanonicalVarInfo<I> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo<I> {
|
pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarInfo<I> {
|
||||||
CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
|
CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,13 +324,13 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||||
///
|
///
|
||||||
/// In case this is a float or int variable, this causes an ICE if
|
/// In case this is a float or int variable, this causes an ICE if
|
||||||
/// the updated universe is not the root.
|
/// the updated universe is not the root.
|
||||||
pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind<I> {
|
pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarKind<I> {
|
||||||
match self {
|
match self {
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
|
CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => {
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
|
||||||
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
|
CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty.clone()),
|
||||||
|
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||||
CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
|
CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui))
|
||||||
|
@ -339,12 +339,15 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||||
CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
|
CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui))
|
||||||
}
|
}
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
||||||
CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty)
|
CanonicalVarKind::PlaceholderConst(
|
||||||
|
placeholder.with_updated_universe(ui),
|
||||||
|
ty.clone(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float)
|
||||||
| CanonicalVarKind::Effect => {
|
| CanonicalVarKind::Effect => {
|
||||||
assert_eq!(ui, UniverseIndex::ROOT);
|
assert_eq!(ui, UniverseIndex::ROOT);
|
||||||
self
|
self.clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,15 +146,15 @@ impl<I: Interner> DebugWithInfcx<I> for InferConst {
|
||||||
this: WithInfcx<'_, Infcx, &Self>,
|
this: WithInfcx<'_, Infcx, &Self>,
|
||||||
f: &mut core::fmt::Formatter<'_>,
|
f: &mut core::fmt::Formatter<'_>,
|
||||||
) -> core::fmt::Result {
|
) -> core::fmt::Result {
|
||||||
match this.infcx.universe_of_ct(*this.data) {
|
match *this.data {
|
||||||
None => write!(f, "{:?}", this.data),
|
InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) {
|
||||||
Some(universe) => match *this.data {
|
None => write!(f, "{:?}", this.data),
|
||||||
InferConst::Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()),
|
Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()),
|
||||||
InferConst::EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()),
|
|
||||||
InferConst::Fresh(_) => {
|
|
||||||
unreachable!()
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()),
|
||||||
|
InferConst::Fresh(_) => {
|
||||||
|
unreachable!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,37 +1,58 @@
|
||||||
use crate::{InferConst, InferTy, Interner, UniverseIndex};
|
use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex};
|
||||||
|
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
|
|
||||||
pub trait InferCtxtLike {
|
|
||||||
type Interner: Interner;
|
|
||||||
|
|
||||||
fn universe_of_ty(&self, ty: InferTy) -> Option<UniverseIndex>;
|
|
||||||
|
|
||||||
fn universe_of_lt(
|
|
||||||
&self,
|
|
||||||
lt: <Self::Interner as Interner>::InferRegion,
|
|
||||||
) -> Option<UniverseIndex>;
|
|
||||||
|
|
||||||
fn universe_of_ct(&self, ct: InferConst) -> Option<UniverseIndex>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct NoInfcx<I>(PhantomData<I>);
|
pub struct NoInfcx<I>(PhantomData<I>);
|
||||||
|
|
||||||
impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
impl<I: Interner> InferCtxtLike for NoInfcx<I> {
|
||||||
type Interner = I;
|
type Interner = I;
|
||||||
|
|
||||||
fn universe_of_ty(&self, _ty: InferTy) -> Option<UniverseIndex> {
|
fn interner(&self) -> Self::Interner {
|
||||||
None
|
unreachable!()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_ct(&self, _ct: InferConst) -> Option<UniverseIndex> {
|
fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
|
fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn universe_of_ct(&self, _ct: ConstVid) -> Option<UniverseIndex> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_ty_var(&self, vid: TyVid) -> TyVid {
|
||||||
|
vid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_ty_var(&self, _vid: TyVid) -> Option<<Self::Interner as Interner>::Ty> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_lt_var(
|
||||||
|
&self,
|
||||||
|
vid: <Self::Interner as Interner>::InferRegion,
|
||||||
|
) -> <Self::Interner as Interner>::InferRegion {
|
||||||
|
vid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_lt_var(
|
||||||
|
&self,
|
||||||
|
_vid: <Self::Interner as Interner>::InferRegion,
|
||||||
|
) -> Option<<Self::Interner as Interner>::Region> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
|
||||||
|
fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
|
||||||
|
vid
|
||||||
|
}
|
||||||
|
|
||||||
|
fn probe_ct_var(&self, _vid: ConstVid) -> Option<<Self::Interner as Interner>::Const> {
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
|
pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
|
||||||
|
|
40
compiler/rustc_type_ir/src/infcx.rs
Normal file
40
compiler/rustc_type_ir/src/infcx.rs
Normal file
|
@ -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 root `InferRegion`.
|
||||||
|
fn root_lt_var(
|
||||||
|
&self,
|
||||||
|
vid: <Self::Interner as Interner>::InferRegion,
|
||||||
|
) -> <Self::Interner as Interner>::InferRegion;
|
||||||
|
|
||||||
|
/// Resolve `InferRegion` to its inferred region, if it has been equated with a non-infer region.
|
||||||
|
fn probe_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>;
|
||||||
|
}
|
|
@ -2,8 +2,12 @@ use smallvec::SmallVec;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
use std::hash::Hash;
|
use std::hash::Hash;
|
||||||
|
|
||||||
use crate::{BoundVar, DebugWithInfcx, Mutability, UniverseIndex};
|
use crate::{
|
||||||
|
BoundVar, CanonicalVarInfo, ConstKind, DebruijnIndex, DebugWithInfcx, Mutability, RegionKind,
|
||||||
|
TyKind, UniverseIndex,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[allow(rustc::usage_of_ty_tykind)]
|
||||||
pub trait Interner: Sized {
|
pub trait Interner: Sized {
|
||||||
type DefId: Clone + Debug + Hash + Ord;
|
type DefId: Clone + Debug + Hash + Ord;
|
||||||
type AdtDef: Clone + Debug + Hash + Ord;
|
type AdtDef: Clone + Debug + Hash + Ord;
|
||||||
|
@ -18,10 +22,15 @@ pub trait Interner: Sized {
|
||||||
|
|
||||||
type Binder<T>;
|
type Binder<T>;
|
||||||
type TypeAndMut: Clone + Debug + Hash + Ord;
|
type TypeAndMut: Clone + Debug + Hash + Ord;
|
||||||
type CanonicalVars: Clone + Debug + Hash + Eq;
|
type CanonicalVars: Clone + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
|
||||||
|
|
||||||
// Kinds of tys
|
// Kinds of tys
|
||||||
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type Ty: Clone
|
||||||
|
+ DebugWithInfcx<Self>
|
||||||
|
+ Hash
|
||||||
|
+ Ord
|
||||||
|
+ Into<Self::GenericArg>
|
||||||
|
+ IntoKind<Kind = TyKind<Self>>;
|
||||||
type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
|
||||||
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type ParamTy: Clone + Debug + Hash + Ord;
|
type ParamTy: Clone + Debug + Hash + Ord;
|
||||||
|
@ -35,7 +44,13 @@ pub trait Interner: Sized {
|
||||||
type AllocId: Clone + Debug + Hash + Ord;
|
type AllocId: Clone + Debug + Hash + Ord;
|
||||||
|
|
||||||
// Kinds of consts
|
// Kinds of consts
|
||||||
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type Const: Clone
|
||||||
|
+ DebugWithInfcx<Self>
|
||||||
|
+ Hash
|
||||||
|
+ Ord
|
||||||
|
+ Into<Self::GenericArg>
|
||||||
|
+ IntoKind<Kind = ConstKind<Self>>
|
||||||
|
+ ConstTy<Self>;
|
||||||
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder;
|
type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder;
|
||||||
type ParamConst: Clone + Debug + Hash + Ord;
|
type ParamConst: Clone + Debug + Hash + Ord;
|
||||||
|
@ -44,10 +59,15 @@ pub trait Interner: Sized {
|
||||||
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
|
|
||||||
// Kinds of regions
|
// Kinds of regions
|
||||||
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type Region: Clone
|
||||||
|
+ DebugWithInfcx<Self>
|
||||||
|
+ Hash
|
||||||
|
+ Ord
|
||||||
|
+ Into<Self::GenericArg>
|
||||||
|
+ IntoKind<Kind = RegionKind<Self>>;
|
||||||
type EarlyParamRegion: Clone + Debug + Hash + Ord;
|
type EarlyParamRegion: Clone + Debug + Hash + Ord;
|
||||||
type BoundRegion: Clone + Debug + Hash + Ord;
|
|
||||||
type LateParamRegion: Clone + Debug + Hash + Ord;
|
type LateParamRegion: Clone + Debug + Hash + Ord;
|
||||||
|
type BoundRegion: Clone + Debug + Hash + Ord;
|
||||||
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord;
|
||||||
type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder;
|
type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder;
|
||||||
|
|
||||||
|
@ -63,6 +83,12 @@ pub trait Interner: Sized {
|
||||||
type ClosureKind: Clone + Debug + Hash + Eq;
|
type ClosureKind: Clone + Debug + Hash + Eq;
|
||||||
|
|
||||||
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
|
fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability);
|
||||||
|
|
||||||
|
fn mk_canonical_var_infos(&self, infos: &[CanonicalVarInfo<Self>]) -> Self::CanonicalVars;
|
||||||
|
|
||||||
|
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
|
/// Common capabilities of placeholder kinds
|
||||||
|
@ -70,7 +96,19 @@ pub trait Placeholder {
|
||||||
fn universe(&self) -> UniverseIndex;
|
fn universe(&self) -> UniverseIndex;
|
||||||
fn var(&self) -> BoundVar;
|
fn var(&self) -> BoundVar;
|
||||||
|
|
||||||
fn with_updated_universe(self, ui: UniverseIndex) -> Self;
|
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`
|
/// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter`
|
||||||
|
|
|
@ -35,6 +35,7 @@ mod canonical;
|
||||||
mod const_kind;
|
mod const_kind;
|
||||||
mod debug;
|
mod debug;
|
||||||
mod flags;
|
mod flags;
|
||||||
|
mod infcx;
|
||||||
mod interner;
|
mod interner;
|
||||||
mod predicate_kind;
|
mod predicate_kind;
|
||||||
mod region_kind;
|
mod region_kind;
|
||||||
|
@ -43,8 +44,9 @@ pub use canonical::*;
|
||||||
#[cfg(feature = "nightly")]
|
#[cfg(feature = "nightly")]
|
||||||
pub use codec::*;
|
pub use codec::*;
|
||||||
pub use const_kind::*;
|
pub use const_kind::*;
|
||||||
pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx};
|
pub use debug::{DebugWithInfcx, WithInfcx};
|
||||||
pub use flags::*;
|
pub use flags::*;
|
||||||
|
pub use infcx::InferCtxtLike;
|
||||||
pub use interner::*;
|
pub use interner::*;
|
||||||
pub use predicate_kind::*;
|
pub use predicate_kind::*;
|
||||||
pub use region_kind::*;
|
pub use region_kind::*;
|
||||||
|
@ -337,6 +339,12 @@ impl UniverseIndex {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Default for UniverseIndex {
|
||||||
|
fn default() -> Self {
|
||||||
|
Self::ROOT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rustc_index::newtype_index! {
|
rustc_index::newtype_index! {
|
||||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
|
||||||
#[encodable]
|
#[encodable]
|
||||||
|
|
|
@ -820,15 +820,15 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
|
||||||
this: WithInfcx<'_, Infcx, &Self>,
|
this: WithInfcx<'_, Infcx, &Self>,
|
||||||
f: &mut fmt::Formatter<'_>,
|
f: &mut fmt::Formatter<'_>,
|
||||||
) -> fmt::Result {
|
) -> fmt::Result {
|
||||||
use InferTy::*;
|
match this.data {
|
||||||
match this.infcx.universe_of_ty(*this.data) {
|
InferTy::TyVar(vid) => {
|
||||||
None => write!(f, "{:?}", this.data),
|
if let Some(universe) = this.infcx.universe_of_ty(*vid) {
|
||||||
Some(universe) => match *this.data {
|
write!(f, "?{}_{}t", vid.index(), universe.index())
|
||||||
TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
|
} else {
|
||||||
IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
|
write!(f, "{:?}", this.data)
|
||||||
unreachable!()
|
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
|
_ => write!(f, "{:?}", this.data),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue