From cb41509601fc4059dd0c712034efa577a7ef46e3 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Wed, 22 Nov 2023 23:44:58 +0000 Subject: [PATCH 1/3] Uplift canonicalizer into new trait solver crate --- Cargo.lock | 8 + compiler/rustc_infer/src/infer/mod.rs | 72 +++- .../src/infer/region_constraints/mod.rs | 5 + compiler/rustc_middle/src/ty/consts.rs | 16 +- compiler/rustc_middle/src/ty/context.rs | 36 ++ compiler/rustc_middle/src/ty/mod.rs | 32 +- compiler/rustc_middle/src/ty/sty.rs | 10 +- compiler/rustc_next_trait_solver/Cargo.toml | 7 + .../src/canonicalizer.rs} | 387 +++++++++--------- compiler/rustc_next_trait_solver/src/lib.rs | 1 + compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/solve/eval_ctxt/canonical.rs | 2 +- .../rustc_trait_selection/src/solve/mod.rs | 1 - compiler/rustc_type_ir/src/canonical.rs | 13 +- compiler/rustc_type_ir/src/const_kind.rs | 16 +- compiler/rustc_type_ir/src/debug.rs | 53 ++- compiler/rustc_type_ir/src/infcx.rs | 40 ++ compiler/rustc_type_ir/src/interner.rs | 52 ++- compiler/rustc_type_ir/src/lib.rs | 10 +- compiler/rustc_type_ir/src/ty_kind.rs | 16 +- 20 files changed, 506 insertions(+), 272 deletions(-) create mode 100644 compiler/rustc_next_trait_solver/Cargo.toml rename compiler/{rustc_trait_selection/src/solve/canonicalize.rs => rustc_next_trait_solver/src/canonicalizer.rs} (52%) create mode 100644 compiler/rustc_next_trait_solver/src/lib.rs create mode 100644 compiler/rustc_type_ir/src/infcx.rs diff --git a/Cargo.lock b/Cargo.lock index 1d7f93c789afe..03a075b345ca1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4303,6 +4303,13 @@ dependencies = [ "tracing", ] +[[package]] +name = "rustc_next_trait_solver" +version = "0.0.0" +dependencies = [ + "rustc_type_ir", +] + [[package]] name = "rustc_parse" version = "0.0.0" @@ -4571,6 +4578,7 @@ dependencies = [ "rustc_infer", "rustc_macros", "rustc_middle", + "rustc_next_trait_solver", "rustc_parse_format", "rustc_query_system", "rustc_session", diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 32c09e491c7ed..3a71251e73da4 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -345,37 +345,61 @@ pub struct InferCtxt<'tcx> { impl<'tcx> ty::InferCtxtLike for InferCtxt<'tcx> { type Interner = TyCtxt<'tcx>; - fn universe_of_ty(&self, ty: ty::InferTy) -> Option { - use InferTy::*; - 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 - // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then - // try to print out `?0.1` it will just print `?0`. - TyVar(ty_vid) => match self.probe_ty_var(ty_vid) { - Err(universe) => Some(universe), - Ok(_) => None, - }, - IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None, + fn interner(&self) -> TyCtxt<'tcx> { + self.tcx + } + + fn universe_of_ty(&self, vid: TyVid) -> Option { + // 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 + // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then + // try to print out `?0.1` it will just print `?0`. + match self.probe_ty_var(vid) { + Err(universe) => Some(universe), + Ok(_) => None, } } - fn universe_of_ct(&self, ct: ty::InferConst) -> Option { - use ty::InferConst::*; - match ct { - // Same issue as with `universe_of_ty` - Var(ct_vid) => match self.probe_const_var(ct_vid) { - Err(universe) => Some(universe), - Ok(_) => None, - }, - EffectVar(_) => None, - Fresh(_) => None, + fn universe_of_ct(&self, ct: ConstVid) -> Option { + // Same issue as with `universe_of_ty` + match self.probe_const_var(ct) { + Err(universe) => Some(universe), + Ok(_) => None, } } fn universe_of_lt(&self, lt: ty::RegionVid) -> Option { 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> { + 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> { + 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> { + self.probe_const_var(vid).ok() + } } /// 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) } + 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 { self.inner.borrow_mut().const_unification_table().find(var).vid } diff --git a/compiler/rustc_infer/src/infer/region_constraints/mod.rs b/compiler/rustc_infer/src/infer/region_constraints/mod.rs index cbd8040c9f10f..5c043b1d3dd64 100644 --- a/compiler/rustc_infer/src/infer/region_constraints/mod.rs +++ b/compiler/rustc_infer/src/infer/region_constraints/mod.rs @@ -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> { match t { Glb => &mut self.glbs, diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index e48840fac2059..78cc2f91796db 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -7,7 +7,7 @@ use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::LocalDefId; use rustc_macros::HashStable; -use rustc_type_ir::{TypeFlags, WithCachedTypeInfo}; +use rustc_type_ir::{ConstTy, IntoKind, TypeFlags, WithCachedTypeInfo}; mod int; mod kind; @@ -26,6 +26,20 @@ use super::sty::ConstKind; #[rustc_pass_by_value] pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); +impl<'tcx> IntoKind for Const<'tcx> { + type Kind = ConstKind<'tcx>; + + fn kind(&self) -> ConstKind<'tcx> { + (*self).kind().clone() + } +} + +impl<'tcx> ConstTy> for Const<'tcx> { + fn ty(&self) -> Ty<'tcx> { + (*self).ty() + } +} + /// Typed constant value. #[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)] pub struct ConstData<'tcx> { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 3012434ad3fb8..a39acc9859fcb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -131,6 +131,42 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ) -> (Self::Ty, ty::Mutability) { (ty, mutbl) } + + fn mk_canonical_var_infos( + &self, + infos: &[rustc_type_ir::CanonicalVarInfo], + ) -> 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, ()>; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 203c9eb65df86..6aaa363eb01d2 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -474,6 +474,14 @@ pub struct CReaderCacheKey { #[rustc_pass_by_value] pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); +impl<'tcx> IntoKind for Ty<'tcx> { + type Kind = TyKind<'tcx>; + + fn kind(&self) -> TyKind<'tcx> { + (*self).kind().clone() + } +} + impl EarlyParamRegion { /// Does this early bound region have a name? Early bound regions normally /// always have names except when using anonymous lifetimes (`'_`). @@ -1554,8 +1562,12 @@ impl rustc_type_ir::Placeholder for PlaceholderRegion { self.bound.var } - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..self } + fn with_updated_universe(&self, ui: UniverseIndex) -> 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 } - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..self } + fn with_updated_universe(&self, ui: UniverseIndex) -> 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 } - fn with_updated_universe(self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..self } + fn with_updated_universe(&self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..*self } + } + + fn new(ui: UniverseIndex, var: BoundVar) -> Self { + Placeholder { universe: ui, bound: var } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index e221b4e8bec01..ed2f8f0a6abb4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -6,7 +6,7 @@ use crate::infer::canonical::Canonical; use crate::ty::visit::ValidateBoundVars; use crate::ty::InferTy::*; use crate::ty::{ - self, AdtDef, Discr, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, + self, AdtDef, Discr, IntoKind, Term, Ty, TyCtxt, TypeFlags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use crate::ty::{GenericArg, GenericArgs, GenericArgsRef}; @@ -1477,6 +1477,14 @@ impl ParamConst { #[rustc_pass_by_value] 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> { #[inline] pub fn new_early_param( diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml new file mode 100644 index 0000000000000..88c4b62c54cd5 --- /dev/null +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "rustc_next_trait_solver" +version = "0.0.0" +edition = "2021" + +[dependencies] +rustc_type_ir = { path = "../rustc_type_ir" } diff --git a/compiler/rustc_trait_selection/src/solve/canonicalize.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs similarity index 52% rename from compiler/rustc_trait_selection/src/solve/canonicalize.rs rename to compiler/rustc_next_trait_solver/src/canonicalizer.rs index 469d1f5a9cbf6..c2e6e82f2afb8 100644 --- a/compiler/rustc_trait_selection/src/solve/canonicalize.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -1,17 +1,11 @@ use std::cmp::Ordering; -use crate::infer::InferCtxt; -use rustc_middle::infer::canonical::Canonical; -use rustc_middle::infer::canonical::CanonicalTyVarKind; -use rustc_middle::infer::canonical::CanonicalVarInfo; -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}; +use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; +use rustc_type_ir::{ + BoundVar, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstKind, + ConstTy, DebruijnIndex, InferConst, InferCtxtLike, InferTy, Interner, IntoKind, Placeholder, + RegionKind, TyKind, UniverseIndex, INNERMOST, +}; /// 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 /// we do remember their universe in the response. - max_input_universe: ty::UniverseIndex, + max_input_universe: UniverseIndex, }, } -pub struct Canonicalizer<'a, 'tcx> { - infcx: &'a InferCtxt<'tcx>, +pub struct Canonicalizer<'a, Infcx: InferCtxtLike> { + infcx: &'a Infcx, canonicalize_mode: CanonicalizeMode, - variables: &'a mut Vec>, - primitive_var_infos: Vec>, - binder_index: ty::DebruijnIndex, + variables: &'a mut Vec<::GenericArg>, + primitive_var_infos: Vec>, + binder_index: DebruijnIndex, } -impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { - #[instrument(level = "debug", skip(infcx), ret)] - pub fn canonicalize>>( - infcx: &'a InferCtxt<'tcx>, +impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infcx> { + pub fn canonicalize>( + infcx: &'a Infcx, canonicalize_mode: CanonicalizeMode, - variables: &'a mut Vec>, + variables: &'a mut Vec<::GenericArg>, value: T, - ) -> Canonical<'tcx, T> { + ) -> Canonical { let mut canonicalizer = Canonicalizer { infcx, canonicalize_mode, variables, primitive_var_infos: Vec::new(), - binder_index: ty::INNERMOST, + binder_index: INNERMOST, }; let value = value.fold_with(&mut canonicalizer); - assert!(!value.has_infer(), "unexpected infer in {value:?}"); - assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); + // FIXME: Restore these assertions. Should we uplift type flags? + // assert!(!value.has_infer(), "unexpected infer in {value:?}"); + // assert!(!value.has_placeholders(), "unexpected placeholders in {value:?}"); let (max_universe, variables) = canonicalizer.finalize(); Canonical { max_universe, variables, value } } - fn finalize(self) -> (ty::UniverseIndex, CanonicalVarInfos<'tcx>) { + fn finalize(self) -> (UniverseIndex, ::CanonicalVars) { let mut var_infos = self.primitive_var_infos; // See the rustc-dev-guide section about how we deal with universes // during canonicalization in the new solver. @@ -94,18 +88,17 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { CanonicalizeMode::Response { max_input_universe } => { for var in var_infos.iter_mut() { let uv = var.universe(); - let new_uv = ty::UniverseIndex::from( - uv.index().saturating_sub(max_input_universe.index()), - ); + let new_uv = + UniverseIndex::from(uv.index().saturating_sub(max_input_universe.index())); *var = var.with_updated_universe(new_uv); } let max_universe = var_infos .iter() .map(|info| info.universe()) .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); } } @@ -127,11 +120,11 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { // // 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. - let mut curr_compressed_uv = ty::UniverseIndex::ROOT; + let mut curr_compressed_uv = UniverseIndex::ROOT; 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() { - let mut update_uv = |var: &mut CanonicalVarInfo<'tcx>, orig_uv, is_existential| { + let mut update_uv = |var: &mut CanonicalVarInfo, orig_uv, is_existential| { let uv = var.universe(); match uv.cmp(&orig_uv) { Ordering::Less => (), // Already updated @@ -183,23 +176,25 @@ impl<'a, 'tcx> Canonicalizer<'a, 'tcx> { for var in var_infos.iter_mut() { if var.is_region() { 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) } } -impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { - fn interner(&self) -> TyCtxt<'tcx> { - self.infcx.tcx +impl, I: Interner> TypeFolder for Canonicalizer<'_, Infcx> { + fn interner(&self) -> I { + self.infcx.interner() } - fn fold_binder(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T> + fn fold_binder(&mut self, t: I::Binder) -> I::Binder where - T: TypeFoldable>, + T: TypeFoldable, + I::Binder: TypeSuperFoldable, { self.binder_index.shift_in(1); let t = t.super_fold_with(self); @@ -207,22 +202,9 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { t } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReVar(vid) = *r { - 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, + fn fold_region(&mut self, r: I::Region) -> I::Region { + let kind = match r.kind() { + RegionKind::ReBound(..) => return r, // We may encounter `ReStatic` in item signatures or the hidden type // of an opaque. `ReErased` should only be encountered in the hidden @@ -232,197 +214,212 @@ impl<'tcx> TypeFolder> for Canonicalizer<'_, 'tcx> { // FIXME: We should investigate the perf implications of not uniquifying // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. - ty::ReStatic | ty::ReErased => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + RegionKind::ReStatic | RegionKind::ReErased => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, }, - ty::ReLateParam(_) | ty::ReEarlyParam(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => bug!("unexpected region in response: {r:?}"), - }, + RegionKind::ReEarlyParam(_) | RegionKind::ReLateParam(_) => { + match self.canonicalize_mode { + 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. - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), CanonicalizeMode::Response { max_input_universe } => { // If we have a placeholder region inside of a query, it must be from // a new universe. - if max_input_universe.can_name(placeholder.universe) { - bug!("new placeholder in universe {max_input_universe:?}: {r:?}"); + if max_input_universe.can_name(placeholder.universe()) { + panic!("new placeholder in universe {max_input_universe:?}: {r:?}"); } CanonicalVarKind::PlaceholderRegion(placeholder) } }, - ty::ReVar(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => { - CanonicalVarKind::Region(self.infcx.universe_of_region(r)) - } - }, + RegionKind::ReVar(vid) => { + assert_eq!( + self.infcx.root_lt_var(vid.clone()), + 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 { CanonicalizeMode::Input => None, 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 = ty::BoundVar::from(self.variables.len()); + let var = BoundVar::from(self.variables.len()); self.variables.push(r.into()); self.primitive_var_infos.push(CanonicalVarInfo { kind }); 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> { - let kind = match *t.kind() { - ty::Infer(ty::TyVar(vid)) => { - assert_eq!(self.infcx.root_var(vid), vid, "ty vid should have been resolved"); - let Err(ui) = self.infcx.probe_ty_var(vid) else { - bug!("ty var should have been resolved: {t}"); - }; - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) - } - ty::Infer(ty::IntVar(vid)) => { - assert_eq!(self.infcx.opportunistic_resolve_int_var(vid), t); - CanonicalVarKind::Ty(CanonicalTyVarKind::Int) - } - ty::Infer(ty::FloatVar(vid)) => { - assert_eq!(self.infcx.opportunistic_resolve_float_var(vid), t); - CanonicalVarKind::Ty(CanonicalTyVarKind::Float) - } - ty::Infer(ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => { - bug!("fresh var during canonicalization: {t:?}") - } - ty::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { - universe: placeholder.universe, - bound: ty::BoundTy { - var: ty::BoundVar::from_usize(self.variables.len()), - kind: ty::BoundTyKind::Anon, - }, - }), + fn fold_ty(&mut self, t: I::Ty) -> I::Ty + where + I::Ty: TypeSuperFoldable, + { + let kind = match t.kind() { + TyKind::Infer(i) => match i { + InferTy::TyVar(vid) => { + assert_eq!( + self.infcx.root_ty_var(vid), + vid, + "ty vid should have been resolved fully before canonicalization" + ); + assert_eq!( + self.infcx.probe_ty_var(vid), + None, + "ty vid should have been resolved fully before canonicalization" + ); + + CanonicalVarKind::Ty(CanonicalTyVarKind::General( + self.infcx + .universe_of_ty(vid) + .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), + )) + } + InferTy::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int), + 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), }, - ty::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(ty::Placeholder { - universe: ty::UniverseIndex::ROOT, - bound: ty::BoundTy { - var: ty::BoundVar::from_usize(self.variables.len()), - kind: ty::BoundTyKind::Anon, - }, - }), - CanonicalizeMode::Response { .. } => bug!("param ty in response: {t:?}"), + TyKind::Param(_) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(Placeholder::new( + UniverseIndex::ROOT, + self.variables.len().into(), + )), + CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, - ty::Bool - | ty::Char - | ty::Int(_) - | ty::Uint(_) - | ty::Float(_) - | ty::Adt(_, _) - | ty::Foreign(_) - | ty::Str - | ty::Array(_, _) - | ty::Slice(_) - | ty::RawPtr(_) - | ty::Ref(_, _, _) - | ty::FnDef(_, _) - | ty::FnPtr(_) - | ty::Dynamic(_, _, _) - | ty::Closure(_, _) - | ty::Coroutine(_, _, _) - | ty::CoroutineWitness(..) - | ty::Never - | ty::Tuple(_) - | ty::Alias(_, _) - | ty::Bound(_, _) - | ty::Error(_) => return t.super_fold_with(self), + TyKind::Bool + | TyKind::Char + | TyKind::Int(_) + | TyKind::Uint(_) + | TyKind::Float(_) + | TyKind::Adt(_, _) + | TyKind::Foreign(_) + | TyKind::Str + | TyKind::Array(_, _) + | TyKind::Slice(_) + | TyKind::RawPtr(_) + | TyKind::Ref(_, _, _) + | TyKind::FnDef(_, _) + | TyKind::FnPtr(_) + | TyKind::Dynamic(_, _, _) + | TyKind::Closure(_, _) + | TyKind::Coroutine(_, _, _) + | TyKind::CoroutineWitness(..) + | TyKind::Never + | TyKind::Tuple(_) + | TyKind::Alias(_, _) + | TyKind::Bound(_, _) + | TyKind::Error(_) => return t.super_fold_with(self), }; - let var = ty::BoundVar::from( - self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| { + let t = t.clone().into(); + let var = + BoundVar::from(self.variables.iter().position(|v| v == &t).unwrap_or_else(|| { let var = self.variables.len(); - self.variables.push(t.into()); + self.variables.push(t); self.primitive_var_infos.push(CanonicalVarInfo { kind }); 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, + { let kind = match c.kind() { - ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { - assert_eq!( - self.infcx.root_const_var(vid), - vid, - "const var should have been resolved" - ); - let Err(ui) = self.infcx.probe_const_var(vid) else { - bug!("const var should have been resolved"); - }; - // FIXME: we should fold this ty eventually - CanonicalVarKind::Const(ui, c.ty()) - } - ty::ConstKind::Infer(ty::InferConst::EffectVar(vid)) => { - 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:?}") + ConstKind::Infer(i) => { + // FIXME: we should fold the ty too eventually + match i { + InferConst::Var(vid) => { + assert_eq!( + self.infcx.root_ct_var(vid), + vid, + "region vid should have been resolved fully before canonicalization" + ); + assert_eq!( + 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::Placeholder(placeholder) => match self.canonicalize_mode { + ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( - ty::Placeholder { - universe: placeholder.universe, - bound: ty::BoundVar::from(self.variables.len()), - }, + Placeholder::new(placeholder.universe(), self.variables.len().into()), c.ty(), ), CanonicalizeMode::Response { .. } => { CanonicalVarKind::PlaceholderConst(placeholder, c.ty()) } }, - ty::ConstKind::Param(_) => match self.canonicalize_mode { + ConstKind::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( - ty::Placeholder { - universe: ty::UniverseIndex::ROOT, - bound: ty::BoundVar::from(self.variables.len()), - }, + Placeholder::new(UniverseIndex::ROOT, self.variables.len().into()), c.ty(), ), - CanonicalizeMode::Response { .. } => bug!("param ty in response: {c:?}"), + CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, - ty::ConstKind::Bound(_, _) - | ty::ConstKind::Unevaluated(_) - | ty::ConstKind::Value(_) - | ty::ConstKind::Error(_) - | ty::ConstKind::Expr(_) => return c.super_fold_with(self), + ConstKind::Bound(_, _) + | ConstKind::Unevaluated(_) + | ConstKind::Value(_) + | ConstKind::Error(_) + | ConstKind::Expr(_) => return c.super_fold_with(self), }; - let var = ty::BoundVar::from( - self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| { + let ty = c.ty(); + let c = c.clone().into(); + let var = + BoundVar::from(self.variables.iter().position(|v| v == &c).unwrap_or_else(|| { let var = self.variables.len(); - self.variables.push(c.into()); + self.variables.push(c); self.primitive_var_infos.push(CanonicalVarInfo { kind }); var - }), - ); - ty::Const::new_bound(self.infcx.tcx, self.binder_index, var, c.ty()) + })); + + self.interner().mk_bound_const(self.binder_index, var, ty) } } diff --git a/compiler/rustc_next_trait_solver/src/lib.rs b/compiler/rustc_next_trait_solver/src/lib.rs new file mode 100644 index 0000000000000..e5fc8f755e0a9 --- /dev/null +++ b/compiler/rustc_next_trait_solver/src/lib.rs @@ -0,0 +1 @@ +pub mod canonicalizer; diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 7d098180b9314..29c0d8b5ff172 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -15,6 +15,7 @@ rustc_index = { path = "../rustc_index" } rustc_infer = { path = "../rustc_infer" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } +rustc_next_trait_solver = { path = "../rustc_next_trait_solver" } rustc_parse_format = { path = "../rustc_parse_format" } rustc_query_system = { path = "../rustc_query_system" } rustc_session = { path = "../rustc_session" } diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs index da2f16e97608a..7457ba837f505 100644 --- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs +++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs @@ -9,7 +9,6 @@ //! //! [c]: https://rustc-dev-guide.rust-lang.org/solve/canonicalization.html use super::{CanonicalInput, Certainty, EvalCtxt, Goal}; -use crate::solve::canonicalize::{CanonicalizeMode, Canonicalizer}; use crate::solve::{ 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::ty::{self, BoundVar, GenericArgKind, Ty, TyCtxt, TypeFoldable}; +use rustc_next_trait_solver::canonicalizer::{CanonicalizeMode, Canonicalizer}; use rustc_span::DUMMY_SP; use std::iter; use std::ops::Deref; diff --git a/compiler/rustc_trait_selection/src/solve/mod.rs b/compiler/rustc_trait_selection/src/solve/mod.rs index cf3f94e26e402..0ab099ef0c8d1 100644 --- a/compiler/rustc_trait_selection/src/solve/mod.rs +++ b/compiler/rustc_trait_selection/src/solve/mod.rs @@ -30,7 +30,6 @@ use rustc_middle::ty::{ mod alias_relate; mod assembly; -mod canonicalize; mod eval_ctxt; mod fulfill; pub mod inspect; diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index d2768703297e3..514658046b7c7 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -162,7 +162,7 @@ impl CanonicalVarInfo { } #[must_use] - pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo { + pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarInfo { CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) } } @@ -324,13 +324,13 @@ impl CanonicalVarKind { /// /// In case this is a float or int variable, this causes an ICE if /// the updated universe is not the root. - pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind { + pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarKind { match self { CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => { CanonicalVarKind::Ty(CanonicalTyVarKind::General(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.with_updated_universe(ui)) @@ -339,12 +339,15 @@ impl CanonicalVarKind { CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui)) } 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::Effect => { assert_eq!(ui, UniverseIndex::ROOT); - self + self.clone() } } } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 409033a2d8d0e..fb5b2a4437f61 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -146,15 +146,15 @@ impl DebugWithInfcx for InferConst { this: WithInfcx<'_, Infcx, &Self>, f: &mut core::fmt::Formatter<'_>, ) -> core::fmt::Result { - match this.infcx.universe_of_ct(*this.data) { - None => write!(f, "{:?}", this.data), - Some(universe) => match *this.data { - InferConst::Var(vid) => write!(f, "?{}_{}c", vid.index(), universe.index()), - InferConst::EffectVar(vid) => write!(f, "?{}_{}e", vid.index(), universe.index()), - InferConst::Fresh(_) => { - unreachable!() - } + match *this.data { + InferConst::Var(vid) => match this.infcx.universe_of_ct(vid) { + None => write!(f, "{:?}", this.data), + Some(universe) => write!(f, "?{}_{}c", vid.index(), universe.index()), }, + InferConst::EffectVar(vid) => write!(f, "?{}e", vid.index()), + InferConst::Fresh(_) => { + unreachable!() + } } } } diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index db29ec9da8c9e..1732d311cb400 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -1,35 +1,56 @@ -use crate::{InferConst, InferTy, Interner, UniverseIndex}; +use crate::{ConstVid, InferCtxtLike, Interner, TyVid, UniverseIndex}; use core::fmt; use std::marker::PhantomData; -pub trait InferCtxtLike { - type Interner: Interner; +pub struct NoInfcx(PhantomData); - fn universe_of_ty(&self, ty: InferTy) -> Option; +impl InferCtxtLike for NoInfcx { + type Interner = I; - fn universe_of_lt( - &self, - lt: ::InferRegion, - ) -> Option; + fn interner(&self) -> Self::Interner { + unreachable!() + } - fn universe_of_ct(&self, ct: InferConst) -> Option; -} + fn universe_of_ty(&self, _ty: TyVid) -> Option { + None + } -pub struct NoInfcx(PhantomData); + fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { + None + } -impl InferCtxtLike for NoInfcx { - type Interner = I; + fn universe_of_ct(&self, _ct: ConstVid) -> Option { + None + } - fn universe_of_ty(&self, _ty: InferTy) -> Option { + fn root_ty_var(&self, vid: TyVid) -> TyVid { + vid + } + + fn probe_ty_var(&self, _vid: TyVid) -> Option<::Ty> { None } - fn universe_of_ct(&self, _ct: InferConst) -> Option { + fn root_lt_var( + &self, + vid: ::InferRegion, + ) -> ::InferRegion { + vid + } + + fn probe_lt_var( + &self, + _vid: ::InferRegion, + ) -> Option<::Region> { None } - fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { + fn root_ct_var(&self, vid: ConstVid) -> ConstVid { + vid + } + + fn probe_ct_var(&self, _vid: ConstVid) -> Option<::Const> { None } } diff --git a/compiler/rustc_type_ir/src/infcx.rs b/compiler/rustc_type_ir/src/infcx.rs new file mode 100644 index 0000000000000..681f129a50b7c --- /dev/null +++ b/compiler/rustc_type_ir/src/infcx.rs @@ -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; + + /// 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<::Ty>; + + fn universe_of_lt( + &self, + lt: ::InferRegion, + ) -> Option; + + /// Resolve `InferRegion` to its root `InferRegion`. + fn root_lt_var( + &self, + vid: ::InferRegion, + ) -> ::InferRegion; + + /// Resolve `InferRegion` to its inferred region, if it has been equated with a non-infer region. + fn probe_lt_var( + &self, + vid: ::InferRegion, + ) -> Option<::Region>; + + fn universe_of_ct(&self, ct: ConstVid) -> Option; + + /// 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<::Const>; +} diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 300b0bf090d7b..0acd576050f54 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -2,8 +2,12 @@ use smallvec::SmallVec; use std::fmt::Debug; 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 { type DefId: Clone + Debug + Hash + Ord; type AdtDef: Clone + Debug + Hash + Ord; @@ -18,10 +22,15 @@ pub trait Interner: Sized { type Binder; type TypeAndMut: Clone + Debug + Hash + Ord; - type CanonicalVars: Clone + Debug + Hash + Eq; + type CanonicalVars: Clone + Debug + Hash + Eq + IntoIterator>; // Kinds of tys - type Ty: Clone + DebugWithInfcx + Hash + Ord; + type Ty: Clone + + DebugWithInfcx + + Hash + + Ord + + Into + + IntoKind>; type Tys: Clone + Debug + Hash + Ord + IntoIterator; type AliasTy: Clone + DebugWithInfcx + Hash + Ord; type ParamTy: Clone + Debug + Hash + Ord; @@ -35,7 +44,13 @@ pub trait Interner: Sized { type AllocId: Clone + Debug + Hash + Ord; // Kinds of consts - type Const: Clone + DebugWithInfcx + Hash + Ord; + type Const: Clone + + DebugWithInfcx + + Hash + + Ord + + Into + + IntoKind> + + ConstTy; type AliasConst: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder; type ParamConst: Clone + Debug + Hash + Ord; @@ -44,10 +59,15 @@ pub trait Interner: Sized { type ExprConst: Clone + DebugWithInfcx + Hash + Ord; // Kinds of regions - type Region: Clone + DebugWithInfcx + Hash + Ord; + type Region: Clone + + DebugWithInfcx + + Hash + + Ord + + Into + + IntoKind>; type EarlyParamRegion: Clone + Debug + Hash + Ord; - type BoundRegion: Clone + Debug + Hash + Ord; type LateParamRegion: Clone + Debug + Hash + Ord; + type BoundRegion: Clone + Debug + Hash + Ord; type InferRegion: Clone + DebugWithInfcx + Hash + Ord; type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder; @@ -63,6 +83,12 @@ pub trait Interner: Sized { type ClosureKind: Clone + Debug + Hash + Eq; fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability); + + fn mk_canonical_var_infos(&self, infos: &[CanonicalVarInfo]) -> 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 @@ -70,7 +96,19 @@ pub trait Placeholder { fn universe(&self) -> UniverseIndex; 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 { + fn ty(&self) -> I::Ty; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 2aeb4230bb83c..1bcb1fcff359f 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -35,6 +35,7 @@ mod canonical; mod const_kind; mod debug; mod flags; +mod infcx; mod interner; mod predicate_kind; mod region_kind; @@ -43,8 +44,9 @@ pub use canonical::*; #[cfg(feature = "nightly")] pub use codec::*; pub use const_kind::*; -pub use debug::{DebugWithInfcx, InferCtxtLike, WithInfcx}; +pub use debug::{DebugWithInfcx, WithInfcx}; pub use flags::*; +pub use infcx::InferCtxtLike; pub use interner::*; pub use predicate_kind::*; pub use region_kind::*; @@ -337,6 +339,12 @@ impl UniverseIndex { } } +impl Default for UniverseIndex { + fn default() -> Self { + Self::ROOT + } +} + rustc_index::newtype_index! { #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))] #[encodable] diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 3d4e7f77a4f2c..9d3a578c3e48a 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -820,15 +820,15 @@ impl DebugWithInfcx for InferTy { this: WithInfcx<'_, Infcx, &Self>, f: &mut fmt::Formatter<'_>, ) -> fmt::Result { - use InferTy::*; - match this.infcx.universe_of_ty(*this.data) { - None => write!(f, "{:?}", this.data), - Some(universe) => match *this.data { - TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()), - IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => { - unreachable!() + match this.data { + InferTy::TyVar(vid) => { + if let Some(universe) = this.infcx.universe_of_ty(*vid) { + write!(f, "?{}_{}t", vid.index(), universe.index()) + } else { + write!(f, "{:?}", this.data) } - }, + } + _ => write!(f, "{:?}", this.data), } } } From 1f5895b3e31e10fb9121c751b5aedc31dfe3d92f Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 5 Dec 2023 18:10:23 +0000 Subject: [PATCH 2/3] Feedback - Take more things by self, not &self - Clone more things - Rework namespacing so we can use `ty::` in the canonicalizer --- compiler/rustc_middle/src/ty/consts.rs | 8 +- compiler/rustc_middle/src/ty/context.rs | 31 +-- compiler/rustc_middle/src/ty/mod.rs | 39 ++-- compiler/rustc_middle/src/ty/sty.rs | 4 +- .../src/canonicalizer.rs | 195 +++++++++--------- compiler/rustc_type_ir/src/canonical.rs | 25 +-- compiler/rustc_type_ir/src/const_kind.rs | 2 +- compiler/rustc_type_ir/src/debug.rs | 16 +- compiler/rustc_type_ir/src/interner.rs | 100 ++++----- compiler/rustc_type_ir/src/lib.rs | 6 + compiler/rustc_type_ir/src/ty_kind.rs | 8 +- 11 files changed, 205 insertions(+), 229 deletions(-) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 78cc2f91796db..293df4f691d46 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -29,14 +29,14 @@ pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo IntoKind for Const<'tcx> { type Kind = ConstKind<'tcx>; - fn kind(&self) -> ConstKind<'tcx> { - (*self).kind().clone() + fn kind(self) -> ConstKind<'tcx> { + self.kind().clone() } } impl<'tcx> ConstTy> for Const<'tcx> { - fn ty(&self) -> Ty<'tcx> { - (*self).ty() + fn ty(self) -> Ty<'tcx> { + self.ty() } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index a39acc9859fcb..050f074ee0a40 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -132,40 +132,29 @@ impl<'tcx> Interner for TyCtxt<'tcx> { (ty, mutbl) } - fn mk_canonical_var_infos( - &self, - infos: &[rustc_type_ir::CanonicalVarInfo], - ) -> Self::CanonicalVars { - (*self).mk_canonical_var_infos(infos) + fn mk_canonical_var_infos(self, infos: &[ty::CanonicalVarInfo]) -> 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_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: rustc_type_ir::DebruijnIndex, - var: rustc_type_ir::BoundVar, - ) -> Self::Region { + fn mk_bound_region(self, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self::Region { Region::new_bound( - *self, + self, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::BrAnon }, ) } fn mk_bound_const( - &self, - debruijn: rustc_type_ir::DebruijnIndex, - var: rustc_type_ir::BoundVar, + self, + debruijn: ty::DebruijnIndex, + var: ty::BoundVar, ty: Self::Ty, ) -> Self::Const { - Const::new_bound(*self, debruijn, var, ty) + Const::new_bound(self, debruijn, var, ty) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6aaa363eb01d2..71ff7021ca5de 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -65,15 +65,10 @@ use std::ops::ControlFlow; use std::{fmt, str}; pub use crate::ty::diagnostics::*; -pub use rustc_type_ir::AliasKind::*; pub use rustc_type_ir::ConstKind::{ Bound as BoundCt, Error as ErrorCt, Expr as ExprCt, Infer as InferCt, Param as ParamCt, 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 self::binding::BindingMode; @@ -477,8 +472,8 @@ pub struct Ty<'tcx>(Interned<'tcx, WithCachedTypeInfo>>); impl<'tcx> IntoKind for Ty<'tcx> { type Kind = TyKind<'tcx>; - fn kind(&self) -> TyKind<'tcx> { - (*self).kind().clone() + fn kind(self) -> TyKind<'tcx> { + self.kind().clone() } } @@ -1553,17 +1548,17 @@ pub struct Placeholder { pub type PlaceholderRegion = Placeholder; -impl rustc_type_ir::Placeholder for PlaceholderRegion { - fn universe(&self) -> UniverseIndex { +impl PlaceholderLike for PlaceholderRegion { + fn universe(self) -> UniverseIndex { self.universe } - fn var(&self) -> BoundVar { + fn var(self) -> BoundVar { self.bound.var } - fn with_updated_universe(&self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..*self } + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } } fn new(ui: UniverseIndex, var: BoundVar) -> Self { @@ -1573,17 +1568,17 @@ impl rustc_type_ir::Placeholder for PlaceholderRegion { pub type PlaceholderType = Placeholder; -impl rustc_type_ir::Placeholder for PlaceholderType { - fn universe(&self) -> UniverseIndex { +impl PlaceholderLike for PlaceholderType { + fn universe(self) -> UniverseIndex { self.universe } - fn var(&self) -> BoundVar { + fn var(self) -> BoundVar { self.bound.var } - fn with_updated_universe(&self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..*self } + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } } fn new(ui: UniverseIndex, var: BoundVar) -> Self { @@ -1600,17 +1595,17 @@ pub struct BoundConst<'tcx> { pub type PlaceholderConst = Placeholder; -impl rustc_type_ir::Placeholder for PlaceholderConst { - fn universe(&self) -> UniverseIndex { +impl PlaceholderLike for PlaceholderConst { + fn universe(self) -> UniverseIndex { self.universe } - fn var(&self) -> BoundVar { + fn var(self) -> BoundVar { self.bound } - fn with_updated_universe(&self, ui: UniverseIndex) -> Self { - Placeholder { universe: ui, ..*self } + fn with_updated_universe(self, ui: UniverseIndex) -> Self { + Placeholder { universe: ui, ..self } } fn new(ui: UniverseIndex, var: BoundVar) -> Self { diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index ed2f8f0a6abb4..50a1b85b16918 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -1480,8 +1480,8 @@ 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 + fn kind(self) -> RegionKind<'tcx> { + *self } } diff --git a/compiler/rustc_next_trait_solver/src/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonicalizer.rs index c2e6e82f2afb8..cb1f328577d02 100644 --- a/compiler/rustc_next_trait_solver/src/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonicalizer.rs @@ -2,9 +2,8 @@ use std::cmp::Ordering; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::{ - BoundVar, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstKind, - ConstTy, DebruijnIndex, InferConst, InferCtxtLike, InferTy, Interner, IntoKind, Placeholder, - RegionKind, TyKind, UniverseIndex, INNERMOST, + self as ty, Canonical, CanonicalTyVarKind, CanonicalVarInfo, CanonicalVarKind, ConstTy, + InferCtxtLike, Interner, IntoKind, PlaceholderLike, }; /// Whether we're canonicalizing a query input or the query response. @@ -32,33 +31,33 @@ pub enum CanonicalizeMode { /// /// This doesn't work for universes created inside of the query so /// we do remember their universe in the response. - max_input_universe: UniverseIndex, + max_input_universe: ty::UniverseIndex, }, } -pub struct Canonicalizer<'a, Infcx: InferCtxtLike> { +pub struct Canonicalizer<'a, Infcx: InferCtxtLike, I: Interner> { infcx: &'a Infcx, canonicalize_mode: CanonicalizeMode, - variables: &'a mut Vec<::GenericArg>, - primitive_var_infos: Vec>, - binder_index: DebruijnIndex, + variables: &'a mut Vec, + primitive_var_infos: Vec>, + binder_index: ty::DebruijnIndex, } -impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infcx> { +impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infcx, I> { pub fn canonicalize>( infcx: &'a Infcx, canonicalize_mode: CanonicalizeMode, - variables: &'a mut Vec<::GenericArg>, + variables: &'a mut Vec, value: T, - ) -> Canonical { + ) -> ty::Canonical { let mut canonicalizer = Canonicalizer { infcx, canonicalize_mode, variables, primitive_var_infos: Vec::new(), - binder_index: INNERMOST, + binder_index: ty::INNERMOST, }; let value = value.fold_with(&mut canonicalizer); @@ -71,7 +70,7 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc Canonical { max_universe, variables, value } } - fn finalize(self) -> (UniverseIndex, ::CanonicalVars) { + fn finalize(self) -> (ty::UniverseIndex, I::CanonicalVars) { let mut var_infos = self.primitive_var_infos; // See the rustc-dev-guide section about how we deal with universes // during canonicalization in the new solver. @@ -88,15 +87,16 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc CanonicalizeMode::Response { max_input_universe } => { for var in var_infos.iter_mut() { let uv = var.universe(); - let new_uv = - UniverseIndex::from(uv.index().saturating_sub(max_input_universe.index())); + let new_uv = ty::UniverseIndex::from( + uv.index().saturating_sub(max_input_universe.index()), + ); *var = var.with_updated_universe(new_uv); } let max_universe = var_infos .iter() .map(|info| info.universe()) .max() - .unwrap_or(UniverseIndex::ROOT); + .unwrap_or(ty::UniverseIndex::ROOT); let var_infos = self.infcx.interner().mk_canonical_var_infos(&var_infos); return (max_universe, var_infos); @@ -120,9 +120,9 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc // // 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. - let mut curr_compressed_uv = UniverseIndex::ROOT; + let mut curr_compressed_uv = ty::UniverseIndex::ROOT; let mut existential_in_new_uv = false; - let mut next_orig_uv = Some(UniverseIndex::ROOT); + let mut next_orig_uv = Some(ty::UniverseIndex::ROOT); while let Some(orig_uv) = next_orig_uv.take() { let mut update_uv = |var: &mut CanonicalVarInfo, orig_uv, is_existential| { let uv = var.universe(); @@ -176,8 +176,7 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc for var in var_infos.iter_mut() { if var.is_region() { assert!(var.is_existential()); - let compressed_var = var.with_updated_universe(curr_compressed_uv); - *var = compressed_var; + *var = var.with_updated_universe(curr_compressed_uv); } } @@ -186,7 +185,9 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> Canonicalizer<'a, Infc } } -impl, I: Interner> TypeFolder for Canonicalizer<'_, Infcx> { +impl, I: Interner> TypeFolder + for Canonicalizer<'_, Infcx, I> +{ fn interner(&self) -> I { self.infcx.interner() } @@ -204,7 +205,7 @@ impl, I: Interner> TypeFolder for Canonica fn fold_region(&mut self, r: I::Region) -> I::Region { let kind = match r.kind() { - RegionKind::ReBound(..) => return r, + ty::ReBound(..) => return r, // We may encounter `ReStatic` in item signatures or the hidden type // of an opaque. `ReErased` should only be encountered in the hidden @@ -214,23 +215,21 @@ impl, I: Interner> TypeFolder for Canonica // FIXME: We should investigate the perf implications of not uniquifying // `ReErased`. We may be able to short-circuit registering region // obligations if we encounter a `ReErased` on one side, for example. - RegionKind::ReStatic | RegionKind::ReErased => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), + ty::ReStatic | ty::ReErased => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => return r, }, - RegionKind::ReEarlyParam(_) | RegionKind::ReLateParam(_) => { - match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), - CanonicalizeMode::Response { .. } => { - panic!("unexpected region in response: {r:?}") - } + ty::ReEarlyParam(_) | ty::ReLateParam(_) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), + CanonicalizeMode::Response { .. } => { + panic!("unexpected region in response: {r:?}") } - } + }, - RegionKind::RePlaceholder(placeholder) => match self.canonicalize_mode { + ty::RePlaceholder(placeholder) => match self.canonicalize_mode { // We canonicalize placeholder regions as existentials in query inputs. - CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { max_input_universe } => { // If we have a placeholder region inside of a query, it must be from // a new universe. @@ -241,38 +240,37 @@ impl, I: Interner> TypeFolder for Canonica } }, - RegionKind::ReVar(vid) => { + ty::ReVar(vid) => { assert_eq!( - self.infcx.root_lt_var(vid.clone()), + self.infcx.root_lt_var(vid), vid, "region vid should have been resolved fully before canonicalization" ); assert_eq!( - self.infcx.probe_lt_var(vid.clone()), + self.infcx.probe_lt_var(vid), None, "region vid should have been resolved fully before canonicalization" ); match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::Region(UniverseIndex::ROOT), + CanonicalizeMode::Input => CanonicalVarKind::Region(ty::UniverseIndex::ROOT), CanonicalizeMode::Response { .. } => { CanonicalVarKind::Region(self.infcx.universe_of_lt(vid).unwrap()) } } } - RegionKind::ReError(_) => return r, + ty::ReError(_) => return r, }; let existing_bound_var = match self.canonicalize_mode { CanonicalizeMode::Input => None, CanonicalizeMode::Response { .. } => { - let r = r.clone().into(); - self.variables.iter().position(|v| v == &r).map(BoundVar::from) + self.variables.iter().position(|&v| v == r.into()).map(ty::BoundVar::from) } }; let var = existing_bound_var.unwrap_or_else(|| { - let var = BoundVar::from(self.variables.len()); + let var = ty::BoundVar::from(self.variables.len()); self.variables.push(r.into()); self.primitive_var_infos.push(CanonicalVarInfo { kind }); var @@ -286,8 +284,8 @@ impl, I: Interner> TypeFolder for Canonica I::Ty: TypeSuperFoldable, { let kind = match t.kind() { - TyKind::Infer(i) => match i { - InferTy::TyVar(vid) => { + ty::Infer(i) => match i { + ty::TyVar(vid) => { assert_eq!( self.infcx.root_ty_var(vid), vid, @@ -305,59 +303,59 @@ impl, I: Interner> TypeFolder for Canonica .unwrap_or_else(|| panic!("ty var should have been resolved: {t:?}")), )) } - InferTy::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int), - InferTy::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float), - InferTy::FreshTy(_) | InferTy::FreshIntTy(_) | InferTy::FreshFloatTy(_) => { + ty::IntVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Int), + ty::FloatVar(_) => CanonicalVarKind::Ty(CanonicalTyVarKind::Float), + ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => { todo!() } }, - TyKind::Placeholder(placeholder) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(Placeholder::new( + ty::Placeholder(placeholder) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new( placeholder.universe(), self.variables.len().into(), )), CanonicalizeMode::Response { .. } => CanonicalVarKind::PlaceholderTy(placeholder), }, - TyKind::Param(_) => match self.canonicalize_mode { - CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(Placeholder::new( - UniverseIndex::ROOT, + ty::Param(_) => match self.canonicalize_mode { + CanonicalizeMode::Input => CanonicalVarKind::PlaceholderTy(PlaceholderLike::new( + ty::UniverseIndex::ROOT, self.variables.len().into(), )), CanonicalizeMode::Response { .. } => panic!("param ty in response: {t:?}"), }, - TyKind::Bool - | TyKind::Char - | TyKind::Int(_) - | TyKind::Uint(_) - | TyKind::Float(_) - | TyKind::Adt(_, _) - | TyKind::Foreign(_) - | TyKind::Str - | TyKind::Array(_, _) - | TyKind::Slice(_) - | TyKind::RawPtr(_) - | TyKind::Ref(_, _, _) - | TyKind::FnDef(_, _) - | TyKind::FnPtr(_) - | TyKind::Dynamic(_, _, _) - | TyKind::Closure(_, _) - | TyKind::Coroutine(_, _, _) - | TyKind::CoroutineWitness(..) - | TyKind::Never - | TyKind::Tuple(_) - | TyKind::Alias(_, _) - | TyKind::Bound(_, _) - | TyKind::Error(_) => return t.super_fold_with(self), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _, _) + | ty::Closure(_, _) + | ty::Coroutine(_, _, _) + | ty::CoroutineWitness(..) + | ty::Never + | ty::Tuple(_) + | ty::Alias(_, _) + | ty::Bound(_, _) + | ty::Error(_) => return t.super_fold_with(self), }; - let t = t.clone().into(); - let var = - BoundVar::from(self.variables.iter().position(|v| v == &t).unwrap_or_else(|| { + let var = ty::BoundVar::from( + self.variables.iter().position(|&v| v == t.into()).unwrap_or_else(|| { let var = self.variables.len(); - self.variables.push(t); + self.variables.push(t.into()); self.primitive_var_infos.push(CanonicalVarInfo { kind }); var - })); + }), + ); self.interner().mk_bound_ty(self.binder_index, var) } @@ -367,10 +365,10 @@ impl, I: Interner> TypeFolder for Canonica I::Const: TypeSuperFoldable, { let kind = match c.kind() { - ConstKind::Infer(i) => { + ty::ConstKind::Infer(i) => { // FIXME: we should fold the ty too eventually match i { - InferConst::Var(vid) => { + ty::InferConst::Var(vid) => { assert_eq!( self.infcx.root_ct_var(vid), vid, @@ -383,43 +381,42 @@ impl, I: Interner> TypeFolder for Canonica ); CanonicalVarKind::Const(self.infcx.universe_of_ct(vid).unwrap(), c.ty()) } - InferConst::EffectVar(_) => CanonicalVarKind::Effect, - InferConst::Fresh(_) => todo!(), + ty::InferConst::EffectVar(_) => CanonicalVarKind::Effect, + ty::InferConst::Fresh(_) => todo!(), } } - ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { + ty::ConstKind::Placeholder(placeholder) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( - Placeholder::new(placeholder.universe(), self.variables.len().into()), + PlaceholderLike::new(placeholder.universe(), self.variables.len().into()), c.ty(), ), CanonicalizeMode::Response { .. } => { CanonicalVarKind::PlaceholderConst(placeholder, c.ty()) } }, - ConstKind::Param(_) => match self.canonicalize_mode { + ty::ConstKind::Param(_) => match self.canonicalize_mode { CanonicalizeMode::Input => CanonicalVarKind::PlaceholderConst( - Placeholder::new(UniverseIndex::ROOT, self.variables.len().into()), + PlaceholderLike::new(ty::UniverseIndex::ROOT, self.variables.len().into()), c.ty(), ), CanonicalizeMode::Response { .. } => panic!("param ty in response: {c:?}"), }, - ConstKind::Bound(_, _) - | ConstKind::Unevaluated(_) - | ConstKind::Value(_) - | ConstKind::Error(_) - | ConstKind::Expr(_) => return c.super_fold_with(self), + ty::ConstKind::Bound(_, _) + | ty::ConstKind::Unevaluated(_) + | ty::ConstKind::Value(_) + | ty::ConstKind::Error(_) + | ty::ConstKind::Expr(_) => return c.super_fold_with(self), }; - let ty = c.ty(); - let c = c.clone().into(); - let var = - BoundVar::from(self.variables.iter().position(|v| v == &c).unwrap_or_else(|| { + let var = ty::BoundVar::from( + self.variables.iter().position(|&v| v == c.into()).unwrap_or_else(|| { let var = self.variables.len(); - self.variables.push(c); + self.variables.push(c.into()); self.primitive_var_infos.push(CanonicalVarInfo { kind }); var - })); + }), + ); - self.interner().mk_bound_const(self.binder_index, var, ty) + self.interner().mk_bound_const(self.binder_index, var, c.ty()) } } diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index 514658046b7c7..572c6f201d379 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -4,7 +4,7 @@ use std::ops::ControlFlow; use crate::fold::{FallibleTypeFolder, TypeFoldable}; 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 /// variables have been rewritten to "canonical vars". These are @@ -157,12 +157,12 @@ where } impl CanonicalVarInfo { - pub fn universe(&self) -> UniverseIndex { + pub fn universe(self) -> UniverseIndex { self.kind.universe() } #[must_use] - pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarInfo { + pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarInfo { CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) } } @@ -305,11 +305,11 @@ where } impl CanonicalVarKind { - pub fn universe(&self) -> UniverseIndex { + pub fn universe(self) -> UniverseIndex { match self { - CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => *ui, - CanonicalVarKind::Region(ui) => *ui, - CanonicalVarKind::Const(ui, _) => *ui, + CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) => ui, + CanonicalVarKind::Region(ui) => ui, + CanonicalVarKind::Const(ui, _) => ui, CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe(), CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe(), @@ -324,13 +324,13 @@ impl CanonicalVarKind { /// /// In case this is a float or int variable, this causes an ICE if /// the updated universe is not the root. - pub fn with_updated_universe(&self, ui: UniverseIndex) -> CanonicalVarKind { + pub fn with_updated_universe(self, ui: UniverseIndex) -> CanonicalVarKind { match self { CanonicalVarKind::Ty(CanonicalTyVarKind::General(_)) => { CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui)) } CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui), - CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty.clone()), + CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty), CanonicalVarKind::PlaceholderTy(placeholder) => { CanonicalVarKind::PlaceholderTy(placeholder.with_updated_universe(ui)) @@ -339,15 +339,12 @@ impl CanonicalVarKind { CanonicalVarKind::PlaceholderRegion(placeholder.with_updated_universe(ui)) } CanonicalVarKind::PlaceholderConst(placeholder, ty) => { - CanonicalVarKind::PlaceholderConst( - placeholder.with_updated_universe(ui), - ty.clone(), - ) + CanonicalVarKind::PlaceholderConst(placeholder.with_updated_universe(ui), ty) } CanonicalVarKind::Ty(CanonicalTyVarKind::Int | CanonicalTyVarKind::Float) | CanonicalVarKind::Effect => { assert_eq!(ui, UniverseIndex::ROOT); - self.clone() + self } } } diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index fb5b2a4437f61..879de58f10054 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -81,7 +81,7 @@ impl DebugWithInfcx for ConstKind { match this.data { Param(param) => write!(f, "{param:?}"), 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:?}"), Unevaluated(uv) => { write!(f, "{:?}", &this.wrap(uv)) diff --git a/compiler/rustc_type_ir/src/debug.rs b/compiler/rustc_type_ir/src/debug.rs index 1732d311cb400..8998001ec20ec 100644 --- a/compiler/rustc_type_ir/src/debug.rs +++ b/compiler/rustc_type_ir/src/debug.rs @@ -16,7 +16,7 @@ impl InferCtxtLike for NoInfcx { None } - fn universe_of_lt(&self, _lt: ::InferRegion) -> Option { + fn universe_of_lt(&self, _lt: I::InferRegion) -> Option { None } @@ -28,21 +28,15 @@ impl InferCtxtLike for NoInfcx { vid } - fn probe_ty_var(&self, _vid: TyVid) -> Option<::Ty> { + fn probe_ty_var(&self, _vid: TyVid) -> Option { None } - fn root_lt_var( - &self, - vid: ::InferRegion, - ) -> ::InferRegion { + fn root_lt_var(&self, vid: I::InferRegion) -> I::InferRegion { vid } - fn probe_lt_var( - &self, - _vid: ::InferRegion, - ) -> Option<::Region> { + fn probe_lt_var(&self, _vid: I::InferRegion) -> Option { None } @@ -50,7 +44,7 @@ impl InferCtxtLike for NoInfcx { vid } - fn probe_ct_var(&self, _vid: ConstVid) -> Option<::Const> { + fn probe_ct_var(&self, _vid: ConstVid) -> Option { None } } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0acd576050f54..c262302133bee 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -7,96 +7,96 @@ use crate::{ TyKind, UniverseIndex, }; -#[allow(rustc::usage_of_ty_tykind)] pub trait Interner: Sized { - type DefId: Clone + Debug + Hash + Ord; - type AdtDef: Clone + Debug + Hash + Ord; + type DefId: Copy + Debug + Hash + Ord; + type AdtDef: Copy + Debug + Hash + Ord; - type GenericArgs: Clone + type GenericArgs: Copy + DebugWithInfcx + Hash + Ord + IntoIterator; - type GenericArg: Clone + DebugWithInfcx + Hash + Ord; - type Term: Clone + Debug + Hash + Ord; + type GenericArg: Copy + DebugWithInfcx + Hash + Ord; + type Term: Copy + Debug + Hash + Ord; type Binder; - type TypeAndMut: Clone + Debug + Hash + Ord; - type CanonicalVars: Clone + Debug + Hash + Eq + IntoIterator>; + type TypeAndMut: Copy + Debug + Hash + Ord; + type CanonicalVars: Copy + Debug + Hash + Eq + IntoIterator>; // Kinds of tys - type Ty: Clone + type Ty: Copy + DebugWithInfcx + Hash + Ord + Into + IntoKind>; - type Tys: Clone + Debug + Hash + Ord + IntoIterator; - type AliasTy: Clone + DebugWithInfcx + Hash + Ord; - type ParamTy: Clone + Debug + Hash + Ord; - type BoundTy: Clone + Debug + Hash + Ord; - type PlaceholderTy: Clone + Debug + Hash + Ord + Placeholder; + type Tys: Copy + Debug + Hash + Ord + IntoIterator; + type AliasTy: Copy + DebugWithInfcx + 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 - type ErrorGuaranteed: Clone + Debug + Hash + Ord; - type BoundExistentialPredicates: Clone + DebugWithInfcx + Hash + Ord; - type PolyFnSig: Clone + DebugWithInfcx + Hash + Ord; - type AllocId: Clone + Debug + Hash + Ord; + type ErrorGuaranteed: Copy + Debug + Hash + Ord; + type BoundExistentialPredicates: Copy + DebugWithInfcx + Hash + Ord; + type PolyFnSig: Copy + DebugWithInfcx + Hash + Ord; + type AllocId: Copy + Debug + Hash + Ord; // Kinds of consts - type Const: Clone + type Const: Copy + DebugWithInfcx + Hash + Ord + Into + IntoKind> + ConstTy; - type AliasConst: Clone + DebugWithInfcx + Hash + Ord; - type PlaceholderConst: Clone + Debug + Hash + Ord + Placeholder; - type ParamConst: Clone + Debug + Hash + Ord; - type BoundConst: Clone + Debug + Hash + Ord; - type ValueConst: Clone + Debug + Hash + Ord; - type ExprConst: Clone + DebugWithInfcx + Hash + Ord; + type AliasConst: Copy + DebugWithInfcx + 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 + Hash + Ord; // Kinds of regions - type Region: Clone + type Region: Copy + DebugWithInfcx + Hash + Ord + Into + IntoKind>; - type EarlyParamRegion: Clone + Debug + Hash + Ord; - type LateParamRegion: Clone + Debug + Hash + Ord; - type BoundRegion: Clone + Debug + Hash + Ord; - type InferRegion: Clone + DebugWithInfcx + Hash + Ord; - type PlaceholderRegion: Clone + Debug + Hash + Ord + Placeholder; + type EarlyParamRegion: Copy + Debug + Hash + Ord; + type LateParamRegion: Copy + Debug + Hash + Ord; + type BoundRegion: Copy + Debug + Hash + Ord; + type InferRegion: Copy + DebugWithInfcx + Hash + Ord; + type PlaceholderRegion: Copy + Debug + Hash + Ord + PlaceholderLike; // Predicates - type Predicate: Clone + Debug + Hash + Eq; - type TraitPredicate: Clone + Debug + Hash + Eq; - type RegionOutlivesPredicate: Clone + Debug + Hash + Eq; - type TypeOutlivesPredicate: Clone + Debug + Hash + Eq; - type ProjectionPredicate: Clone + Debug + Hash + Eq; - type NormalizesTo: Clone + Debug + Hash + Eq; - type SubtypePredicate: Clone + Debug + Hash + Eq; - type CoercePredicate: Clone + Debug + Hash + Eq; - type ClosureKind: Clone + Debug + Hash + Eq; + type Predicate: Copy + Debug + Hash + Eq; + type TraitPredicate: Copy + Debug + Hash + Eq; + type RegionOutlivesPredicate: Copy + Debug + Hash + Eq; + type TypeOutlivesPredicate: Copy + Debug + Hash + Eq; + type ProjectionPredicate: Copy + Debug + Hash + Eq; + type NormalizesTo: Copy + Debug + Hash + Eq; + type SubtypePredicate: Copy + Debug + Hash + Eq; + type CoercePredicate: Copy + Debug + Hash + Eq; + type ClosureKind: Copy + Debug + Hash + Eq; fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Mutability); - fn mk_canonical_var_infos(&self, infos: &[CanonicalVarInfo]) -> Self::CanonicalVars; + fn mk_canonical_var_infos(self, infos: &[CanonicalVarInfo]) -> 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; + // 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 -pub trait Placeholder { - fn universe(&self) -> UniverseIndex; - fn var(&self) -> BoundVar; +pub trait PlaceholderLike { + fn universe(self) -> UniverseIndex; + 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; } @@ -104,11 +104,11 @@ pub trait Placeholder { pub trait IntoKind { type Kind; - fn kind(&self) -> Self::Kind; + fn kind(self) -> Self::Kind; } pub trait ConstTy { - fn ty(&self) -> I::Ty; + fn ty(self) -> I::Ty; } /// Imagine you have a function `F: FnOnce(&[T]) -> R`, plus an iterator `iter` diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 1bcb1fcff359f..200963ff7c5c8 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -4,6 +4,7 @@ )] #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] +#![allow(rustc::usage_of_ty_tykind)] #![cfg_attr(feature = "nightly", allow(internal_features))] #[cfg(feature = "nightly")] @@ -52,6 +53,11 @@ pub use predicate_kind::*; pub use region_kind::*; pub use ty_info::*; pub use ty_kind::*; +pub use AliasKind::*; +pub use DynKind::*; +pub use InferTy::*; +pub use RegionKind::*; +pub use TyKind::*; rustc_index::newtype_index! { /// A [De Bruijn index][dbi] is a standard means of representing diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 9d3a578c3e48a..a7a5cae254ccd 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -1,5 +1,3 @@ -#![allow(rustc::usage_of_ty_tykind)] - #[cfg(feature = "nightly")] use rustc_data_structures::stable_hasher::{HashStable, StableHasher}; #[cfg(feature = "nightly")] @@ -394,7 +392,7 @@ impl DebugWithInfcx for TyKind { Float(float) => write!(f, "{float:?}"), Adt(d, s) => { write!(f, "{d:?}")?; - let mut s = s.clone().into_iter(); + let mut s = s.into_iter(); let first = s.next(); match first { Some(first) => write!(f, "<{:?}", first)?, @@ -412,7 +410,7 @@ impl DebugWithInfcx for TyKind { Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)), Slice(t) => write!(f, "[{:?}]", &this.wrap(t)), 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 { Mutability::Mut => write!(f, "*mut "), Mutability::Not => write!(f, "*const "), @@ -442,7 +440,7 @@ impl DebugWithInfcx for TyKind { Tuple(t) => { write!(f, "(")?; let mut count = 0; - for ty in t.clone() { + for ty in *t { if count > 0 { write!(f, ", ")?; } From 80f240a539f3fa8c2892fccb0a0a54ca96589fc7 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Tue, 5 Dec 2023 18:58:14 +0000 Subject: [PATCH 3/3] Make it not depend on nightly conditionally --- compiler/rustc_next_trait_solver/Cargo.toml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_next_trait_solver/Cargo.toml b/compiler/rustc_next_trait_solver/Cargo.toml index 88c4b62c54cd5..9d496fd8e8175 100644 --- a/compiler/rustc_next_trait_solver/Cargo.toml +++ b/compiler/rustc_next_trait_solver/Cargo.toml @@ -4,4 +4,10 @@ version = "0.0.0" edition = "2021" [dependencies] -rustc_type_ir = { path = "../rustc_type_ir" } +rustc_type_ir = { path = "../rustc_type_ir", default-features = false } + +[features] +default = ["nightly"] +nightly = [ + "rustc_type_ir/nightly", +] \ No newline at end of file