Skip to content

Commit

Permalink
Rollup merge of rust-lang#117586 - compiler-errors:the-canonicalizer,…
Browse files Browse the repository at this point in the history
… 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`
  • Loading branch information
compiler-errors authored Dec 7, 2023
2 parents 95aa0b4 + 1c1df45 commit d1d761f
Show file tree
Hide file tree
Showing 20 changed files with 478 additions and 260 deletions.
8 changes: 8 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4308,6 +4308,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"
Expand Down Expand Up @@ -4576,6 +4583,7 @@ dependencies = [
"rustc_infer",
"rustc_macros",
"rustc_middle",
"rustc_next_trait_solver",
"rustc_parse_format",
"rustc_query_system",
"rustc_session",
Expand Down
72 changes: 50 additions & 22 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<ty::UniverseIndex> {
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<ty::UniverseIndex> {
// 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<ty::UniverseIndex> {
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<ty::UniverseIndex> {
// 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<ty::UniverseIndex> {
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.
Expand Down Expand Up @@ -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
}
Expand Down
5 changes: 5 additions & 0 deletions compiler/rustc_infer/src/infer/region_constraints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
18 changes: 17 additions & 1 deletion compiler/rustc_middle/src/ty/consts.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::middle::resolve_bound_vars as rbv;
use crate::mir::interpret::{AllocId, ErrorHandled, LitToConstInput, Scalar};
use crate::ty::{self, GenericArgs, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt};
use crate::ty::{
self, ConstTy, GenericArgs, IntoKind, ParamEnv, ParamEnvAnd, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_data_structures::intern::Interned;
use rustc_error_messages::MultiSpan;
use rustc_hir as hir;
Expand All @@ -26,6 +28,20 @@ use super::sty::ConstKind;
#[rustc_pass_by_value]
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.
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, TyEncodable, TyDecodable)]
pub struct ConstData<'tcx> {
Expand Down
25 changes: 25 additions & 0 deletions compiler/rustc_middle/src/ty/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,31 @@ impl<'tcx> Interner for TyCtxt<'tcx> {
) -> (Self::Ty, ty::Mutability) {
(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>, ()>;
Expand Down
43 changes: 29 additions & 14 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -474,6 +469,14 @@ pub struct CReaderCacheKey {
#[rustc_pass_by_value]
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 {
/// Does this early bound region have a name? Early bound regions normally
/// always have names except when using anonymous lifetimes (`'_`).
Expand Down Expand Up @@ -1506,34 +1509,42 @@ pub struct Placeholder<T> {

pub type PlaceholderRegion = Placeholder<BoundRegion>;

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 new(ui: UniverseIndex, var: BoundVar) -> Self {
Placeholder { universe: ui, bound: BoundRegion { var, kind: BoundRegionKind::BrAnon } }
}
}

pub type PlaceholderType = Placeholder<BoundTy>;

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 new(ui: UniverseIndex, var: BoundVar) -> Self {
Placeholder { universe: ui, bound: BoundTy { var, kind: BoundTyKind::Anon } }
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)]
Expand All @@ -1545,18 +1556,22 @@ pub struct BoundConst<'tcx> {

pub type PlaceholderConst = Placeholder<BoundVar>;

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 new(ui: UniverseIndex, var: BoundVar) -> Self {
Placeholder { universe: ui, bound: var }
}
}

/// When type checking, we use the `ParamEnv` to track
Expand Down
10 changes: 9 additions & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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(
Expand Down
13 changes: 13 additions & 0 deletions compiler/rustc_next_trait_solver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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",
]
Loading

0 comments on commit d1d761f

Please sign in to comment.