Skip to content

Commit 7768a67

Browse files
Uplift BoundVarReplacer
1 parent 55de777 commit 7768a67

File tree

8 files changed

+174
-148
lines changed

8 files changed

+174
-148
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4618,7 +4618,7 @@ dependencies = [
46184618
"derive-where",
46194619
"ena",
46204620
"indexmap",
4621-
"rustc-hash 1.1.0",
4621+
"rustc-hash 2.1.1",
46224622
"rustc_ast_ir",
46234623
"rustc_data_structures",
46244624
"rustc_index",

compiler/rustc_middle/src/ty/consts.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,10 @@ impl<'tcx> rustc_type_ir::inherent::Const<TyCtxt<'tcx>> for Const<'tcx> {
163163
Const::new_bound(tcx, debruijn, var)
164164
}
165165

166+
fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst) -> Self {
167+
Const::new_placeholder(tcx, placeholder)
168+
}
169+
166170
fn new_unevaluated(interner: TyCtxt<'tcx>, uv: ty::UnevaluatedConst<'tcx>) -> Self {
167171
Const::new_unevaluated(interner, uv)
168172
}

compiler/rustc_middle/src/ty/region.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,10 @@ impl<'tcx> rustc_type_ir::inherent::Region<TyCtxt<'tcx>> for Region<'tcx> {
148148
Region::new_bound(tcx, debruijn, ty::BoundRegion { var, kind: ty::BoundRegionKind::Anon })
149149
}
150150

151+
fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderRegion) -> Self {
152+
Region::new_placeholder(tcx, placeholder)
153+
}
154+
151155
fn new_static(tcx: TyCtxt<'tcx>) -> Self {
152156
tcx.lifetimes.re_static
153157
}

compiler/rustc_next_trait_solver/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,6 @@
1212
pub mod canonicalizer;
1313
pub mod coherence;
1414
pub mod delegate;
15+
pub mod placeholder;
1516
pub mod resolve;
1617
pub mod solve;
Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
use core::panic;
2+
3+
use rustc_type_ir::data_structures::IndexMap;
4+
use rustc_type_ir::inherent::*;
5+
use rustc_type_ir::{
6+
self as ty, InferCtxtLike, Interner, TypeFoldable, TypeFolder, TypeSuperFoldable,
7+
TypeVisitableExt,
8+
};
9+
10+
pub struct BoundVarReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
11+
where
12+
Infcx: InferCtxtLike<Interner = I>,
13+
I: Interner,
14+
{
15+
infcx: &'a Infcx,
16+
// These three maps track the bound variable that were replaced by placeholders. It might be
17+
// nice to remove these since we already have the `kind` in the placeholder; we really just need
18+
// the `var` (but we *could* bring that into scope if we were to track them as we pass them).
19+
mapped_regions: IndexMap<I::PlaceholderRegion, I::BoundRegion>,
20+
mapped_types: IndexMap<I::PlaceholderTy, I::BoundTy>,
21+
mapped_consts: IndexMap<I::PlaceholderConst, I::BoundConst>,
22+
// The current depth relative to *this* folding, *not* the entire normalization. In other words,
23+
// the depth of binders we've passed here.
24+
current_index: ty::DebruijnIndex,
25+
// The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy:
26+
// we don't actually create a universe until we see a bound var we have to replace.
27+
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
28+
}
29+
30+
impl<'a, Infcx, I> BoundVarReplacer<'a, Infcx, I>
31+
where
32+
Infcx: InferCtxtLike<Interner = I>,
33+
I: Interner,
34+
{
35+
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
36+
/// use a binding level above `universe_indices.len()`, we fail.
37+
pub fn replace_bound_vars<T: TypeFoldable<I>>(
38+
infcx: &'a Infcx,
39+
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
40+
value: T,
41+
) -> (
42+
T,
43+
IndexMap<I::PlaceholderRegion, I::BoundRegion>,
44+
IndexMap<I::PlaceholderTy, I::BoundTy>,
45+
IndexMap<I::PlaceholderConst, I::BoundConst>,
46+
) {
47+
let mut replacer = BoundVarReplacer {
48+
infcx,
49+
mapped_regions: Default::default(),
50+
mapped_types: Default::default(),
51+
mapped_consts: Default::default(),
52+
current_index: ty::INNERMOST,
53+
universe_indices,
54+
};
55+
56+
let value = value.fold_with(&mut replacer);
57+
58+
(value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
59+
}
60+
61+
fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
62+
let infcx = self.infcx;
63+
let index =
64+
self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
65+
let universe = self.universe_indices[index].unwrap_or_else(|| {
66+
for i in self.universe_indices.iter_mut().take(index + 1) {
67+
*i = i.or_else(|| Some(infcx.create_next_universe()))
68+
}
69+
self.universe_indices[index].unwrap()
70+
});
71+
universe
72+
}
73+
}
74+
75+
impl<Infcx, I> TypeFolder<I> for BoundVarReplacer<'_, Infcx, I>
76+
where
77+
Infcx: InferCtxtLike<Interner = I>,
78+
I: Interner,
79+
{
80+
fn cx(&self) -> I {
81+
self.infcx.cx()
82+
}
83+
84+
fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
85+
self.current_index.shift_in(1);
86+
let t = t.super_fold_with(self);
87+
self.current_index.shift_out(1);
88+
t
89+
}
90+
91+
fn fold_region(&mut self, r: I::Region) -> I::Region {
92+
match r.kind() {
93+
ty::ReBound(debruijn, _)
94+
if debruijn.as_usize()
95+
>= self.current_index.as_usize() + self.universe_indices.len() =>
96+
{
97+
panic!(
98+
"Bound vars {r:#?} outside of `self.universe_indices`: {:#?}",
99+
self.universe_indices
100+
);
101+
}
102+
ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
103+
let universe = self.universe_for(debruijn);
104+
let p = PlaceholderLike::new(universe, br);
105+
self.mapped_regions.insert(p, br);
106+
Region::new_placeholder(self.cx(), p)
107+
}
108+
_ => r,
109+
}
110+
}
111+
112+
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
113+
match t.kind() {
114+
ty::Bound(debruijn, _)
115+
if debruijn.as_usize() + 1
116+
> self.current_index.as_usize() + self.universe_indices.len() =>
117+
{
118+
panic!(
119+
"Bound vars {t:#?} outside of `self.universe_indices`: {:#?}",
120+
self.universe_indices
121+
);
122+
}
123+
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
124+
let universe = self.universe_for(debruijn);
125+
let p = PlaceholderLike::new(universe, bound_ty);
126+
self.mapped_types.insert(p, bound_ty);
127+
Ty::new_placeholder(self.cx(), p)
128+
}
129+
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
130+
_ => t,
131+
}
132+
}
133+
134+
fn fold_const(&mut self, ct: I::Const) -> I::Const {
135+
match ct.kind() {
136+
ty::ConstKind::Bound(debruijn, _)
137+
if debruijn.as_usize() + 1
138+
> self.current_index.as_usize() + self.universe_indices.len() =>
139+
{
140+
panic!(
141+
"Bound vars {ct:#?} outside of `self.universe_indices`: {:#?}",
142+
self.universe_indices
143+
);
144+
}
145+
ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
146+
let universe = self.universe_for(debruijn);
147+
let p = PlaceholderLike::new(universe, bound_const);
148+
self.mapped_consts.insert(p, bound_const);
149+
Const::new_placeholder(self.cx(), p)
150+
}
151+
_ => ct.super_fold_with(self),
152+
}
153+
}
154+
155+
fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
156+
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
157+
}
158+
}

