Split Bound into Canonical and Bound

This commit is contained in:
jackh726
2025-09-28 23:04:55 +00:00
committed by Jack Huey
parent 6f34f4ee07
commit d1bbd39c59
45 changed files with 391 additions and 247 deletions

View File

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

View File

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

View File

@@ -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 => {
@@ -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 => {
@@ -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);
}

View File

@@ -303,8 +303,6 @@ 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> {
@@ -312,24 +310,12 @@ impl<'cx, 'tcx> TypeFolder<TyCtxt<'tcx>> for Canonicalizer<'cx, '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
@@ -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(..)
@@ -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 {
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
@@ -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
@@ -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
@@ -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
@@ -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)
}
}

View File

@@ -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};
@@ -66,7 +66,6 @@ where
value.fold_with(&mut CanonicalInstantiator {
tcx,
current_index: ty::INNERMOST,
var_values: var_values.var_values,
cache: Default::default(),
})
@@ -79,12 +78,9 @@ 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> {
@@ -92,29 +88,19 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'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
}
}
@@ -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,
@@ -132,7 +118,7 @@ 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),
@@ -140,22 +126,14 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for CanonicalInstantiator<'tcx> {
}
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
@@ -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
}

View File

@@ -422,28 +422,28 @@ impl<'tcx> InferCtxt<'tcx> {
// and only use it for placeholders. We need to handle the
// `sub_root` of type inference variables which would make this
// more involved. They are also a lot rarer than region variables.
if let ty::Bound(debruijn, b) = *result_value.kind()
if let ty::Bound(index_kind, b) = *result_value.kind()
&& !matches!(
query_response.variables[b.var.as_usize()],
CanonicalVarKind::Ty { .. }
)
{
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(debruijn, ty::INNERMOST);
// We only allow a `Canonical` index in generic parameters.
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[b.var] = Some(*original_value);
}
}
GenericArgKind::Lifetime(result_value) => {
if let ty::ReBound(debruijn, b) = result_value.kind() {
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ReBound(index_kind, b) = result_value.kind() {
// We only allow a `Canonical` index in generic parameters.
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[b.var] = Some(*original_value);
}
}
GenericArgKind::Const(result_value) => {
if let ty::ConstKind::Bound(debruijn, b) = result_value.kind() {
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ConstKind::Bound(index_kind, b) = result_value.kind() {
// We only allow a `Canonical` index in generic parameters.
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[b.var] = Some(*original_value);
}
}

View File

@@ -44,8 +44,8 @@ pub fn extract_verify_if_eq<'tcx>(
let verify_if_eq = verify_if_eq_b.skip_binder();
m.relate(verify_if_eq.ty, test_ty).ok()?;
if let ty::RegionKind::ReBound(depth, br) = verify_if_eq.bound.kind() {
assert!(depth == ty::INNERMOST);
if let ty::RegionKind::ReBound(index_kind, br) = verify_if_eq.bound.kind() {
assert!(matches!(index_kind, ty::BoundVarIndexKind::Bound(ty::INNERMOST)));
match m.map.get(&br) {
Some(&r) => Some(r),
None => {
@@ -156,7 +156,7 @@ impl<'tcx> TypeRelation<TyCtxt<'tcx>> for MatchAgainstHigherRankedOutlives<'tcx>
pattern: ty::Region<'tcx>,
value: ty::Region<'tcx>,
) -> RelateResult<'tcx, ty::Region<'tcx>> {
if let ty::RegionKind::ReBound(depth, br) = pattern.kind()
if let ty::RegionKind::ReBound(ty::BoundVarIndexKind::Bound(depth), br) = pattern.kind()
&& depth == self.pattern_depth
{
self.bind(br, value)

View File

@@ -95,7 +95,15 @@ impl<'tcx> Const<'tcx> {
debruijn: ty::DebruijnIndex,
bound_const: ty::BoundConst,
) -> Const<'tcx> {
Const::new(tcx, ty::ConstKind::Bound(debruijn, bound_const))
Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const))
}
#[inline]
pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> {
Const::new(
tcx,
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst { var }),
)
}
#[inline]
@@ -180,6 +188,10 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
Const::new_bound(tcx, debruijn, ty::BoundConst { var })
}
fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
Const::new_canonical_bound(tcx, var)
}
fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Self {
Const::new_placeholder(tcx, placeholder)
}

View File

@@ -1110,6 +1110,15 @@ const NUM_PREINTERNED_FRESH_TYS: u32 = 20;
const NUM_PREINTERNED_FRESH_INT_TYS: u32 = 3;
const NUM_PREINTERNED_FRESH_FLOAT_TYS: u32 = 3;
const NUM_PREINTERNED_ANON_BOUND_TYS_I: u32 = 3;
// From general profiling of the *max vars during canonicalization* of a value:
// - about 90% of the time, there are no canonical vars
// - about 9% of the time, there is only one canonical var
// - there are rarely more than 3-5 canonical vars (with exceptions in particularly pathological cases)
// This may not match the number of bound vars found in `for`s.
// Given that this is all heap interned, it seems likely that interning fewer
// vars here won't make an appreciable difference. Though, if we were to inline the data (in an array),
// we may want to consider reducing the number for canonicalized vars down to 4 or so.
const NUM_PREINTERNED_ANON_BOUND_TYS_V: u32 = 20;
// This number may seem high, but it is reached in all but the smallest crates.
@@ -1160,9 +1169,14 @@ pub struct CommonTypes<'tcx> {
pub fresh_float_tys: Vec<Ty<'tcx>>,
/// Pre-interned values of the form:
/// `Bound(DebruijnIndex(i), BoundTy { var: v, kind: BoundTyKind::Anon})`
/// `Bound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundTy { var: v, kind: BoundTyKind::Anon})`
/// for small values of `i` and `v`.
pub anon_bound_tys: Vec<Vec<Ty<'tcx>>>,
// Pre-interned values of the form:
// `Bound(BoundVarIndexKind::Canonical, BoundTy { var: v, kind: BoundTyKind::Anon })`
// for small values of `v`.
pub anon_canonical_bound_tys: Vec<Ty<'tcx>>,
}
pub struct CommonLifetimes<'tcx> {
@@ -1176,9 +1190,14 @@ pub struct CommonLifetimes<'tcx> {
pub re_vars: Vec<Region<'tcx>>,
/// Pre-interned values of the form:
/// `ReBound(DebruijnIndex(i), BoundRegion { var: v, kind: BoundRegionKind::Anon })`
/// `ReBound(BoundVarIndexKind::Bound(DebruijnIndex(i)), BoundRegion { var: v, kind: BoundRegionKind::Anon })`
/// for small values of `i` and `v`.
pub anon_re_bounds: Vec<Vec<Region<'tcx>>>,
// Pre-interned values of the form:
// `ReBound(BoundVarIndexKind::Canonical, BoundRegion { var: v, kind: BoundRegionKind::Anon })`
// for small values of `v`.
pub anon_re_canonical_bounds: Vec<Region<'tcx>>,
}
pub struct CommonConsts<'tcx> {
@@ -1211,7 +1230,7 @@ impl<'tcx> CommonTypes<'tcx> {
(0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
.map(|v| {
mk(ty::Bound(
ty::DebruijnIndex::from(i),
ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon },
))
})
@@ -1219,6 +1238,15 @@ impl<'tcx> CommonTypes<'tcx> {
})
.collect();
let anon_canonical_bound_tys = (0..NUM_PREINTERNED_ANON_BOUND_TYS_V)
.map(|v| {
mk(ty::Bound(
ty::BoundVarIndexKind::Canonical,
ty::BoundTy { var: ty::BoundVar::from(v), kind: ty::BoundTyKind::Anon },
))
})
.collect();
CommonTypes {
unit: mk(Tuple(List::empty())),
bool: mk(Bool),
@@ -1250,6 +1278,7 @@ impl<'tcx> CommonTypes<'tcx> {
fresh_int_tys,
fresh_float_tys,
anon_bound_tys,
anon_canonical_bound_tys,
}
}
}
@@ -1270,7 +1299,7 @@ impl<'tcx> CommonLifetimes<'tcx> {
(0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
.map(|v| {
mk(ty::ReBound(
ty::DebruijnIndex::from(i),
ty::BoundVarIndexKind::Bound(ty::DebruijnIndex::from(i)),
ty::BoundRegion {
var: ty::BoundVar::from(v),
kind: ty::BoundRegionKind::Anon,
@@ -1281,11 +1310,21 @@ impl<'tcx> CommonLifetimes<'tcx> {
})
.collect();
let anon_re_canonical_bounds = (0..NUM_PREINTERNED_ANON_RE_BOUNDS_V)
.map(|v| {
mk(ty::ReBound(
ty::BoundVarIndexKind::Canonical,
ty::BoundRegion { var: ty::BoundVar::from(v), kind: ty::BoundRegionKind::Anon },
))
})
.collect();
CommonLifetimes {
re_static: mk(ty::ReStatic),
re_erased: mk(ty::ReErased),
re_vars,
anon_re_bounds,
anon_re_canonical_bounds,
}
}
}

View File

@@ -125,7 +125,9 @@ where
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::Bound(debruijn), bound_ty)
if debruijn == self.current_index =>
{
let ty = self.delegate.replace_ty(bound_ty);
debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST));
ty::shift_vars(self.tcx, ty, self.current_index.as_u32())
@@ -146,9 +148,11 @@ where
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::Bound(debruijn), br)
if debruijn == self.current_index =>
{
let region = self.delegate.replace_region(br);
if let ty::ReBound(debruijn1, br) = region.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn1), br) = region.kind() {
// If the callback returns a bound region,
// that region should always use the INNERMOST
// debruijn index. Then we adjust it to the
@@ -165,7 +169,9 @@ where
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::Bound(debruijn), bound_const)
if debruijn == self.current_index =>
{
let ct = self.delegate.replace_const(bound_const);
debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
ty::shift_vars(self.tcx, ct, self.current_index.as_u32())

View File

@@ -2664,7 +2664,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
let name = &mut self.name;
let region = match r.kind() {
ty::ReBound(db, br) if db >= self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(db), br) if db >= self.current_index => {
*self.region_map.entry(br).or_insert_with(|| name(Some(db), self.current_index, br))
}
ty::RePlaceholder(ty::PlaceholderRegion {
@@ -2687,7 +2687,7 @@ impl<'a, 'tcx> ty::TypeFolder<TyCtxt<'tcx>> for RegionFolder<'a, 'tcx> {
}
_ => return r,
};
if let ty::ReBound(debruijn1, br) = region.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn1), br) = region.kind() {
assert_eq!(debruijn1, ty::INNERMOST);
ty::Region::new_bound(self.tcx, self.current_index, br)
} else {

View File

@@ -31,7 +31,7 @@ impl<'tcx> rustc_type_ir::Flags for Region<'tcx> {
fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
match self.kind() {
ty::ReBound(debruijn, _) => debruijn.shifted_in(1),
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) => debruijn.shifted_in(1),
_ => ty::INNERMOST,
}
}
@@ -59,7 +59,20 @@ impl<'tcx> Region<'tcx> {
{
re
} else {
tcx.intern_region(ty::ReBound(debruijn, bound_region))
tcx.intern_region(ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), bound_region))
}
}
#[inline]
pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Region<'tcx> {
// Use a pre-interned one when possible.
if let Some(re) = tcx.lifetimes.anon_re_canonical_bounds.get(var.as_usize()).copied() {
re
} else {
tcx.intern_region(ty::ReBound(
ty::BoundVarIndexKind::Canonical,
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
))
}
}
@@ -122,7 +135,12 @@ impl<'tcx> Region<'tcx> {
pub fn new_from_kind(tcx: TyCtxt<'tcx>, kind: RegionKind<'tcx>) -> Region<'tcx> {
match kind {
ty::ReEarlyParam(region) => Region::new_early_param(tcx, region),
ty::ReBound(debruijn, region) => Region::new_bound(tcx, debruijn, region),
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), region) => {
Region::new_bound(tcx, debruijn, region)
}
ty::ReBound(ty::BoundVarIndexKind::Canonical, region) => {
Region::new_canonical_bound(tcx, region.var)
}
ty::ReLateParam(ty::LateParamRegion { scope, kind }) => {
Region::new_late_param(tcx, scope, kind)
}
@@ -148,6 +166,10 @@ impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon })
}
fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self {
Region::new_canonical_bound(tcx, var)
}
fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Self {
Region::new_placeholder(tcx, placeholder)
}
@@ -223,7 +245,7 @@ impl<'tcx> Region<'tcx> {
#[inline]
pub fn bound_at_or_above_binder(self, index: ty::DebruijnIndex) -> bool {
match self.kind() {
ty::ReBound(debruijn, _) => debruijn >= index,
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) => debruijn >= index,
_ => false,
}
}
@@ -254,7 +276,11 @@ impl<'tcx> Region<'tcx> {
ty::ReStatic => {
flags = flags | TypeFlags::HAS_FREE_REGIONS;
}
ty::ReBound(..) => {
ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
flags = flags | TypeFlags::HAS_RE_BOUND;
flags = flags | TypeFlags::HAS_CANONICAL_BOUND;
}
ty::ReBound(ty::BoundVarIndexKind::Bound(..), _) => {
flags = flags | TypeFlags::HAS_RE_BOUND;
}
ty::ReErased => {

View File

@@ -487,7 +487,23 @@ impl<'tcx> Ty<'tcx> {
{
ty
} else {
Ty::new(tcx, Bound(index, bound_ty))
Ty::new(tcx, Bound(ty::BoundVarIndexKind::Bound(index), bound_ty))
}
}
#[inline]
pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: BoundVar) -> Ty<'tcx> {
// Use a pre-interned one when possible.
if let Some(ty) = tcx.types.anon_canonical_bound_tys.get(var.as_usize()).copied() {
ty
} else {
Ty::new(
tcx,
Bound(
ty::BoundVarIndexKind::Canonical,
ty::BoundTy { var, kind: ty::BoundTyKind::Anon },
),
)
}
}
@@ -952,6 +968,10 @@ impl<'tcx> rustc_type_ir::inherent::Ty<TyCtxt<'tcx>> for Ty<'tcx> {
Ty::new_bound(tcx, debruijn, ty::BoundTy { var, kind: ty::BoundTyKind::Anon })
}
fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Self {
Ty::new_canonical_bound(tcx, var)
}
fn new_alias(
interner: TyCtxt<'tcx>,
kind: ty::AliasTyKind,

View File

@@ -798,8 +798,8 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
match arg.kind() {
GenericArgKind::Type(ty) => match ty.kind() {
ty::Bound(debruijn, b) => {
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(*debruijn, ty::INNERMOST);
// We only allow a `ty::BoundVarIndexKind::Canonical` index in generic parameters.
assert_eq!(*debruijn, ty::BoundVarIndexKind::Canonical);
cvar == b.var
}
_ => false,
@@ -807,8 +807,8 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
GenericArgKind::Lifetime(r) => match r.kind() {
ty::ReBound(debruijn, b) => {
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(debruijn, ty::INNERMOST);
// We only allow a `ty::BoundVarIndexKind::Canonical` index in generic parameters.
assert_eq!(debruijn, ty::BoundVarIndexKind::Canonical);
cvar == b.var
}
_ => false,
@@ -816,8 +816,8 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> {
GenericArgKind::Const(ct) => match ct.kind() {
ty::ConstKind::Bound(debruijn, b) => {
// We only allow a `ty::INNERMOST` index in generic parameters.
assert_eq!(debruijn, ty::INNERMOST);
// We only allow a `ty::BoundVarIndexKind::Canonical` index in generic parameters.
assert_eq!(debruijn, ty::BoundVarIndexKind::Canonical);
cvar == b.var
}
_ => false,

View File

@@ -78,7 +78,9 @@ impl<'tcx> TyCtxt<'tcx> {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
match r.kind() {
ty::ReBound(debruijn, _) if debruijn < self.outer_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn < self.outer_index =>
{
ControlFlow::Continue(())
}
_ => {
@@ -205,7 +207,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for LateBoundRegionsCollector {
}
fn visit_region(&mut self, r: ty::Region<'tcx>) {
if let ty::ReBound(debruijn, br) = r.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) = r.kind() {
if debruijn == self.current_index {
self.regions.insert(br.kind);
}

View File

@@ -74,12 +74,10 @@ pub(super) struct Canonicalizer<'a, D: SolverDelegate<Interner = I>, I: Interner
/// we set the `sub_root` of the second variable to the position of the first.
/// Otherwise the `sub_root` of each type variable is just its own position.
sub_root_lookup_table: HashMap<ty::TyVid, usize>,
binder_index: ty::DebruijnIndex,
/// We only use the debruijn index during lookup. We don't need to
/// track the `variables` as each generic arg only results in a single
/// bound variable regardless of how many times it is encountered.
cache: HashMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
/// We can simply cache based on the ty itself, because we use
/// `ty::BoundVarIndexKind::Canonical`.
cache: HashMap<I::Ty, I::Ty>,
}
impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
@@ -97,7 +95,6 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
@@ -141,12 +138,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
let param_env = param_env.fold_with(&mut env_canonicalizer);
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
CanonicalParamEnvCacheEntry {
param_env,
@@ -175,12 +170,10 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table: Default::default(),
sub_root_lookup_table: Default::default(),
var_kinds: Vec::new(),
binder_index: ty::INNERMOST,
cache: Default::default(),
};
let param_env = param_env.fold_with(&mut env_canonicalizer);
debug_assert_eq!(env_canonicalizer.binder_index, ty::INNERMOST);
debug_assert!(env_canonicalizer.sub_root_lookup_table.is_empty());
(param_env, env_canonicalizer.variable_lookup_table, env_canonicalizer.var_kinds)
}
@@ -212,7 +205,6 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
variable_lookup_table,
sub_root_lookup_table: Default::default(),
var_kinds,
binder_index: ty::INNERMOST,
// We do not reuse the cache as it may contain entries whose canonicalized
// value contains `'static`. While we could alternatively handle this by
@@ -409,7 +401,7 @@ impl<'a, D: SolverDelegate<Interner = I>, I: Interner> Canonicalizer<'a, D, I> {
let var = self.get_or_insert_bound_var(t, kind);
Ty::new_anon_bound(self.cx(), self.binder_index, var)
Ty::new_canonical_bound(self.cx(), var)
}
}
@@ -418,16 +410,6 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
self.delegate.cx()
}
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
where
T: TypeFoldable<I>,
{
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: I::Region) -> I::Region {
let kind = match r.kind() {
ty::ReBound(..) => return r,
@@ -491,15 +473,15 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
let var = self.get_or_insert_bound_var(r, kind);
Region::new_anon_bound(self.cx(), self.binder_index, var)
Region::new_canonical_bound(self.cx(), var)
}
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
if let Some(&ty) = self.cache.get(&(self.binder_index, t)) {
if let Some(&ty) = self.cache.get(&t) {
ty
} else {
let res = self.inner_fold_ty(t);
let old = self.cache.insert((self.binder_index, t), res);
let old = self.cache.insert(t, res);
assert_eq!(old, None);
res
}
@@ -552,7 +534,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> TypeFolder<I> for Canonicaliz
let var = self.get_or_insert_bound_var(c, kind);
Const::new_anon_bound(self.cx(), self.binder_index, var)
Const::new_canonical_bound(self.cx(), var)
}
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {

View File

@@ -167,25 +167,25 @@ where
// and only use it for placeholders. We need to handle the
// `sub_root` of type inference variables which would make this
// more involved. They are also a lot rarer than region variables.
if let ty::Bound(debruijn, b) = t.kind()
if let ty::Bound(index_kind, b) = t.kind()
&& !matches!(
response.variables.get(b.var().as_usize()).unwrap(),
CanonicalVarKind::Ty { .. }
)
{
assert_eq!(debruijn, ty::INNERMOST);
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[b.var()] = Some(*original_value);
}
}
ty::GenericArgKind::Lifetime(r) => {
if let ty::ReBound(debruijn, br) = r.kind() {
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ReBound(index_kind, br) = r.kind() {
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[br.var()] = Some(*original_value);
}
}
ty::GenericArgKind::Const(c) => {
if let ty::ConstKind::Bound(debruijn, bv) = c.kind() {
assert_eq!(debruijn, ty::INNERMOST);
if let ty::ConstKind::Bound(index_kind, bv) = c.kind() {
assert!(matches!(index_kind, ty::BoundVarIndexKind::Canonical));
opt_values[bv.var()] = Some(*original_value);
}
}

View File

@@ -90,7 +90,7 @@ where
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(debruijn, _)
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize()
>= self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -99,7 +99,9 @@ where
self.universe_indices
);
}
ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, br);
self.mapped_regions.insert(p, br);
@@ -111,7 +113,7 @@ where
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
match t.kind() {
ty::Bound(debruijn, _)
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize() + 1
> self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -120,7 +122,9 @@ where
self.universe_indices
);
}
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, bound_ty);
self.mapped_types.insert(p, bound_ty);
@@ -133,7 +137,7 @@ where
fn fold_const(&mut self, ct: I::Const) -> I::Const {
match ct.kind() {
ty::ConstKind::Bound(debruijn, _)
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn.as_usize() + 1
> self.current_index.as_usize() + self.universe_indices.len() =>
{
@@ -142,7 +146,9 @@ where
self.universe_indices
);
}
ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)
if debruijn >= self.current_index =>
{
let universe = self.universe_for(debruijn);
let p = PlaceholderLike::new(universe, bound_const);
self.mapped_consts.insert(p, bound_const);

View File

@@ -453,7 +453,10 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
TyKind::Alias(alias_kind.stable(tables, cx), alias_ty.stable(tables, cx))
}
ty::Param(param_ty) => TyKind::Param(param_ty.stable(tables, cx)),
ty::Bound(debruijn_idx, bound_ty) => {
ty::Bound(ty::BoundVarIndexKind::Canonical, _) => {
unreachable!()
}
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn_idx), bound_ty) => {
TyKind::Bound(debruijn_idx.as_usize(), bound_ty.stable(tables, cx))
}
ty::CoroutineWitness(def_id, args) => TyKind::RigidTy(RigidTy::CoroutineWitness(
@@ -907,7 +910,7 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
index: early_reg.index,
name: early_reg.name.to_string(),
}),
ty::ReBound(db_index, bound_reg) => RegionKind::ReBound(
ty::ReBound(ty::BoundVarIndexKind::Bound(db_index), bound_reg) => RegionKind::ReBound(
db_index.as_u32(),
BoundRegion {
var: bound_reg.var.as_u32(),

View File

@@ -287,7 +287,7 @@ fn encode_region<'tcx>(region: Region<'tcx>, dict: &mut FxHashMap<DictKey<'tcx>,
// u6region[I[<region-disambiguator>][<region-index>]E] as vendor extended type
let mut s = String::new();
match region.kind() {
RegionKind::ReBound(debruijn, r) => {
RegionKind::ReBound(ty::BoundVarIndexKind::Bound(debruijn), r) => {
s.push_str("u6regionI");
// Debruijn index, which identifies the binder, as region disambiguator
let num = debruijn.index() as u64;
@@ -303,7 +303,8 @@ fn encode_region<'tcx>(region: Region<'tcx>, dict: &mut FxHashMap<DictKey<'tcx>,
s.push_str("u6region");
compress(dict, DictKey::Region(region), &mut s);
}
RegionKind::ReEarlyParam(..)
RegionKind::ReBound(ty::BoundVarIndexKind::Canonical, _)
| RegionKind::ReEarlyParam(..)
| RegionKind::ReLateParam(..)
| RegionKind::ReStatic
| RegionKind::ReError(_)

View File

@@ -412,7 +412,10 @@ impl<'tcx> Printer<'tcx> for V0SymbolMangler<'tcx> {
// Bound lifetimes use indices starting at 1,
// see `BinderLevel` for more details.
ty::ReBound(debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon }) => {
ty::ReBound(
ty::BoundVarIndexKind::Bound(debruijn),
ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon },
) => {
let binder = &self.binders[self.binders.len() - 1 - debruijn.index()];
let depth = binder.lifetime_depths.start + var.as_u32();

View File

@@ -830,7 +830,7 @@ impl<'tcx> TypeFolder<TyCtxt<'tcx>> for EraseEscapingBoundRegions<'tcx> {
}
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
if let ty::ReBound(debruijn, _) = r.kind()
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind()
&& debruijn < self.binder
{
r

View File

@@ -145,7 +145,9 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for MaxEscapingBoundVarVisitor {
#[inline]
fn visit_region(&mut self, r: ty::Region<'tcx>) {
match r.kind() {
ty::ReBound(debruijn, _) if debruijn > self.outer_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn > self.outer_index =>
{
self.escaping =
self.escaping.max(debruijn.as_usize() - self.outer_index.as_usize());
}

View File

@@ -235,7 +235,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
// bounds of the RPITIT. Shift these binders back out when
// constructing the top-level projection predicate.
let shifted_alias_ty = fold_regions(self.tcx, unshifted_alias_ty, |re, depth| {
if let ty::ReBound(index, bv) = re.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(index), bv) = re.kind() {
if depth != ty::INNERMOST {
return ty::Region::new_error_with_message(
self.tcx,

View File

@@ -4,6 +4,7 @@ use std::ops::{ControlFlow, Deref};
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
use tracing::instrument;
use crate::data_structures::SsoHashSet;
@@ -11,7 +12,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldabl
use crate::inherent::*;
use crate::lift::Lift;
use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
use crate::{self as ty, Interner};
use crate::{self as ty, DebruijnIndex, Interner};
/// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the
/// compiler's representation for things like `for<'a> Fn(&'a isize)`
@@ -299,7 +300,9 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
return ControlFlow::Break(());
}
match t.kind() {
ty::Bound(debruijn, bound_ty) if debruijn == self.binder_index => {
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
if debruijn == self.binder_index =>
{
let idx = bound_ty.var().as_usize();
if self.bound_vars.len() <= idx {
panic!("Not enough bound vars: {:?} not found in {:?}", t, self.bound_vars);
@@ -317,7 +320,9 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
return ControlFlow::Break(());
}
match c.kind() {
ty::ConstKind::Bound(debruijn, bound_const) if debruijn == self.binder_index => {
ty::ConstKind::Bound(debruijn, bound_const)
if debruijn == ty::BoundVarIndexKind::Bound(self.binder_index) =>
{
let idx = bound_const.var().as_usize();
if self.bound_vars.len() <= idx {
panic!("Not enough bound vars: {:?} not found in {:?}", c, self.bound_vars);
@@ -332,7 +337,7 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
fn visit_region(&mut self, r: I::Region) -> Self::Result {
match r.kind() {
ty::ReBound(index, br) if index == self.binder_index => {
ty::ReBound(index, br) if index == ty::BoundVarIndexKind::Bound(self.binder_index) => {
let idx = br.var().as_usize();
if self.bound_vars.len() <= idx {
panic!("Not enough bound vars: {:?} not found in {:?}", r, self.bound_vars);
@@ -913,3 +918,33 @@ impl<'a, I: Interner> ArgFolder<'a, I> {
}
}
}
/// Okay, we do something fun for `Bound` types/regions/consts:
/// Specifically, we distinguish between *canonically* bound things and
/// `for<>` bound things. And, really, it comes down to caching during
/// canonicalization and instantiation.
///
/// To understand why we do this, imagine we have a type `(T, for<> fn(T))`.
/// If we just tracked canonically bound types with a `DebruijnIndex` (as we
/// used to), then the canonicalized type would be something like
/// `for<0> (^0.0, for<> fn(^1.0))` and so we can't cache `T -> ^0.0`,
/// we have to also factor in binder level. (Of course, we don't cache that
/// exactly, but rather the entire enclosing type, but the point stands.)
///
/// Of course, this is okay because we don't ever nest canonicalization, so
/// `BoundVarIndexKind::Canonical` is unambiguous. We, alternatively, could
/// have some sentinel `DebruijinIndex`, but that just seems too scary.
///
/// This doesn't seem to have a huge perf swing either way, but in the next
/// solver, canonicalization is hot and there are some pathological cases where
/// this is needed (`post-mono-higher-ranked-hang`).
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
pub enum BoundVarIndexKind {
Bound(DebruijnIndex),
Canonical,
}

View File

@@ -230,13 +230,13 @@ impl<I: Interner> CanonicalVarValues<I> {
pub fn is_identity(&self) -> bool {
self.var_values.iter().enumerate().all(|(bv, arg)| match arg.kind() {
ty::GenericArgKind::Lifetime(r) => {
matches!(r.kind(), ty::ReBound(ty::INNERMOST, br) if br.var().as_usize() == bv)
matches!(r.kind(), ty::ReBound(ty::BoundVarIndexKind::Canonical, br) if br.var().as_usize() == bv)
}
ty::GenericArgKind::Type(ty) => {
matches!(ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var().as_usize() == bv)
matches!(ty.kind(), ty::Bound(ty::BoundVarIndexKind::Canonical, bt) if bt.var().as_usize() == bv)
}
ty::GenericArgKind::Const(ct) => {
matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.var().as_usize() == bv)
matches!(ct.kind(), ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, bc) if bc.var().as_usize() == bv)
}
})
}
@@ -246,21 +246,23 @@ impl<I: Interner> CanonicalVarValues<I> {
for arg in self.var_values.iter() {
match arg.kind() {
ty::GenericArgKind::Lifetime(r) => {
if matches!(r.kind(), ty::ReBound(ty::INNERMOST, br) if var == br.var()) {
if matches!(r.kind(), ty::ReBound(ty::BoundVarIndexKind::Canonical, br) if var == br.var())
{
var = var + 1;
} else {
// It's ok if this region var isn't an identity variable
}
}
ty::GenericArgKind::Type(ty) => {
if matches!(ty.kind(), ty::Bound(ty::INNERMOST, bt) if var == bt.var()) {
if matches!(ty.kind(), ty::Bound(ty::BoundVarIndexKind::Canonical, bt) if var == bt.var())
{
var = var + 1;
} else {
return false;
}
}
ty::GenericArgKind::Const(ct) => {
if matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if var == bc.var())
if matches!(ct.kind(), ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, bc) if var == bc.var())
{
var = var + 1;
} else {
@@ -284,16 +286,13 @@ impl<I: Interner> CanonicalVarValues<I> {
| CanonicalVarKind::Int
| CanonicalVarKind::Float
| CanonicalVarKind::PlaceholderTy(_) => {
Ty::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
Ty::new_canonical_bound(cx, ty::BoundVar::from_usize(i)).into()
}
CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
Region::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
Region::new_canonical_bound(cx, ty::BoundVar::from_usize(i)).into()
}
CanonicalVarKind::Const(_) | CanonicalVarKind::PlaceholderConst(_) => {
Const::new_anon_bound(cx, ty::INNERMOST, ty::BoundVar::from_usize(i))
.into()
Const::new_canonical_bound(cx, ty::BoundVar::from_usize(i)).into()
}
}
},

View File

@@ -7,7 +7,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use crate::{self as ty, DebruijnIndex, Interner};
use crate::{self as ty, BoundVarIndexKind, Interner};
/// Represents a constant in Rust.
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
@@ -23,7 +23,7 @@ pub enum ConstKind<I: Interner> {
Infer(InferConst),
/// Bound const variable, used only when preparing a trait query.
Bound(DebruijnIndex, I::BoundConst),
Bound(BoundVarIndexKind, I::BoundConst),
/// A placeholder const - universally quantified higher-ranked const.
Placeholder(I::PlaceholderConst),

View File

@@ -133,6 +133,9 @@ bitflags::bitflags! {
/// Does this type have any coroutines in it?
const HAS_TY_CORO = 1 << 24;
/// Does this have have a `Bound(BoundVarIndexKind::Canonical, _)`?
const HAS_CANONICAL_BOUND = 1 << 25;
}
}
@@ -254,7 +257,12 @@ impl<I: Interner> FlagComputation<I> {
self.add_args(args.as_slice());
}
ty::Bound(debruijn, _) => {
ty::Bound(ty::BoundVarIndexKind::Canonical, _) => {
self.add_flags(TypeFlags::HAS_TY_BOUND);
self.add_flags(TypeFlags::HAS_CANONICAL_BOUND);
}
ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) => {
self.add_bound_var(debruijn);
self.add_flags(TypeFlags::HAS_TY_BOUND);
}
@@ -434,7 +442,7 @@ impl<I: Interner> FlagComputation<I> {
fn add_region(&mut self, r: I::Region) {
self.add_flags(r.flags());
if let ty::ReBound(debruijn, _) = r.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind() {
self.add_bound_var(debruijn);
}
}
@@ -454,10 +462,14 @@ impl<I: Interner> FlagComputation<I> {
ty::InferConst::Fresh(_) => self.add_flags(TypeFlags::HAS_CT_FRESH),
ty::InferConst::Var(_) => self.add_flags(TypeFlags::HAS_CT_INFER),
},
ty::ConstKind::Bound(debruijn, _) => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) => {
self.add_bound_var(debruijn);
self.add_flags(TypeFlags::HAS_CT_BOUND);
}
ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, _) => {
self.add_flags(TypeFlags::HAS_CT_BOUND);
self.add_flags(TypeFlags::HAS_CANONICAL_BOUND);
}
ty::ConstKind::Param(_) => {
self.add_flags(TypeFlags::HAS_CT_PARAM);
}

View File

@@ -55,7 +55,7 @@ use tracing::{debug, instrument};
use crate::inherent::*;
use crate::visit::{TypeVisitable, TypeVisitableExt as _};
use crate::{self as ty, Interner, TypeFlags};
use crate::{self as ty, BoundVarIndexKind, Interner, TypeFlags};
/// This trait is implemented for every type that can be folded,
/// providing the skeleton of the traversal.
@@ -398,7 +398,9 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
if debruijn >= self.current_index =>
{
let debruijn = debruijn.shifted_in(self.amount);
Region::new_bound(self.cx, debruijn, br)
}
@@ -408,7 +410,9 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
match ty.kind() {
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty)
if debruijn >= self.current_index =>
{
let debruijn = debruijn.shifted_in(self.amount);
Ty::new_bound(self.cx, debruijn, bound_ty)
}
@@ -420,7 +424,9 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
fn fold_const(&mut self, ct: I::Const) -> I::Const {
match ct.kind() {
ty::ConstKind::Bound(debruijn, bound_ct) if debruijn >= self.current_index => {
ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ct)
if debruijn >= self.current_index =>
{
let debruijn = debruijn.shifted_in(self.amount);
Const::new_bound(self.cx, debruijn, bound_ct)
}
@@ -435,7 +441,7 @@ impl<I: Interner> TypeFolder<I> for Shifter<I> {
pub fn shift_region<I: Interner>(cx: I, region: I::Region, amount: u32) -> I::Region {
match region.kind() {
ty::ReBound(debruijn, br) if amount > 0 => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) if amount > 0 => {
Region::new_bound(cx, debruijn.shifted_in(amount), br)
}
_ => region,
@@ -515,7 +521,13 @@ where
#[instrument(skip(self), level = "debug", ret)]
fn fold_region(&mut self, r: I::Region) -> I::Region {
match r.kind() {
ty::ReBound(debruijn, _) if debruijn < self.current_index => {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
if debruijn < self.current_index =>
{
debug!(?self.current_index, "skipped bound region");
r
}
ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
debug!(?self.current_index, "skipped bound region");
r
}

View File

@@ -48,6 +48,8 @@ pub trait Ty<I: Interner<Ty = Self>>:
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self;
fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self {
@@ -230,6 +232,8 @@ pub trait Region<I: Interner<Region = Self>>:
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self;
fn new_static(interner: I) -> Self;
fn new_placeholder(interner: I, var: I::PlaceholderRegion) -> Self;
@@ -260,6 +264,8 @@ pub trait Const<I: Interner<Const = Self>>:
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self;
fn new_placeholder(interner: I, param: I::PlaceholderConst) -> Self;
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;

View File

@@ -196,14 +196,21 @@ impl DebruijnIndex {
pub fn debug_bound_var<T: std::fmt::Write>(
fmt: &mut T,
debruijn: DebruijnIndex,
bound_index: BoundVarIndexKind,
var: impl std::fmt::Debug,
) -> Result<(), std::fmt::Error> {
match bound_index {
BoundVarIndexKind::Bound(debruijn) => {
if debruijn == INNERMOST {
write!(fmt, "^{var:?}")
} else {
write!(fmt, "^{}_{:?}", debruijn.index(), var)
}
}
BoundVarIndexKind::Canonical => {
write!(fmt, "^c_{:?}", var)
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash)]

View File

@@ -7,7 +7,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
use self::RegionKind::*;
use crate::{DebruijnIndex, Interner};
use crate::{BoundVarIndexKind, Interner};
rustc_index::newtype_index! {
/// A **region** **v**ariable **ID**.
@@ -147,7 +147,7 @@ pub enum RegionKind<I: Interner> {
/// Bound regions inside of types **must not** be erased, as they impact trait
/// selection and the `TypeId` of that type. `for<'a> fn(&'a ())` and
/// `fn(&'static ())` are different types and have to be treated as such.
ReBound(DebruijnIndex, I::BoundRegion),
ReBound(BoundVarIndexKind, I::BoundRegion),
/// Late-bound function parameters are represented using a `ReBound`. When
/// inside of a function, we convert these bound variables to placeholder

View File

@@ -15,7 +15,7 @@ pub use self::closure::*;
use crate::inherent::*;
#[cfg(feature = "nightly")]
use crate::visit::TypeVisitable;
use crate::{self as ty, DebruijnIndex, FloatTy, IntTy, Interner, UintTy};
use crate::{self as ty, BoundVarIndexKind, FloatTy, IntTy, Interner, UintTy};
mod closure;
@@ -229,7 +229,7 @@ pub enum TyKind<I: Interner> {
///
/// [1]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
/// [2]: https://rustc-dev-guide.rust-lang.org/traits/canonical-queries.html
Bound(DebruijnIndex, I::BoundTy),
Bound(BoundVarIndexKind, I::BoundTy),
/// A placeholder type, used during higher ranked subtyping to instantiate
/// bound variables.

View File

@@ -344,7 +344,8 @@ impl<I: Interner> TypeVisitor<I> for HasRegionsBoundAt {
}
fn visit_region(&mut self, r: I::Region) -> Self::Result {
if matches!(r.kind(), ty::ReBound(binder, _) if self.binder == binder) {
if matches!(r.kind(), ty::ReBound(ty::BoundVarIndexKind::Bound(binder), _) if self.binder == binder)
{
ControlFlow::Break(())
} else {
ControlFlow::Continue(())
@@ -531,7 +532,7 @@ impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
}
fn fold_region(&mut self, r: <I as Interner>::Region) -> <I as Interner>::Region {
if let ty::ReBound(debruijn, _) = r.kind() {
if let ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) = r.kind() {
assert!(
debruijn <= self.debruijn,
"cannot instantiate binder with escaping bound vars"

View File

@@ -14,7 +14,7 @@ use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, No
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::adjustment::{Adjust, PointerCoercion};
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::{self, RegionKind, TyCtxt};
use rustc_middle::ty::{self, BoundVarIndexKind, RegionKind, TyCtxt};
use rustc_session::impl_lint_pass;
use rustc_span::def_id::LocalDefId;
use rustc_span::{Span, sym};
@@ -151,7 +151,7 @@ impl PassByRefOrValue {
match *ty.skip_binder().kind() {
ty::Ref(lt, ty, Mutability::Not) => {
match lt.kind() {
RegionKind::ReBound(index, region)
RegionKind::ReBound(BoundVarIndexKind::Bound(index), region)
if index.as_u32() == 0 && output_regions.contains(&region) =>
{
continue;

View File

@@ -21,7 +21,7 @@ use rustc_middle::traits::EvaluationResult;
use rustc_middle::ty::adjustment::{Adjust, Adjustment};
use rustc_middle::ty::layout::ValidityRequirement;
use rustc_middle::ty::{
self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, GenericArgKind, GenericArgsRef,
GenericParamDefKind, IntTy, Region, RegionKind, TraitRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
TypeVisitableExt, TypeVisitor, UintTy, Upcast, VariantDef, VariantDiscr,
};
@@ -826,7 +826,7 @@ pub fn for_each_top_level_late_bound_region<B>(
impl<'tcx, B, F: FnMut(BoundRegion) -> ControlFlow<B>> TypeVisitor<TyCtxt<'tcx>> for V<F> {
type Result = ControlFlow<B>;
fn visit_region(&mut self, r: Region<'tcx>) -> Self::Result {
if let RegionKind::ReBound(idx, bound) = r.kind()
if let RegionKind::ReBound(BoundVarIndexKind::Bound(idx), bound) = r.kind()
&& idx.as_u32() == self.index
{
(self.f)(bound)

View File

@@ -1,30 +1,30 @@
// MIR for `address_of_reborrow` after SimplifyCfg-initial
| User Type Annotations
| 0: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
| 0: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:8:10: 8:18, inferred_ty: *const [i32; 10]
| 1: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:10:10: 10:25, inferred_ty: *const dyn std::marker::Send
| 2: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
| 3: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
| 2: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
| 3: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:14:12: 14:20, inferred_ty: *const [i32; 10]
| 4: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
| 5: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:15:12: 15:28, inferred_ty: *const [i32; 10]
| 6: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
| 7: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:16:12: 16:27, inferred_ty: *const dyn std::marker::Send
| 8: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
| 9: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:17:12: 17:24, inferred_ty: *const [i32]
| 10: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
| 10: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:19:10: 19:18, inferred_ty: *const [i32; 10]
| 11: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:21:10: 21:25, inferred_ty: *const dyn std::marker::Send
| 12: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
| 13: user_ty: Canonical { value: Ty(*const ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
| 12: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
| 13: user_ty: Canonical { value: Ty(*const ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:24:12: 24:20, inferred_ty: *const [i32; 10]
| 14: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
| 15: user_ty: Canonical { value: Ty(*const [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:25:12: 25:28, inferred_ty: *const [i32; 10]
| 16: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
| 17: user_ty: Canonical { value: Ty(*const dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:26:12: 26:27, inferred_ty: *const dyn std::marker::Send
| 18: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
| 19: user_ty: Canonical { value: Ty(*const [i32]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:27:12: 27:24, inferred_ty: *const [i32]
| 20: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
| 20: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:29:10: 29:16, inferred_ty: *mut [i32; 10]
| 21: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:31:10: 31:23, inferred_ty: *mut dyn std::marker::Send
| 22: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
| 23: user_ty: Canonical { value: Ty(*mut ^0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
| 22: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
| 23: user_ty: Canonical { value: Ty(*mut ^c_0), max_universe: U0, variables: [Ty { ui: U0, sub_root: 0 }] }, span: $DIR/address_of.rs:34:12: 34:18, inferred_ty: *mut [i32; 10]
| 24: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
| 25: user_ty: Canonical { value: Ty(*mut [i32; 10]), max_universe: U0, variables: [] }, span: $DIR/address_of.rs:35:12: 35:26, inferred_ty: *mut [i32; 10]
| 26: user_ty: Canonical { value: Ty(*mut dyn std::marker::Send), max_universe: U0, variables: [Region(U0)] }, span: $DIR/address_of.rs:36:12: 36:25, inferred_ty: *mut dyn std::marker::Send

View File

@@ -1,5 +1,5 @@
error: reached the recursion limit while instantiating `ToChain::<'_, '_>::perm_pairs::<{async closure@$DIR/post-mono-higher-ranked-hang.rs:43:45: 43:67}>`
--> $DIR/post-mono-higher-ranked-hang.rs:43:21
error: reached the recursion limit while instantiating `ToChain::<'_, '_>::perm_pairs::<{async closure@$DIR/post-mono-higher-ranked-hang.rs:47:45: 47:67}>`
--> $DIR/post-mono-higher-ranked-hang.rs:47:21
|
LL | / self.perm_pairs(l, &mut async move |left_pair| {
LL | |
@@ -8,7 +8,7 @@ LL | | })
| |______________________^
|
note: `ToChain::<'env, 'db>::perm_pairs` defined here
--> $DIR/post-mono-higher-ranked-hang.rs:34:5
--> $DIR/post-mono-higher-ranked-hang.rs:38:5
|
LL | / fn perm_pairs<'l>(
LL | | &'l self,

View File

@@ -0,0 +1,21 @@
error: reached the recursion limit while instantiating `ToChain::<'_, '_>::perm_pairs::<{async closure@$DIR/post-mono-higher-ranked-hang.rs:47:45: 47:67}>`
--> $DIR/post-mono-higher-ranked-hang.rs:47:21
|
LL | / self.perm_pairs(l, &mut async move |left_pair| {
LL | |
LL | | self.perm_pairs(r, yield_chain).await
LL | | })
| |______________________^
|
note: `ToChain::<'env, 'db>::perm_pairs` defined here
--> $DIR/post-mono-higher-ranked-hang.rs:38:5
|
LL | / fn perm_pairs<'l>(
LL | | &'l self,
LL | | perm: &'l SymPerm<'db>,
LL | | yield_chain: &'l mut impl AsyncFnMut(&SymPerm<'db>),
LL | | ) -> Pin<Box<dyn std::future::Future<Output = ()> + 'l>> {
| |____________________________________________________________^
error: aborting due to 1 previous error

View File

@@ -2,6 +2,10 @@
//@ aux-build:block-on.rs
//@ edition:2021
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// Regression test for <https://github.com/rust-lang/rust/issues/135780>.
extern crate block_on;

View File

@@ -37,7 +37,7 @@ error: higher-ranked lifetime error
LL | v.t(|| {});
| ^^^^^
|
= note: could not prove `for<'a> &'a V: 'b`
= note: could not prove `for<'a> &'a V: '_`
error: aborting due to 3 previous errors

View File

@@ -4,7 +4,7 @@ error: higher-ranked lifetime error
LL | || {};
| ^^^^^
|
= note: could not prove `for<'a> &'a (): 'b`
= note: could not prove `for<'a> &'a (): '_`
error: aborting due to 1 previous error

View File

@@ -4,7 +4,7 @@ error: higher-ranked lifetime error
LL | foo(&10);
| ^^^^^^^^
|
= note: could not prove `for<'b> &'b (): 'a`
= note: could not prove `for<'b> &'b (): '_`
error: aborting due to 1 previous error

View File

@@ -31,7 +31,7 @@ fn main() {
// Here: we only want the `T` to be given, the rest should be variables.
//
// (`T` refers to the declaration of `Bazoom`)
let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^0, u32, ^1]
let x = <_ as Bazoom<u32>>::method::<_>; //~ ERROR [^c_0, u32, ^c_1]
x(&22, 44, 66);
// Here: all are given and definitely contain no lifetimes, so we
@@ -48,7 +48,7 @@ fn main() {
//
// (`U` refers to the declaration of `Bazoom`)
let y = 22_u32;
y.method::<u32>(44, 66); //~ ERROR [^0, ^1, u32]
y.method::<u32>(44, 66); //~ ERROR [^c_0, ^c_1, u32]
// Here: nothing is given, so we don't have any annotation.
let y = 22_u32;

View File

@@ -4,7 +4,7 @@ error: user args: UserArgs { args: [&'static u32], user_self_ty: None }
LL | let x = foo::<&'static u32>;
| ^^^^^^^^^^^^^^^^^^^
error: user args: UserArgs { args: [^0, u32, ^1], user_self_ty: None }
error: user args: UserArgs { args: [^c_0, u32, ^c_1], user_self_ty: None }
--> $DIR/dump-fn-method.rs:34:13
|
LL | let x = <_ as Bazoom<u32>>::method::<_>;
@@ -16,7 +16,7 @@ error: user args: UserArgs { args: [u8, &'static u16, u32], user_self_ty: None }
LL | let x = <u8 as Bazoom<&'static u16>>::method::<u32>;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: user args: UserArgs { args: [^0, ^1, u32], user_self_ty: None }
error: user args: UserArgs { args: [^c_0, ^c_1, u32], user_self_ty: None }
--> $DIR/dump-fn-method.rs:51:5
|
LL | y.method::<u32>(44, 66);