Rollup merge of #117586 - compiler-errors:the-canonicalizer, r=lcnr

Uplift the (new solver) canonicalizer into `rustc_next_trait_solver`

Uplifts the new trait solver's canonicalizer into a new crate called `rustc_next_trait_solver`.

The crate name is literally a bikeshed-avoidance name, so let's not block this PR on that -- renames are welcome later.

There are a host of other changes that were required to make this possible:
* Expose a `ConstTy` trait to get the `Interner::Ty` from a `Interner::Const`.
* Expose some constructor methods to construct `Bound` variants. These are currently methods defined on the interner themselves, but they could be pulled into traits later.
* Expose a `IntoKind` trait to turn a `Ty`/`Const`/`Region` into their corresponding `*Kind`s.
* Some minor tweaks to other APIs in `rustc_type_ir`.

The canonicalizer code itself is best reviewed **with whitespace ignored.**

r? ``@lcnr``
This commit is contained in:
Matthias Krüger 2023-12-08 23:15:11 +01:00 committed by GitHub
commit 4df6134f1a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 478 additions and 262 deletions

View File

@ -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",

View File

@ -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
} }

View File

@ -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,

View File

@ -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> {

View File

@ -131,6 +131,31 @@ 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: &[ty::CanonicalVarInfo<Self>]) -> Self::CanonicalVars {
self.mk_canonical_var_infos(infos)
}
fn mk_bound_ty(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Ty {
Ty::new_bound(self, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
}
fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region {
Region::new_bound(
self,
debruijn,
ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon },
)
}
fn mk_bound_const(
self,
debruijn: ty::DebruijnIndex,
var: ty::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>, ()>;

View File

@ -65,15 +65,10 @@ use std::ops::ControlFlow;
use std::{fmt, str}; use std::{fmt, str};
pub use crate::ty::diagnostics::*; pub use crate::ty::diagnostics::*;
pub use rustc_type_ir::AliasKind::*;
pub use rustc_type_ir::ConstKind::{ pub use rustc_type_ir::ConstKind::{
Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt,
Placeholder as PlaceholderCt, Unevaluated, Value, Placeholder as PlaceholderCt, Unevaluated, Value,
}; };
pub use rustc_type_ir::DynKind::*;
pub use rustc_type_ir::InferTy::*;
pub use rustc_type_ir::RegionKind::*;
pub use rustc_type_ir::TyKind::*;
pub use rustc_type_ir::*; pub use rustc_type_ir::*;
pub use self::binding::BindingMode; pub use self::binding::BindingMode;
@ -474,6 +469,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 (`'_`).
@ -1545,34 +1548,42 @@ pub struct Placeholder<T> {
pub type PlaceholderRegion = Placeholder<BoundRegion>; pub type PlaceholderRegion = Placeholder<BoundRegion>;
impl rustc_type_ir::Placeholder for PlaceholderRegion { impl PlaceholderLike for PlaceholderRegion {
fn universe(&self) -> UniverseIndex { fn universe(self) -> UniverseIndex {
self.universe self.universe
} }
fn var(&self) -> BoundVar { fn var(self) -> BoundVar {
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 } }
}
} }
pub type PlaceholderType = Placeholder<BoundTy>; pub type PlaceholderType = Placeholder<BoundTy>;
impl rustc_type_ir::Placeholder for PlaceholderType { impl PlaceholderLike for PlaceholderType {
fn universe(&self) -> UniverseIndex { fn universe(self) -> UniverseIndex {
self.universe self.universe
} }
fn var(&self) -> BoundVar { fn var(self) -> BoundVar {
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 } }
}
} }
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
@ -1584,18 +1595,22 @@ pub struct BoundConst<'tcx> {
pub type PlaceholderConst = Placeholder<BoundVar>; pub type PlaceholderConst = Placeholder<BoundVar>;
impl rustc_type_ir::Placeholder for PlaceholderConst { impl PlaceholderLike for PlaceholderConst {
fn universe(&self) -> UniverseIndex { fn universe(self) -> UniverseIndex {
self.universe self.universe
} }
fn var(&self) -> BoundVar { fn var(self) -> BoundVar {
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 }
}
} }
/// When type checking, we use the `ParamEnv` to track /// When type checking, we use the `ParamEnv` to track

View File

@ -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(

View File

@ -0,0 +1,13 @@
[package]
name = "rustc_next_trait_solver"
version = "0.0.0"
edition = "2021"
[dependencies]
rustc_type_ir = { path = "../rustc_type_ir", default-features = false }
[features]
default = ["nightly"]
nightly = [
"rustc_type_ir/nightly",
]

View File

@ -1,17 +1,10 @@
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; self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy,
use rustc_middle::infer::canonical::CanonicalVarInfo; InferCtxtLike, Interner, IntoKind, PlaceholderLike,
use rustc_middle::infer::canonical::CanonicalVarInfos; };
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.
/// ///
@ -42,23 +35,22 @@ pub enum CanonicalizeMode {
}, },
} }
pub struct Canonicalizer<'a, 'tcx> { pub struct Canonicalizer<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> {
infcx: &'a InferCtxt<'tcx>, infcx: &'a Infcx,
canonicalize_mode: CanonicalizeMode, canonicalize_mode: CanonicalizeMode,
variables: &'a mut Vec<ty::GenericArg<'tcx>>, variables: &'a mut Vec<I::GenericArg>,
primitive_var_infos: Vec<CanonicalVarInfo<'tcx>>, primitive_var_infos: Vec<CanonicalVarInfo<I>>,
binder_index: ty::DebruijnIndex, binder_index: ty::DebruijnIndex,
} }
impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { impl<'a, Infcx: InferCtxtLike<Interner = I>, I: Interner> Canonicalizer<'a, Infcx, I> {
#[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::GenericArg>,
value: T, value: T,
) -> Canonical<'tcx, T> { ) -> ty::Canonical<I, T> {
let mut canonicalizer = Canonicalizer { let mut canonicalizer = Canonicalizer {
infcx, infcx,
canonicalize_mode, canonicalize_mode,
@ -69,15 +61,16 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
}; };
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) -> (ty::UniverseIndex, I::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.
@ -105,7 +98,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
.max() .max()
.unwrap_or(ty::UniverseIndex::ROOT); .unwrap_or(ty::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);
} }
} }
@ -131,7 +124,7 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
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(ty::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
@ -187,19 +180,22 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> {
} }
} }
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>
fn interner(&self) -> TyCtxt<'tcx> { for Canonicalizer<'_, Infcx, I>
self.infcx.tcx {
fn interner(&self) -> I {
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,21 +203,8 @@ 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
.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, 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
@ -237,9 +220,11 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
CanonicalizeMode::Response { .. } => return r, CanonicalizeMode::Response { .. } => return r,
}, },
ty::ReLateParam(_) | ty::ReEarlyParam(_) => match self.canonicalize_mode { ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"), CanonicalizeMode::Response { .. } => {
panic!("unexpected region in response: {r:?}")
}
}, },
ty::RePlaceholder(placeholder) => match self.canonicalize_mode { ty::RePlaceholder(placeholder) => match self.canonicalize_mode {
@ -248,20 +233,32 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
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 { ty::ReVar(vid) => {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), assert_eq!(
CanonicalizeMode::Response { .. } => { self.infcx.root_lt_var(vid),
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),
None,
"region vid should have been resolved fully before canonicalization"
);
match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT),
CanonicalizeMode::Response { .. } => {
CanonicalVarKind::Region(self.infcx.universe_of_lt(vid).unwrap())
}
}
}
ty::ReError(_) => return r, ty::ReError(_) => return r,
}; };
@ -271,55 +268,60 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from) self.variables.iter().position(|&v| v == r.into()).map(ty::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 = ty::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}"); ty::Infer(i) => match i {
}; ty::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
.universe_of_ty(vid)
.unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")),
))
}
ty::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int),
ty::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float),
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {
todo!()
}
},
ty::Placeholder(placeholder) => match self.canonicalize_mode { ty::Placeholder(placeholder) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new(
universe: placeholder.universe, placeholder.universe(),
bound: ty::BoundTy { self.variables.len().into(),
var: ty::BoundVar::from_usize(self.variables.len()), )),
kind: ty::BoundTyKind::Anon,
},
}),
CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder),
}, },
ty::Param(_) => match self.canonicalize_mode { ty::Param(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new(
universe: ty::UniverseIndex::ROOT, ty::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 ty::Bool
| ty::Char | ty::Char
@ -354,44 +356,38 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
var var
}), }),
); );
let bt = ty::BoundTy { var, kind: BoundTyKind::Anon };
Ty::new_bound(self.infcx.tcx, self.binder_index, bt) self.interner().mk_bound_ty(self.binder_index, var)
} }
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)) => { ty::ConstKind::Infer(i) => {
assert_eq!( // FIXME: we should fold the ty too eventually
self.infcx.root_const_var(vid), match i {
vid, ty::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,
ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { "region vid should have been resolved fully before canonicalization"
assert_eq!( );
self.infcx.root_effect_var(vid), CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty())
vid, }
"effect var should have been resolved" ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect,
); ty::InferConst::Fresh(_) => todo!(),
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 { ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
ty::Placeholder { PlaceholderLike::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 { .. } => {
@ -400,13 +396,10 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
}, },
ty::ConstKind::Param(_) => match self.canonicalize_mode { ty::ConstKind::Param(_) => match self.canonicalize_mode {
CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst(
ty::Placeholder { PlaceholderLike::new(ty::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(_, _) ty::ConstKind::Bound(_, _)
| ty::ConstKind::Unevaluated(_) | ty::ConstKind::Unevaluated(_)
@ -423,6 +416,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'_, 'tcx> {
var var
}), }),
); );
ty::Const::new_bound(self.infcx.tcx, self.binder_index, var, c.ty())
self.interner().mk_bound_const(self.binder_index, var, c.ty())
} }
} }

