Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ impl<'tcx> ClosureOutlivesSubjectTy<'tcx> {
mut map: impl FnMut(ty::RegionVid) -> ty::Region<'tcx>,
) -> Ty<'tcx> {
fold_regions(tcx, self.inner, |r, depth| match r.kind() {
ty::ReBound(debruijn, br) => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) => {
debug_assert_eq!(debruijn, depth);
map(ty::RegionVid::from_usize(br.var.index()))
}
Expand Down
16 changes: 10 additions & 6 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,21 +174,25 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
for (param, var) in std::iter::zip(&generics.own_params, gat_vars) {
let existing = match var.kind() {
ty::GenericArgKind::Lifetime(re) => {
if let ty::RegionKind::ReBound(ty::INNERMOST, bv) = re.kind() {
if let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
re.kind()
{
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
return None;
}
}
ty::GenericArgKind::Type(ty) => {
if let ty::Bound(ty::INNERMOST, bv) = *ty.kind() {
if let ty::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) = *ty.kind() {
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
return None;
}
}
ty::GenericArgKind::Const(ct) => {
if let ty::ConstKind::Bound(ty::INNERMOST, bv) = ct.kind() {
if let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(ty::INNERMOST), bv) =
ct.kind()
{
mapping.insert(bv.var, tcx.mk_param_from_def(param))
} else {
return None;
Expand Down Expand Up @@ -253,7 +257,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> {
return ty;
}

if let ty::Bound(binder, old_bound) = *ty.kind()
if let ty::Bound(ty::BoundVarIndexKind::Bound(binder), old_bound) = *ty.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) {
Expand All @@ -279,7 +283,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> {
}

fn fold_region(&mut self, re: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReBound(binder, old_bound) = re.kind()
if let ty::ReBound(ty::BoundVarIndexKind::Bound(binder), old_bound) = re.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) {
Expand Down Expand Up @@ -307,7 +311,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for MapAndCompressBoundVars<'tcx> {
return ct;
}

if let ty::ConstKind::Bound(binder, old_bound) = ct.kind()
if let ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(binder), old_bound) = ct.kind()
&& self.binder == binder
{
let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) {
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -915,7 +915,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't
ty::Param(param) => {
self.params.insert(param.index);
}
ty::Bound(db, bt) if *db >= self.depth => {
ty::Bound(ty::BoundVarIndexKind::Bound(db), bt) if *db >= self.depth => {
self.vars.insert(match bt.kind {
ty::BoundTyKind::Param(def_id) => def_id,
ty::BoundTyKind::Anon => {
Expand All @@ -938,7 +938,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't
ty::ReEarlyParam(param) => {
self.params.insert(param.index);
}
ty::ReBound(db, br) if db >= self.depth => {
ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.depth => {
self.vars.insert(match br.kind {
ty::BoundRegionKind::Named(def_id) => def_id,
ty::BoundRegionKind::Anon | ty::BoundRegionKind::ClosureEnv => {
Expand All @@ -961,7 +961,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for GenericParamAndBoundVarCollector<'_, 't
ty::ConstKind::Param(param) => {
self.params.insert(param.index);
}
ty::ConstKind::Bound(db, _) if db >= self.depth => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(db), _) if db >= self.depth => {
let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var");
return ControlFlow::Break(guar);
}
Expand Down
53 changes: 16 additions & 37 deletions compiler/rustc_infer/src/infer/canonical/canonicalizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -303,33 +303,19 @@ struct Canonicalizer<'cx, 'tcx> {
sub_root_lookup_table: SsoHashMap<ty::TyVid, usize>,
canonicalize_mode: &'cx dyn CanonicalizeMode,
needs_canonical_flags: TypeFlags,

binder_index: ty::DebruijnIndex,
}

impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
where
T: TypeFoldable<TyCtxt<'tcx>>,
{
self.binder_index.shift_in(1);
let t = t.super_fold_with(self);
self.binder_index.shift_out(1);
t
}

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match r.kind() {
ty::ReBound(index, ..) => {
if index >= self.binder_index {
bug!("escaping late-bound region during canonicalization");
} else {
r
}
ty::ReBound(ty::BoundVarIndexKind::Bound(_), ..) => r,

ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
bug!("canonicalized bound var found during canonicalization");
}

ty::ReStatic
Expand Down Expand Up @@ -403,12 +389,10 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
self.canonicalize_ty_var(CanonicalVarKind::PlaceholderTy(placeholder), t)
}

ty::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
bug!("escaping bound type during canonicalization")
} else {
t
}
ty::Bound(ty::BoundVarIndexKind::Bound(_), _) => t,

ty::Bound(ty::BoundVarIndexKind::Canonical, _) => {
bug!("canonicalized bound var found during canonicalization");
}

ty::Closure(..)
Expand Down Expand Up @@ -479,12 +463,11 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, 'tcx> {
ty::ConstKind::Infer(InferConst::Fresh(_)) => {
bug!("encountered a fresh const during canonicalization")
}
ty::ConstKind::Bound(debruijn, _) => {
if debruijn >= self.binder_index {
bug!("escaping bound const during canonicalization")
} else {
return ct;
}
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(_), _) => {
return ct;
}
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, _) => {
bug!("canonicalized bound var found during canonicalization");
}
ty::ConstKind::Placeholder(placeholder) => {
return self
Expand Down Expand Up @@ -569,7 +552,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
query_state,
indices: FxHashMap::default(),
sub_root_lookup_table: Default::default(),
binder_index: ty::INNERMOST,
};
if canonicalizer.query_state.var_values.spilled() {
canonicalizer.indices = canonicalizer
Expand Down Expand Up @@ -751,8 +733,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
r: ty::Region<'tcx>,
) -> ty::Region<'tcx> {
let var = self.canonical_var(var_kind, r.into());
let br = ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon };
ty::Region::new_bound(self.cx(), self.binder_index, br)
ty::Region::new_canonical_bound(self.cx(), var)
}

/// Given a type variable `ty_var` of the given kind, first check
Expand All @@ -766,8 +747,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
) -> Ty<'tcx> {
debug_assert!(!self.infcx.is_some_and(|infcx| ty_var != infcx.shallow_resolve(ty_var)));
let var = self.canonical_var(var_kind, ty_var.into());
let bt = ty::BoundTy { var, kind: ty::BoundTyKind::Anon };
Ty::new_bound(self.tcx, self.binder_index, bt)
Ty::new_canonical_bound(self.tcx, var)
}

/// Given a type variable `const_var` of the given kind, first check
Expand All @@ -783,7 +763,6 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
!self.infcx.is_some_and(|infcx| ct_var != infcx.shallow_resolve_const(ct_var))
);
let var = self.canonical_var(var_kind, ct_var.into());
let bc = ty::BoundConst { var };
ty::Const::new_bound(self.tcx, self.binder_index, bc)
ty::Const::new_canonical_bound(self.tcx, var)
}
}
74 changes: 18 additions & 56 deletions compiler/rustc_infer/src/infer/canonical/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use rustc_middle::ty::{
self, DelayedMap, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable,
TypeVisitableExt, TypeVisitor,
};
use rustc_type_ir::TypeVisitable;
use rustc_type_ir::{TypeFlags, TypeVisitable};

use crate::infer::canonical::{Canonical, CanonicalVarValues};

Expand Down Expand Up @@ -66,7 +66,6 @@ where

value.fold_with(&mut CanonicalInstantiator {
tcx,
current_index: ty::INNERMOST,
var_values: var_values.var_values,
cache: Default::default(),
})
Expand All @@ -79,42 +78,29 @@ struct CanonicalInstantiator<'tcx> {
// The values that the bound vars are are being instantiated with.
var_values: ty::GenericArgsRef<'tcx>,

/// As with `BoundVarReplacer`, represents the index of a binder *just outside*
/// the ones we have visited.
current_index: ty::DebruijnIndex,

// Instantiation is a pure function of `DebruijnIndex` and `Ty`.
cache: DelayedMap<(ty::DebruijnIndex, Ty<'tcx>), Ty<'tcx>>,
// Because we use `ty::BoundVarIndexKind::Canonical`, we can cache
// based only on the entire ty, not worrying about a `DebruijnIndex`
cache: DelayedMap<Ty<'tcx>, Ty<'tcx>>,
}

impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'tcx> {
fn cx(&self) -> TyCtxt<'tcx> {
self.tcx
}

fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
&mut self,
t: ty::Binder<'tcx, T>,
) -> ty::Binder<'tcx, T> {
self.current_index.shift_in(1);
let t = t.super_fold_with(self);
self.current_index.shift_out(1);
t
}

fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
match *t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.current_index => {
ty::Bound(ty::BoundVarIndexKind::Canonical, bound_ty) => {
self.var_values[bound_ty.var.as_usize()].expect_ty()
}
_ => {
if !t.has_vars_bound_at_or_above(self.current_index) {
if !t.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
t
} else if let Some(&t) = self.cache.get(&(self.current_index, t)) {
} else if let Some(&t) = self.cache.get(&t) {
t
} else {
let res = t.super_fold_with(self);
assert!(self.cache.insert((self.current_index, t), res));
assert!(self.cache.insert(t, res));
res
}
}
Expand All @@ -123,7 +109,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'tcx> {

fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
match r.kind() {
ty::ReBound(debruijn, br) if debruijn == self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Canonical, br) => {
self.var_values[br.var.as_usize()].expect_region()
}
_ => r,
Expand All @@ -132,30 +118,22 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'tcx> {

fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
match ct.kind() {
ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.current_index => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, bound_const) => {
self.var_values[bound_const.var.as_usize()].expect_const()
}
_ => ct.super_fold_with(self),
}
}

fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
if p.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) { p.super_fold_with(self) } else { p }
}

