From 94cc5bb9620cdee942b8b79e7026f622fcc695a0 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Jul 2025 14:29:28 +1000 Subject: [PATCH 1/3] Streamline const folding/visiting. Type folders can only modify a few "types of interest": `Binder`, `Ty`, `Predicate`, `Clauses`, `Region`, `Const`. Likewise for type visitors, but they can also visit errors (via `ErrorGuaranteed`). Currently the impls of `try_super_fold_with`, `super_fold_with`, and `super_visit_with` do more than they need to -- they fold/visit values that cannot contain any types of interest. This commit removes those unnecessary fold/visit operations, which makes these impls more similar to the impls for `Ty`. It also removes the now-unnecessary derived impls for the no-longer-visited types. --- .../rustc_middle/src/ty/structural_impls.rs | 46 ++++++++----------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index a5fdce93e4b2b..10e499d9c758c 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -232,6 +232,7 @@ TrivialLiftImpls! { crate::mir::Promoted, crate::mir::interpret::AllocId, crate::mir::interpret::Scalar, + crate::ty::ParamConst, rustc_abi::ExternAbi, rustc_abi::Size, rustc_hir::Safety, @@ -271,10 +272,6 @@ TrivialTypeTraversalImpls! { crate::ty::AssocItem, crate::ty::AssocKind, crate::ty::BoundRegion, - crate::ty::BoundVar, - crate::ty::InferConst, - crate::ty::Placeholder, - crate::ty::Placeholder, crate::ty::UserTypeAnnotationIndex, crate::ty::ValTree<'tcx>, crate::ty::abstract_const::NotConstEvaluatable, @@ -302,9 +299,8 @@ TrivialTypeTraversalImpls! { // interners). TrivialTypeTraversalAndLiftImpls! { // tidy-alphabetical-start - crate::ty::ParamConst, crate::ty::ParamTy, - crate::ty::Placeholder, + crate::ty::PlaceholderType, crate::ty::instance::ReifyReason, rustc_hir::def_id::DefId, // tidy-alphabetical-end @@ -673,30 +669,30 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { folder: &mut F, ) -> Result { let kind = match self.kind() { - ConstKind::Param(p) => ConstKind::Param(p.try_fold_with(folder)?), - ConstKind::Infer(i) => ConstKind::Infer(i.try_fold_with(folder)?), - ConstKind::Bound(d, b) => { - ConstKind::Bound(d.try_fold_with(folder)?, b.try_fold_with(folder)?) - } - ConstKind::Placeholder(p) => ConstKind::Placeholder(p.try_fold_with(folder)?), ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?), ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), - ConstKind::Error(e) => ConstKind::Error(e.try_fold_with(folder)?), ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) + | ConstKind::Error(_) => return Ok(self), }; if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) } } fn super_fold_with>>(self, folder: &mut F) -> Self { let kind = match self.kind() { - ConstKind::Param(p) => ConstKind::Param(p.fold_with(folder)), - ConstKind::Infer(i) => ConstKind::Infer(i.fold_with(folder)), - ConstKind::Bound(d, b) => ConstKind::Bound(d.fold_with(folder), b.fold_with(folder)), - ConstKind::Placeholder(p) => ConstKind::Placeholder(p.fold_with(folder)), ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.fold_with(folder)), ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)), - ConstKind::Error(e) => ConstKind::Error(e.fold_with(folder)), ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) + | ConstKind::Error(_) => return self, }; if kind != self.kind() { folder.cx().mk_ct_from_kind(kind) } else { self } } @@ -705,17 +701,15 @@ impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { match self.kind() { - ConstKind::Param(p) => p.visit_with(visitor), - ConstKind::Infer(i) => i.visit_with(visitor), - ConstKind::Bound(d, b) => { - try_visit!(d.visit_with(visitor)); - b.visit_with(visitor) - } - ConstKind::Placeholder(p) => p.visit_with(visitor), ConstKind::Unevaluated(uv) => uv.visit_with(visitor), ConstKind::Value(v) => v.visit_with(visitor), - ConstKind::Error(e) => e.visit_with(visitor), ConstKind::Expr(e) => e.visit_with(visitor), + ConstKind::Error(e) => e.visit_with(visitor), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) => V::Result::output(), } } } From 507dec4dc321c868ad876c0b7302c66088b7cc7c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Jul 2025 14:21:00 +1000 Subject: [PATCH 2/3] Make const bound handling more like types/regions. Currently there is `Ty` and `BoundTy`, and `Region` and `BoundRegion`, and `Const` and... `BoundVar`. An annoying inconsistency. This commit repurposes the existing `BoundConst`, which was barely used, so it's the partner to `Const`. Unlike `BoundTy`/`BoundRegion` it lacks a `kind` field but it's still nice to have because it makes the const code more similar to the ty/region code everywhere. The commit also removes `impl From for BoundTy`, which has a single use and doesn't seem worth it. These changes fix the "FIXME: We really should have a separate `BoundConst` for consts". --- .../src/type_check/relate_tys.rs | 4 ++-- .../src/check/compare_impl_item.rs | 2 +- .../src/collect/item_bounds.rs | 10 ++++---- .../src/hir_ty_lowering/bounds.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 8 ++++--- .../src/infer/canonical/canonicalizer.rs | 6 +++-- .../src/infer/canonical/instantiate.rs | 4 ++-- .../src/infer/canonical/query_response.rs | 6 ++--- compiler/rustc_infer/src/infer/mod.rs | 4 ++-- .../src/infer/relate/higher_ranked.rs | 4 ++-- compiler/rustc_middle/src/ty/consts.rs | 14 +++++++---- compiler/rustc_middle/src/ty/context.rs | 2 +- compiler/rustc_middle/src/ty/fold.rs | 24 ++++++++++++------- compiler/rustc_middle/src/ty/mod.rs | 23 ++++++++++++------ compiler/rustc_middle/src/ty/sty.rs | 6 ----- .../rustc_middle/src/ty/typeck_results.rs | 6 ++--- .../src/traits/coherence.rs | 5 +++- .../rustc_trait_selection/src/traits/mod.rs | 5 +++- .../rustc_trait_selection/src/traits/util.rs | 4 ++-- compiler/rustc_type_ir/src/inherent.rs | 2 +- compiler/rustc_type_ir/src/lib.rs | 10 -------- 21 files changed, 82 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index e023300f1c281..bb72d1d52f37e 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -187,7 +187,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { types: &mut |_bound_ty: ty::BoundTy| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_var: ty::BoundVar| { + consts: &mut |_bound_const: ty::BoundConst| { unreachable!("we only replace regions in nll_relate, not consts") }, }; @@ -226,7 +226,7 @@ impl<'a, 'b, 'tcx> NllTypeRelating<'a, 'b, 'tcx> { types: &mut |_bound_ty: ty::BoundTy| { unreachable!("we only replace regions in nll_relate, not types") }, - consts: &mut |_bound_var: ty::BoundVar| { + consts: &mut |_bound_const: ty::BoundConst| { unreachable!("we only replace regions in nll_relate, not consts") }, }; diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index e24426f9fedce..13d690054ce67 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2498,7 +2498,7 @@ fn param_env_with_gat_bounds<'tcx>( ty::Const::new_bound( tcx, ty::INNERMOST, - ty::BoundVar::from_usize(bound_vars.len() - 1), + ty::BoundConst { var: ty::BoundVar::from_usize(bound_vars.len() - 1) }, ) .into() } diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 548ba343aaeee..ba54fa8cc0dbf 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -189,7 +189,7 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>( } ty::GenericArgKind::Const(ct) => { if let ty::ConstKind::Bound(ty::INNERMOST, bv) = ct.kind() { - mapping.insert(bv, tcx.mk_param_from_def(param)) + mapping.insert(bv.var, tcx.mk_param_from_def(param)) } else { return None; } @@ -307,16 +307,16 @@ impl<'tcx> TypeFolder> for MapAndCompressBoundVars<'tcx> { return ct; } - if let ty::ConstKind::Bound(binder, old_var) = ct.kind() + if let ty::ConstKind::Bound(binder, old_bound) = ct.kind() && self.binder == binder { - let mapped = if let Some(mapped) = self.mapping.get(&old_var) { + let mapped = if let Some(mapped) = self.mapping.get(&old_bound.var) { mapped.expect_const() } else { let var = ty::BoundVar::from_usize(self.still_bound_vars.len()); self.still_bound_vars.push(ty::BoundVariableKind::Const); - let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, var); - self.mapping.insert(old_var, mapped.into()); + let mapped = ty::Const::new_bound(self.tcx, ty::INNERMOST, ty::BoundConst { var }); + self.mapping.insert(old_bound.var, mapped.into()); mapped }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 7760642d8fb0a..386e1091ac4eb 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -1077,7 +1077,7 @@ impl<'tcx> TypeVisitor> for GenericParamAndBoundVarCollector<'_, 't ty::ConstKind::Param(param) => { self.params.insert(param.index); } - ty::ConstKind::Bound(db, ty::BoundVar { .. }) if db >= self.depth => { + ty::ConstKind::Bound(db, _) if db >= self.depth => { let guar = self.cx.dcx().delayed_bug("unexpected escaping late-bound const var"); return ControlFlow::Break(guar); } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index d768799835867..d93f3c5f50858 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2107,9 +2107,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let name = tcx.item_name(param_def_id); ty::Const::new_param(tcx, ty::ParamConst::new(index, name)) } - Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => { - ty::Const::new_bound(tcx, debruijn, ty::BoundVar::from_u32(index)) - } + Some(rbv::ResolvedArg::LateBound(debruijn, index, _)) => ty::Const::new_bound( + tcx, + debruijn, + ty::BoundConst { var: ty::BoundVar::from_u32(index) }, + ), Some(rbv::ResolvedArg::Error(guar)) => ty::Const::new_error(tcx, guar), arg => bug!("unexpected bound var resolution for {:?}: {arg:?}", path_hir_id), } diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 060447ba72068..a4c6d078125db 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -752,7 +752,8 @@ 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()); - Ty::new_bound(self.tcx, self.binder_index, var.into()) + let bt = ty::BoundTy { var, kind: ty::BoundTyKind::Anon }; + Ty::new_bound(self.tcx, self.binder_index, bt) } /// Given a type variable `const_var` of the given kind, first check @@ -768,6 +769,7 @@ 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()); - ty::Const::new_bound(self.tcx, self.binder_index, var) + let bc = ty::BoundConst { var }; + ty::Const::new_bound(self.tcx, self.binder_index, bc) } } diff --git a/compiler/rustc_infer/src/infer/canonical/instantiate.rs b/compiler/rustc_infer/src/infer/canonical/instantiate.rs index 2385c68ef6bb7..cc052fbd85c12 100644 --- a/compiler/rustc_infer/src/infer/canonical/instantiate.rs +++ b/compiler/rustc_infer/src/infer/canonical/instantiate.rs @@ -133,7 +133,7 @@ impl<'tcx> TypeFolder> 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 => { - self.var_values[bound_const.as_usize()].expect_const() + self.var_values[bound_const.var.as_usize()].expect_const() } _ => ct.super_fold_with(self), } @@ -217,7 +217,7 @@ fn highest_var_in_clauses<'tcx>(c: ty::Clauses<'tcx>) -> usize { if let ty::ConstKind::Bound(debruijn, bound_const) = ct.kind() && debruijn == self.current_index { - self.max_var = self.max_var.max(bound_const.as_usize()); + self.max_var = self.max_var.max(bound_const.var.as_usize()); } else if ct.has_vars_bound_at_or_above(self.current_index) { ct.super_visit_with(self); } diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs index 6be53c948c84a..73b1ca6c69136 100644 --- a/compiler/rustc_infer/src/infer/canonical/query_response.rs +++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs @@ -433,12 +433,12 @@ impl<'tcx> InferCtxt<'tcx> { } GenericArgKind::Lifetime(result_value) => { // e.g., here `result_value` might be `'?1` in the example above... - if let ty::ReBound(debruijn, br) = result_value.kind() { + if let ty::ReBound(debruijn, b) = result_value.kind() { // ... in which case we would set `canonical_vars[0]` to `Some('static)`. // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); - opt_values[br.var] = Some(*original_value); + opt_values[b.var] = Some(*original_value); } } GenericArgKind::Const(result_value) => { @@ -447,7 +447,7 @@ impl<'tcx> InferCtxt<'tcx> { // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); - opt_values[b] = Some(*original_value); + opt_values[b.var] = Some(*original_value); } } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 2d269e320b64d..41297e8ffca15 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1208,8 +1208,8 @@ impl<'tcx> InferCtxt<'tcx> { fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { self.args[bt.var.index()].expect_ty() } - fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { - self.args[bv.index()].expect_const() + fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + self.args[bc.var.index()].expect_const() } } let delegate = ToFreshVars { args }; diff --git a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs index 2143f72a3b0a5..16fe591b29bba 100644 --- a/compiler/rustc_infer/src/infer/relate/higher_ranked.rs +++ b/compiler/rustc_infer/src/infer/relate/higher_ranked.rs @@ -45,10 +45,10 @@ impl<'tcx> InferCtxt<'tcx> { ty::PlaceholderType { universe: next_universe, bound: bound_ty }, ) }, - consts: &mut |bound_var: ty::BoundVar| { + consts: &mut |bound_const: ty::BoundConst| { ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst { universe: next_universe, bound: bound_var }, + ty::PlaceholderConst { universe: next_universe, bound: bound_const }, ) }, }; diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index fd1aa4042bcfd..614b6471f188a 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -93,9 +93,9 @@ impl<'tcx> Const<'tcx> { pub fn new_bound( tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, - var: ty::BoundVar, + bound_const: ty::BoundConst, ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Bound(debruijn, var)) + Const::new(tcx, ty::ConstKind::Bound(debruijn, bound_const)) } #[inline] @@ -168,12 +168,16 @@ impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { Const::new_var(tcx, vid) } - fn new_bound(interner: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Const::new_bound(interner, debruijn, var) + fn new_bound( + interner: TyCtxt<'tcx>, + debruijn: ty::DebruijnIndex, + bound_const: ty::BoundConst, + ) -> Self { + Const::new_bound(interner, debruijn, bound_const) } fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Const::new_bound(tcx, debruijn, var) + Const::new_bound(tcx, debruijn, ty::BoundConst { var }) } fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Self { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6f21160d1f66e..466b3f191c066 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -152,7 +152,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type PlaceholderConst = ty::PlaceholderConst; type ParamConst = ty::ParamConst; - type BoundConst = ty::BoundVar; + type BoundConst = ty::BoundConst; type ValueConst = ty::Value<'tcx>; type ExprConst = ty::Expr<'tcx>; type ValTree = ty::ValTree<'tcx>; diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index b2057fa36d7fc..7d56ec1635f8d 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -3,7 +3,7 @@ use rustc_hir::def_id::DefId; use rustc_type_ir::data_structures::DelayedMap; use crate::ty::{ - self, Binder, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, + self, Binder, BoundConst, BoundTy, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -60,7 +60,7 @@ where pub trait BoundVarReplacerDelegate<'tcx> { fn replace_region(&mut self, br: ty::BoundRegion) -> ty::Region<'tcx>; fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx>; - fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx>; + fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx>; } /// A simple delegate taking 3 mutable functions. The used functions must @@ -69,7 +69,7 @@ pub trait BoundVarReplacerDelegate<'tcx> { pub struct FnMutDelegate<'a, 'tcx> { pub regions: &'a mut (dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx> + 'a), pub types: &'a mut (dyn FnMut(ty::BoundTy) -> Ty<'tcx> + 'a), - pub consts: &'a mut (dyn FnMut(ty::BoundVar) -> ty::Const<'tcx> + 'a), + pub consts: &'a mut (dyn FnMut(ty::BoundConst) -> ty::Const<'tcx> + 'a), } impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { @@ -79,8 +79,8 @@ impl<'a, 'tcx> BoundVarReplacerDelegate<'tcx> for FnMutDelegate<'a, 'tcx> { fn replace_ty(&mut self, bt: ty::BoundTy) -> Ty<'tcx> { (self.types)(bt) } - fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { - (self.consts)(bv) + fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + (self.consts)(bc) } } @@ -300,7 +300,13 @@ impl<'tcx> TyCtxt<'tcx> { ty::BoundTy { var: shift_bv(t.var), kind: t.kind }, ) }, - consts: &mut |c| ty::Const::new_bound(self, ty::INNERMOST, shift_bv(c)), + consts: &mut |c| { + ty::Const::new_bound( + self, + ty::INNERMOST, + ty::BoundConst { var: shift_bv(c.var) }, + ) + }, }, ) } @@ -343,12 +349,12 @@ impl<'tcx> TyCtxt<'tcx> { .expect_ty(); Ty::new_bound(self.tcx, ty::INNERMOST, BoundTy { var, kind }) } - fn replace_const(&mut self, bv: ty::BoundVar) -> ty::Const<'tcx> { - let entry = self.map.entry(bv); + fn replace_const(&mut self, bc: ty::BoundConst) -> ty::Const<'tcx> { + let entry = self.map.entry(bc.var); let index = entry.index(); let var = ty::BoundVar::from_usize(index); let () = entry.or_insert_with(|| ty::BoundVariableKind::Const).expect_const(); - ty::Const::new_bound(self.tcx, ty::INNERMOST, var) + ty::Const::new_bound(self.tcx, ty::INNERMOST, BoundConst { var }) } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index bb70c61cd1417..fab020547ad39 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -968,34 +968,43 @@ impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for Placeholde #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable)] #[derive(TyEncodable, TyDecodable)] -pub struct BoundConst<'tcx> { +pub struct BoundConst { pub var: BoundVar, - pub ty: Ty<'tcx>, } -pub type PlaceholderConst = Placeholder; +impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundConst { + fn var(self) -> BoundVar { + self.var + } + + fn assert_eq(self, _var: ty::BoundVariableKind) { + unreachable!() + } +} + +pub type PlaceholderConst = Placeholder; impl<'tcx> rustc_type_ir::inherent::PlaceholderLike> for PlaceholderConst { - type Bound = BoundVar; + type Bound = BoundConst; fn universe(self) -> UniverseIndex { self.universe } fn var(self) -> BoundVar { - self.bound + self.bound.var } fn with_updated_universe(self, ui: UniverseIndex) -> Self { Placeholder { universe: ui, ..self } } - fn new(ui: UniverseIndex, bound: BoundVar) -> Self { + fn new(ui: UniverseIndex, bound: BoundConst) -> Self { Placeholder { universe: ui, bound } } fn new_anon(ui: UniverseIndex, var: BoundVar) -> Self { - Placeholder { universe: ui, bound: var } + Placeholder { universe: ui, bound: BoundConst { var } } } } diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 4569596cfbe83..ea84ea3af4284 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -403,12 +403,6 @@ pub enum BoundTyKind { Param(DefId), } -impl From for BoundTy { - fn from(var: BoundVar) -> Self { - BoundTy { var, kind: BoundTyKind::Anon } - } -} - /// Constructors for `Ty` impl<'tcx> Ty<'tcx> { /// Avoid using this in favour of more specific `new_*` methods, where possible. diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs index 88583407d25d7..6b187c5325a9b 100644 --- a/compiler/rustc_middle/src/ty/typeck_results.rs +++ b/compiler/rustc_middle/src/ty/typeck_results.rs @@ -789,10 +789,10 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { }, GenericArgKind::Lifetime(r) => match r.kind() { - ty::ReBound(debruijn, br) => { + ty::ReBound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); - cvar == br.var + cvar == b.var } _ => false, }, @@ -801,7 +801,7 @@ impl<'tcx> IsIdentity for CanonicalUserType<'tcx> { ty::ConstKind::Bound(debruijn, b) => { // We only allow a `ty::INNERMOST` index in generic parameters. assert_eq!(debruijn, ty::INNERMOST); - cvar == b + cvar == b.var } _ => false, }, diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 07e78da37b3b5..d8aedf5c2bf3b 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -535,7 +535,10 @@ fn plug_infer_with_placeholders<'tcx>( ct, ty::Const::new_placeholder( self.infcx.tcx, - ty::Placeholder { universe: self.universe, bound: self.next_var() }, + ty::Placeholder { + universe: self.universe, + bound: ty::BoundConst { var: self.next_var() }, + }, ), ) else { diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 9b5e59ce0fdb7..08315dbd21fbf 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -706,7 +706,10 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>( self.idx += 1; ty::Const::new_placeholder( self.tcx, - ty::PlaceholderConst { universe: ty::UniverseIndex::ROOT, bound: idx }, + ty::PlaceholderConst { + universe: ty::UniverseIndex::ROOT, + bound: ty::BoundConst { var: idx }, + }, ) } else { c.super_fold_with(self) diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index c3d60ec45c46b..83c0969762f4a 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -222,7 +222,7 @@ pub struct PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, - mapped_consts: FxIndexMap, + mapped_consts: FxIndexMap, universe_indices: &'a [Option], current_index: ty::DebruijnIndex, } @@ -232,7 +232,7 @@ impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> { infcx: &'a InferCtxt<'tcx>, mapped_regions: FxIndexMap, mapped_types: FxIndexMap, - mapped_consts: FxIndexMap, + mapped_consts: FxIndexMap, universe_indices: &'a [Option], value: T, ) -> T { diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 0e307e15d5b4d..1a6c99ce7dec0 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -251,7 +251,7 @@ pub trait Const>: fn new_var(interner: I, var: ty::ConstVid) -> Self; - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self; + fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: I::BoundConst) -> Self; fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index a483c18813b03..5c9cac5b21b1e 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -387,16 +387,6 @@ rustc_index::newtype_index! { pub struct BoundVar {} } -impl inherent::BoundVarLike for BoundVar { - fn var(self) -> BoundVar { - self - } - - fn assert_eq(self, _var: I::BoundVarKind) { - unreachable!("FIXME: We really should have a separate `BoundConst` for consts") - } -} - /// Represents the various closure traits in the language. This /// will determine the type of the environment (`self`, in the /// desugaring) argument that the closure expects. From 64be8bb599d3efa12235e266177c828ad97373e6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 30 Jul 2025 19:04:03 +1000 Subject: [PATCH 3/3] Check consts in `ValidateBoundVars`. Alongside the existing type and region checking. --- compiler/rustc_middle/src/ty/mod.rs | 4 ++-- compiler/rustc_type_ir/src/binder.rs | 23 +++++++++++++++++++++-- 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index fab020547ad39..342f598746615 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -977,8 +977,8 @@ impl<'tcx> rustc_type_ir::inherent::BoundVarLike> for BoundConst { self.var } - fn assert_eq(self, _var: ty::BoundVariableKind) { - unreachable!() + fn assert_eq(self, var: ty::BoundVariableKind) { + var.expect_const() } } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index a7b915c48455b..fb0dfe95b7384 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -274,8 +274,9 @@ impl Binder { pub struct ValidateBoundVars { bound_vars: I::BoundVarKinds, binder_index: ty::DebruijnIndex, - // We may encounter the same variable at different levels of binding, so - // this can't just be `Ty` + // We only cache types because any complex const will have to step through + // a type at some point anyways. We may encounter the same variable at + // different levels of binding, so this can't just be `Ty`. visited: SsoHashSet<(ty::DebruijnIndex, I::Ty)>, } @@ -319,6 +320,24 @@ impl TypeVisitor for ValidateBoundVars { t.super_visit_with(self) } + fn visit_const(&mut self, c: I::Const) -> Self::Result { + if c.outer_exclusive_binder() < self.binder_index { + return ControlFlow::Break(()); + } + match c.kind() { + ty::ConstKind::Bound(debruijn, bound_const) if debruijn == 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); + } + bound_const.assert_eq(self.bound_vars.get(idx).unwrap()); + } + _ => {} + }; + + c.super_visit_with(self) + } + fn visit_region(&mut self, r: I::Region) -> Self::Result { match r.kind() { ty::ReBound(index, br) if index == self.binder_index => {