View File

@ -0,0 +1 @@
pub mod canonicalizer;

View File

@ -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" }

View File

@ -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;

View File

@ -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;

View File

@ -4,7 +4,7 @@ use std::ops::ControlFlow;
use crate::fold::{FallibleTypeFolder, TypeFoldable}; use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor}; use crate::visit::{TypeVisitable, TypeVisitor};
use crate::{Interner, Placeholder, UniverseIndex}; use crate::{Interner, PlaceholderLike, UniverseIndex};
/// A "canonicalized" type `V` is one where all free inference /// A "canonicalized" type `V` is one where all free inference
/// variables have been rewritten to "canonical vars". These are /// variables have been rewritten to "canonical vars". These are
@ -157,7 +157,7 @@ where
} }
impl<I: Interner> CanonicalVarInfo<I> { impl<I: Interner> CanonicalVarInfo<I> {
pub fn universe(&self) -> UniverseIndex { pub fn universe(self) -> UniverseIndex {
self.kind.universe() self.kind.universe()
} }
@ -305,11 +305,11 @@ where
} }
impl<I: Interner> CanonicalVarKind<I> { impl<I: Interner> CanonicalVarKind<I> {
pub fn universe(&self) -> UniverseIndex { pub fn universe(self) -> UniverseIndex {
match self { match self {
CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => *ui, CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui,
CanonicalVarKind::Region(ui) => *ui, CanonicalVarKind::Region(ui) => ui,
CanonicalVarKind::Const(ui, _) => *ui, CanonicalVarKind::Const(ui, _) => ui,
CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(),
CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(),
CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(), CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(),

View File

@ -81,7 +81,7 @@ impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
match this.data { match this.data {
Param(param) => write!(f, "{param:?}"), Param(param) => write!(f, "{param:?}"),
Infer(var) => write!(f, "{:?}", &this.wrap(var)), Infer(var) => write!(f, "{:?}", &this.wrap(var)),
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()), Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
Placeholder(placeholder) => write!(f, "{placeholder:?}"), Placeholder(placeholder) => write!(f, "{placeholder:?}"),
Unevaluated(uv) => { Unevaluated(uv) => {
write!(f, "{:?}", &this.wrap(uv)) write!(f, "{:?}", &this.wrap(uv))
@ -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!()
}
} }
} }
} }

View File

@ -1,35 +1,50 @@
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 {
unreachable!()
}
fn universe_of_ty(&self, _ty: TyVid) -> Option<UniverseIndex> {
None None
} }
fn universe_of_ct(&self, _ct: InferConst) -> Option<UniverseIndex> { fn universe_of_lt(&self, _lt: I::InferRegion) -> Option<UniverseIndex> {
None None
} }
fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> { 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<I::Ty> {
None
}
fn root_lt_var(&self, vid: I::InferRegion) -> I::InferRegion {
vid
}
fn probe_lt_var(&self, _vid: I::InferRegion) -> Option<I::Region> {
None
}
fn root_ct_var(&self, vid: ConstVid) -> ConstVid {
vid
}
fn probe_ct_var(&self, _vid: ConstVid) -> Option<I::Const> {
None None
} }
} }