fn fold_clauses(&mut self, c: ty::Clauses<'tcx>) -> ty::Clauses<'tcx> {
if !c.has_vars_bound_at_or_above(self.current_index) {
if !c.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
return c;
}

// Since instantiation is a function of `DebruijnIndex`, we don't want
// to have to cache more copies of clauses when we're inside of binders.
// Since we currently expect to only have clauses in the outermost
// debruijn index, we just fold if we're inside of a binder.
if self.current_index > ty::INNERMOST {
return c.super_fold_with(self);
}

// Our cache key is `(clauses, var_values)`, but we also don't care about
// var values that aren't named in the clauses, since they can change without
// affecting the output. Since `ParamEnv`s are cached first, we compute the
Expand Down Expand Up @@ -185,45 +163,29 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'tcx> {
fn highest_var_in_clauses<'tcx>(c: ty::Clauses<'tcx>) -> usize {
struct HighestVarInClauses {
max_var: usize,
current_index: ty::DebruijnIndex,
}
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for HighestVarInClauses {
fn visit_binder<T: TypeVisitable<TyCtxt<'tcx>>>(
&mut self,
t: &ty::Binder<'tcx, T>,
) -> Self::Result {
self.current_index.shift_in(1);
let t = t.super_visit_with(self);
self.current_index.shift_out(1);
t
}
fn visit_ty(&mut self, t: Ty<'tcx>) {
if let ty::Bound(debruijn, bound_ty) = *t.kind()
&& debruijn == self.current_index
{
if let ty::Bound(ty::BoundVarIndexKind::Canonical, bound_ty) = *t.kind() {
self.max_var = self.max_var.max(bound_ty.var.as_usize());
} else if t.has_vars_bound_at_or_above(self.current_index) {
} else if t.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
t.super_visit_with(self);
}
}
fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReBound(debruijn, bound_region) = r.kind()
&& debruijn == self.current_index
{
if let ty::ReBound(ty::BoundVarIndexKind::Canonical, bound_region) = r.kind() {
self.max_var = self.max_var.max(bound_region.var.as_usize());
}
}
fn visit_const(&mut self, ct: ty::Const<'tcx>) {
if let ty::ConstKind::Bound(debruijn, bound_const) = ct.kind()
&& debruijn == self.current_index
{
if let ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, bound_const) = ct.kind() {
self.max_var = self.max_var.max(bound_const.var.as_usize());
} else if ct.has_vars_bound_at_or_above(self.current_index) {
} else if ct.has_type_flags(TypeFlags::HAS_CANONICAL_BOUND) {
ct.super_visit_with(self);
}
}
}
let mut visitor = HighestVarInClauses { max_var: 0, current_index: ty::INNERMOST };
let mut visitor = HighestVarInClauses { max_var: 0 };
c.visit_with(&mut visitor);
visitor.max_var
}
Loading
Loading