compiler/rustc_trait_selection/src/traits/util.rs

Lines changed: 1 addition & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use rustc_middle::bug;
99
use rustc_middle::ty::{
1010
self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
1111
};
12+
pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
1213
use rustc_span::Span;
1314
use smallvec::{SmallVec, smallvec};
1415
use tracing::debug;
@@ -212,152 +213,6 @@ pub fn with_replaced_escaping_bound_vars<
212213
}
213214
}
214215

215-
pub struct BoundVarReplacer<'a, 'tcx> {
216-
infcx: &'a InferCtxt<'tcx>,
217-
// These three maps track the bound variable that were replaced by placeholders. It might be
218-
// nice to remove these since we already have the `kind` in the placeholder; we really just need
219-
// the `var` (but we *could* bring that into scope if we were to track them as we pass them).
220-
mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
221-
mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
222-
mapped_consts: FxIndexMap<ty::PlaceholderConst, ty::BoundVar>,
223-
// The current depth relative to *this* folding, *not* the entire normalization. In other words,
224-
// the depth of binders we've passed here.
225-
current_index: ty::DebruijnIndex,
226-
// The `UniverseIndex` of the binding levels above us. These are optional, since we are lazy:
227-
// we don't actually create a universe until we see a bound var we have to replace.
228-
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
229-
}
230-
231-
impl<'a, 'tcx> BoundVarReplacer<'a, 'tcx> {
232-
/// Returns `Some` if we *were* able to replace bound vars. If there are any bound vars that
233-
/// use a binding level above `universe_indices.len()`, we fail.
234-
pub fn replace_bound_vars<T: TypeFoldable<TyCtxt<'tcx>>>(
235-
infcx: &'a InferCtxt<'tcx>,
236-
universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
237-
value: T,
238-
) -> (
239-
T,
240-
FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion>,
241-
FxIndexMap<ty::PlaceholderType, ty::BoundTy>,
242-
FxIndexMap<ty::PlaceholderConst, ty::BoundVar>,
243-
) {
244-
let mapped_regions: FxIndexMap<ty::PlaceholderRegion, ty::BoundRegion> =
245-
FxIndexMap::default();
246-
let mapped_types: FxIndexMap<ty::PlaceholderType, ty::BoundTy> = FxIndexMap::default();
247-
let mapped_consts: FxIndexMap<ty::PlaceholderConst, ty::BoundVar> = FxIndexMap::default();
248-
249-
let mut replacer = BoundVarReplacer {
250-
infcx,
251-
mapped_regions,
252-
mapped_types,
253-
mapped_consts,
254-
current_index: ty::INNERMOST,
255-
universe_indices,
256-
};
257-
258-
let value = value.fold_with(&mut replacer);
259-
260-
(value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
261-
}
262-
263-
fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
264-
let infcx = self.infcx;
265-
let index =
266-
self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
267-
let universe = self.universe_indices[index].unwrap_or_else(|| {
268-
for i in self.universe_indices.iter_mut().take(index + 1) {
269-
*i = i.or_else(|| Some(infcx.create_next_universe()))
270-
}
271-
self.universe_indices[index].unwrap()
272-
});
273-
universe
274-
}
275-
}
276-
277-
impl<'tcx> TypeFolder<TyCtxt<'tcx>> for BoundVarReplacer<'_, 'tcx> {
278-
fn cx(&self) -> TyCtxt<'tcx> {
279-
self.infcx.tcx
280-
}
281-
282-
fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
283-
&mut self,
284-
t: ty::Binder<'tcx, T>,
285-
) -> ty::Binder<'tcx, T> {
286-
self.current_index.shift_in(1);
287-
let t = t.super_fold_with(self);
288-
self.current_index.shift_out(1);
289-
t
290-
}
291-
292-
fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
293-
match r.kind() {
294-
ty::ReBound(debruijn, _)
295-
if debruijn.as_usize()
296-
>= self.current_index.as_usize() + self.universe_indices.len() =>
297-
{
298-
bug!(
299-
"Bound vars {r:#?} outside of `self.universe_indices`: {:#?}",
300-
self.universe_indices
301-
);
302-
}
303-
ty::ReBound(debruijn, br) if debruijn >= self.current_index => {
304-
let universe = self.universe_for(debruijn);
305-
let p = ty::PlaceholderRegion { universe, bound: br };
306-
self.mapped_regions.insert(p, br);
307-
ty::Region::new_placeholder(self.infcx.tcx, p)
308-
}
309-
_ => r,
310-
}
311-
}
312-
313-
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
314-
match *t.kind() {
315-
ty::Bound(debruijn, _)
316-
if debruijn.as_usize() + 1
317-
> self.current_index.as_usize() + self.universe_indices.len() =>
318-
{
319-
bug!(
320-
"Bound vars {t:#?} outside of `self.universe_indices`: {:#?}",
321-
self.universe_indices
322-
);
323-
}
324-
ty::Bound(debruijn, bound_ty) if debruijn >= self.current_index => {
325-
let universe = self.universe_for(debruijn);
326-
let p = ty::PlaceholderType { universe, bound: bound_ty };
327-
self.mapped_types.insert(p, bound_ty);
328-
Ty::new_placeholder(self.infcx.tcx, p)
329-
}
330-
_ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
331-
_ => t,
332-
}
333-
}
334-
335-
fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
336-
match ct.kind() {
337-
ty::ConstKind::Bound(debruijn, _)
338-
if debruijn.as_usize() + 1
339-
> self.current_index.as_usize() + self.universe_indices.len() =>
340-
{
341-
bug!(
342-
"Bound vars {ct:#?} outside of `self.universe_indices`: {:#?}",
343-
self.universe_indices
344-
);
345-
}
346-
ty::ConstKind::Bound(debruijn, bound_const) if debruijn >= self.current_index => {
347-
let universe = self.universe_for(debruijn);
348-
let p = ty::PlaceholderConst { universe, bound: bound_const };
349-
self.mapped_consts.insert(p, bound_const);
350-
ty::Const::new_placeholder(self.infcx.tcx, p)
351-
}
352-
_ => ct.super_fold_with(self),
353-
}
354-
}
355-
356-
fn fold_predicate(&mut self, p: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
357-
if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
358-
}
359-
}
360-
361216
/// The inverse of [`BoundVarReplacer`]: replaces placeholders with the bound vars from which they came.
362217
pub struct PlaceholderReplacer<'a, 'tcx> {
363218
infcx: &'a InferCtxt<'tcx>,

compiler/rustc_type_ir/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ bitflags = "2.4.1"
99
derive-where = "1.2.7"
1010
ena = "0.14.3"
1111
indexmap = "2.0.0"
12-
rustc-hash = "1.1.0"
12+
rustc-hash = "2.0.0"
1313
rustc_ast_ir = { path = "../rustc_ast_ir", default-features = false }
1414
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
1515
rustc_index = { path = "../rustc_index", default-features = false }

compiler/rustc_type_ir/src/inherent.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,8 @@ pub trait Region<I: Interner<Region = Self>>:
228228

229229
fn new_static(interner: I) -> Self;
230230

231+
fn new_placeholder(interner: I, var: I::PlaceholderRegion) -> Self;
232+
231233
fn is_bound(self) -> bool {
232234
matches!(self.kind(), ty::ReBound(..))
233235
}
@@ -254,6 +256,8 @@ pub trait Const<I: Interner<Const = Self>>:
254256

255257
fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
256258

259+
fn new_placeholder(interner: I, param: I::PlaceholderConst) -> Self;
260+
257261
fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
258262

259263
fn new_expr(interner: I, expr: I::ExprConst) -> Self;

0 commit comments

Comments
 (0)