View 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>;
}

View File

@ -2,75 +2,113 @@ 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,
};
pub trait Interner: Sized { pub trait Interner: Sized {
type DefId: Clone + Debug + Hash + Ord; type DefId: Copy + Debug + Hash + Ord;
type AdtDef: Clone + Debug + Hash + Ord; type AdtDef: Copy + Debug + Hash + Ord;
type GenericArgs: Clone type GenericArgs: Copy
+ DebugWithInfcx<Self> + DebugWithInfcx<Self>
+ Hash + Hash
+ Ord + Ord
+ IntoIterator<Item = Self::GenericArg>; + IntoIterator<Item = Self::GenericArg>;
type GenericArg: Clone + DebugWithInfcx<Self> + Hash + Ord; type GenericArg: Copy + DebugWithInfcx<Self> + Hash + Ord;
type Term: Clone + Debug + Hash + Ord; type Term: Copy + Debug + Hash + Ord;
type Binder<T>; type Binder<T>;
type TypeAndMut: Clone + Debug + Hash + Ord; type TypeAndMut: Copy + Debug + Hash + Ord;
type CanonicalVars: Clone + Debug + Hash + Eq; type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator<Item = CanonicalVarInfo<Self>>;
// Kinds of tys // Kinds of tys
type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord; type Ty: Copy
type Tys: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>; + DebugWithInfcx<Self>
type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord; + Hash
type ParamTy: Clone + Debug + Hash + Ord; + Ord
type BoundTy: Clone + Debug + Hash + Ord; + Into<Self::GenericArg>
type PlaceholderTy: Clone + Debug + Hash + Ord + Placeholder; + IntoKind<Kind = TyKind<Self>>;
type Tys: Copy + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
type AliasTy: Copy + DebugWithInfcx<Self> + Hash + Ord;
type ParamTy: Copy + Debug + Hash + Ord;
type BoundTy: Copy + Debug + Hash + Ord;
type PlaceholderTy: Copy + Debug + Hash + Ord + PlaceholderLike;
// Things stored inside of tys // Things stored inside of tys
type ErrorGuaranteed: Clone + Debug + Hash + Ord; type ErrorGuaranteed: Copy + Debug + Hash + Ord;
type BoundExistentialPredicates: Clone + DebugWithInfcx<Self> + Hash + Ord; type BoundExistentialPredicates: Copy + DebugWithInfcx<Self> + Hash + Ord;
type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord; type PolyFnSig: Copy + DebugWithInfcx<Self> + Hash + Ord;
type AllocId: Clone + Debug + Hash + Ord; type AllocId: Copy + Debug + Hash + Ord;
// Kinds of consts // Kinds of consts
type Const: Clone + DebugWithInfcx<Self> + Hash + Ord; type Const: Copy
type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord; + DebugWithInfcx<Self>
type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder; + Hash
type ParamConst: Clone + Debug + Hash + Ord; + Ord
type BoundConst: Clone + Debug + Hash + Ord; + Into<Self::GenericArg>
type ValueConst: Clone + Debug + Hash + Ord; + IntoKind<Kind = ConstKind<Self>>
type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord; + ConstTy<Self>;
type AliasConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
type PlaceholderConst: Copy + Debug + Hash + Ord + PlaceholderLike;
type ParamConst: Copy + Debug + Hash + Ord;
type BoundConst: Copy + Debug + Hash + Ord;
type ValueConst: Copy + Debug + Hash + Ord;
type ExprConst: Copy + DebugWithInfcx<Self> + Hash + Ord;
// Kinds of regions // Kinds of regions
type Region: Clone + DebugWithInfcx<Self> + Hash + Ord; type Region: Copy
type EarlyParamRegion: Clone + Debug + Hash + Ord; + DebugWithInfcx<Self>
type BoundRegion: Clone + Debug + Hash + Ord; + Hash
type LateParamRegion: Clone + Debug + Hash + Ord; + Ord
type InferRegion: Clone + DebugWithInfcx<Self> + Hash + Ord; + Into<Self::GenericArg>
type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder; + IntoKind<Kind = RegionKind<Self>>;
type EarlyParamRegion: Copy + Debug + Hash + Ord;
type LateParamRegion: Copy + Debug + Hash + Ord;
type BoundRegion: Copy + Debug + Hash + Ord;
type InferRegion: Copy + DebugWithInfcx<Self> + Hash + Ord;
type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike;
// Predicates // Predicates
type Predicate: Clone + Debug + Hash + Eq; type Predicate: Copy + Debug + Hash + Eq;
type TraitPredicate: Clone + Debug + Hash + Eq; type TraitPredicate: Copy + Debug + Hash + Eq;
type RegionOutlivesPredicate: Clone + Debug + Hash + Eq; type RegionOutlivesPredicate: Copy + Debug + Hash + Eq;
type TypeOutlivesPredicate: Clone + Debug + Hash + Eq; type TypeOutlivesPredicate: Copy + Debug + Hash + Eq;
type ProjectionPredicate: Clone + Debug + Hash + Eq; type ProjectionPredicate: Copy + Debug + Hash + Eq;
type NormalizesTo: Clone + Debug + Hash + Eq; type NormalizesTo: Copy + Debug + Hash + Eq;
type SubtypePredicate: Clone + Debug + Hash + Eq; type SubtypePredicate: Copy + Debug + Hash + Eq;
type CoercePredicate: Clone + Debug + Hash + Eq; type CoercePredicate: Copy + Debug + Hash + Eq;
type ClosureKind: Clone + Debug + Hash + Eq; type ClosureKind: Copy + 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;
// FIXME: We should not have all these constructors on `Interner`, but as functions on some trait.
fn mk_bound_ty(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Ty;
fn mk_bound_region(self, debruijn: DebruijnIndex, var: BoundVar) -> Self::Region;
fn mk_bound_const(self, debruijn: DebruijnIndex, var: BoundVar, ty: Self::Ty) -> Self::Const;
} }
/// Common capabilities of placeholder kinds /// Common capabilities of placeholder kinds
pub trait Placeholder { pub trait PlaceholderLike {
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`

View File

@ -4,6 +4,7 @@
)] )]
#![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)] #![deny(rustc::diagnostic_outside_of_impl)]
#![allow(rustc::usage_of_ty_tykind)]
#![cfg_attr(feature = "nightly", allow(internal_features))] #![cfg_attr(feature = "nightly", allow(internal_features))]
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
@ -35,6 +36,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,13 +45,19 @@ 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::*;
pub use ty_info::*; pub use ty_info::*;
pub use ty_kind::*; pub use ty_kind::*;
pub use AliasKind::*;
pub use DynKind::*;
pub use InferTy::*;
pub use RegionKind::*;
pub use TyKind::*;
rustc_index::newtype_index! { rustc_index::newtype_index! {
/// A [De Bruijn index][dbi] is a standard means of representing /// A [De Bruijn index][dbi] is a standard means of representing
@ -337,6 +345,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]

View File

@ -1,5 +1,3 @@
#![allow(rustc::usage_of_ty_tykind)]
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
@ -394,7 +392,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
Float(float) => write!(f, "{float:?}"), Float(float) => write!(f, "{float:?}"),
Adt(d, s) => { Adt(d, s) => {
write!(f, "{d:?}")?; write!(f, "{d:?}")?;
let mut s = s.clone().into_iter(); let mut s = s.into_iter();
let first = s.next(); let first = s.next();
match first { match first {
Some(first) => write!(f, "<{:?}", first)?, Some(first) => write!(f, "<{:?}", first)?,
@ -412,7 +410,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
RawPtr(p) => { RawPtr(p) => {
let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone()); let (ty, mutbl) = I::ty_and_mut_to_parts(*p);
match mutbl { match mutbl {
Mutability::Mut => write!(f, "*mut "), Mutability::Mut => write!(f, "*mut "),
Mutability::Not => write!(f, "*const "), Mutability::Not => write!(f, "*const "),
@ -442,7 +440,7 @@ impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
Tuple(t) => { Tuple(t) => {
write!(f, "(")?; write!(f, "(")?;
let mut count = 0; let mut count = 0;
for ty in t.clone() { for ty in *t {
if count > 0 { if count > 0 {
write!(f, ", ")?; write!(f, ", ")?;
} }
@ -820,15 +818,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),
} }
} }
} }