1use core::panic;
2
3use rustc_type_ir::data_structures::IndexMap;
4use rustc_type_ir::inherent::*;
5use rustc_type_ir::{
6 self as ty, Const, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion,
7 PlaceholderType, PredicateProxy, Region, TypeFoldable, TypeFolder, TypeSuperFoldable,
8 TypeVisitableExt,
9};
10use tracing::debug;
11
12pub struct BoundVarReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
13where
14 Infcx: InferCtxtLike<Interner = I>,
15 I: Interner,
16{
17 infcx: &'a Infcx,
18 mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
22 mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
23 mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
24 current_index: ty::DebruijnIndex,
27 universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
30}
31
32impl<'a, Infcx, I> BoundVarReplacer<'a, Infcx, I>
33where
34 Infcx: InferCtxtLike<Interner = I>,
35 I: Interner,
36{
37 pub fn replace_bound_vars<T: TypeFoldable<I>>(
42 infcx: &'a Infcx,
43 universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
44 value: T,
45 ) -> (
46 T,
47 IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
48 IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
49 IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
50 ) {
51 let old_universes = universe_indices.clone();
52 let mut replacer = BoundVarReplacer {
53 infcx,
54 mapped_regions: Default::default(),
55 mapped_types: Default::default(),
56 mapped_consts: Default::default(),
57 current_index: ty::INNERMOST,
58 universe_indices,
59 };
60
61 let value = value.fold_with(&mut replacer);
62 let BoundVarReplacer {
63 mapped_regions,
64 mapped_types,
65 mapped_consts,
66 universe_indices,
67 infcx: _,
68 current_index: _,
69 } = replacer;
70
71 if infcx.cx().assumptions_on_binders() {
72 for (old, new) in old_universes.into_iter().zip(universe_indices.iter()) {
73 if let (None, Some(new)) = (old, new) {
74 infcx.insert_placeholder_assumptions(
77 *new,
78 rustc_type_ir::region_constraint::Assumptions::empty(),
79 );
80 }
81 }
82 }
83
84 (value, mapped_regions, mapped_types, mapped_consts)
85 }
86
87 fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
88 let infcx = self.infcx;
89 let index =
90 self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
91 let universe = self.universe_indices[index].unwrap_or_else(|| {
92 for i in self.universe_indices.iter_mut().take(index + 1) {
93 *i = i.or_else(|| Some(infcx.create_next_universe()))
94 }
95 self.universe_indices[index].unwrap()
96 });
97 universe
98 }
99}
100
101impl<Infcx, I> TypeFolder<I> for BoundVarReplacer<'_, Infcx, I>
102where
103 Infcx: InferCtxtLike<Interner = I>,
104 I: Interner,
105{
106 fn cx(&self) -> I {
107 self.infcx.cx()
108 }
109
110 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
111 self.current_index.shift_in(1);
112 let t = t.super_fold_with(self);
113 self.current_index.shift_out(1);
114 t
115 }
116
117 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
118 match r.kind() {
119 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
120 if debruijn.as_usize()
121 >= self.current_index.as_usize() + self.universe_indices.len() =>
122 {
123 {
::core::panicking::panic_fmt(format_args!("Bound vars {1:#?} outside of `self.universe_indices`: {0:#?}",
self.universe_indices, r));
};panic!(
124 "Bound vars {r:#?} outside of `self.universe_indices`: {:#?}",
125 self.universe_indices
126 );
127 }
128 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
129 if debruijn >= self.current_index =>
130 {
131 let universe = self.universe_for(debruijn);
132 let p = PlaceholderRegion::new(universe, br);
133 self.mapped_regions.insert(p, br);
134 Region::new_placeholder(self.cx(), p)
135 }
136 _ => r,
137 }
138 }
139
140 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
141 match t.kind() {
142 ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
143 if debruijn.as_usize() + 1
144 > self.current_index.as_usize() + self.universe_indices.len() =>
145 {
146 {
::core::panicking::panic_fmt(format_args!("Bound vars {1:#?} outside of `self.universe_indices`: {0:#?}",
self.universe_indices, t));
};panic!(
147 "Bound vars {t:#?} outside of `self.universe_indices`: {:#?}",
148 self.universe_indices
149 );
150 }
151 ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
152 if debruijn >= self.current_index =>
153 {
154 let universe = self.universe_for(debruijn);
155 let p = PlaceholderType::new(universe, bound_ty);
156 self.mapped_types.insert(p, bound_ty);
157 Ty::new_placeholder(self.cx(), p)
158 }
159 _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
160 _ => t,
161 }
162 }
163
164 fn fold_const(&mut self, ct: Const<I>) -> Const<I> {
165 match ct.kind() {
166 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
167 if debruijn.as_usize() + 1
168 > self.current_index.as_usize() + self.universe_indices.len() =>
169 {
170 {
::core::panicking::panic_fmt(format_args!("Bound vars {1:#?} outside of `self.universe_indices`: {0:#?}",
self.universe_indices, ct));
};panic!(
171 "Bound vars {ct:#?} outside of `self.universe_indices`: {:#?}",
172 self.universe_indices
173 );
174 }
175 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)
176 if debruijn >= self.current_index =>
177 {
178 let universe = self.universe_for(debruijn);
179 let p = PlaceholderConst::new(universe, bound_const);
180 self.mapped_consts.insert(p, bound_const);
181 Const::new_placeholder(self.cx(), p)
182 }
183 _ => ct.super_fold_with(self),
184 }
185 }
186
187 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
188 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
189 }
190}
191
192pub struct PlaceholderReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
194where
195 Infcx: InferCtxtLike<Interner = I>,
196 I: Interner,
197{
198 infcx: &'a Infcx,
199 mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
200 mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
201 mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
202 universe_indices: &'a [Option<ty::UniverseIndex>],
203 current_index: ty::DebruijnIndex,
204}
205
206impl<'a, Infcx, I> PlaceholderReplacer<'a, Infcx, I>
207where
208 Infcx: InferCtxtLike<Interner = I>,
209 I: Interner,
210{
211 pub fn replace_placeholders<T: TypeFoldable<I>>(
212 infcx: &'a Infcx,
213 mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
214 mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
215 mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
216 universe_indices: &'a [Option<ty::UniverseIndex>],
217 value: T,
218 ) -> T {
219 let mut replacer = PlaceholderReplacer {
220 infcx,
221 mapped_regions,
222 mapped_types,
223 mapped_consts,
224 universe_indices,
225 current_index: ty::INNERMOST,
226 };
227 value.fold_with(&mut replacer)
228 }
229}
230
231impl<'a, Infcx, I> TypeFolder<I> for PlaceholderReplacer<'a, Infcx, I>
232where
233 Infcx: InferCtxtLike<Interner = I>,
234 I: Interner,
235{
236 fn cx(&self) -> I {
237 self.infcx.cx()
238 }
239
240 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
241 if !t.has_placeholders() && !t.has_infer() {
242 return t;
243 }
244 self.current_index.shift_in(1);
245 let t = t.super_fold_with(self);
246 self.current_index.shift_out(1);
247 t
248 }
249
250 fn fold_region(&mut self, r0: Region<I>) -> Region<I> {
251 let r1 = match r0.kind() {
252 ty::ReVar(vid) => self.infcx.shallow_resolve_region_var(vid),
253 _ => r0,
254 };
255
256 let r2 = match r1.kind() {
257 ty::RePlaceholder(p) => {
258 let replace_var = self.mapped_regions.get(&p);
259 match replace_var {
260 Some(replace_var) => {
261 let index = self
262 .universe_indices
263 .iter()
264 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
265 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
266 let db = ty::DebruijnIndex::from_usize(
267 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
268 );
269 Region::new_bound(self.cx(), db, *replace_var)
270 }
271 None => r1,
272 }
273 }
274 _ => r1,
275 };
276
277 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/0abfedbc7cd4e725f126913880c95800394f7c37/compiler/rustc_next_trait_solver/src/placeholder.rs:277",
"rustc_next_trait_solver::placeholder",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0abfedbc7cd4e725f126913880c95800394f7c37/compiler/rustc_next_trait_solver/src/placeholder.rs"),
::tracing_core::__macro_support::Option::Some(277u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::placeholder"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r0")
}> =
::tracing::__macro_support::FieldName::new("r0");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r1")
}> =
::tracing::__macro_support::FieldName::new("r1");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r2")
}> =
::tracing::__macro_support::FieldName::new("r2");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("fold_region")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r0)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r1)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r2)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?r0, ?r1, ?r2, "fold_region");
278
279 r2
280 }
281
282 fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
283 let ty = self.infcx.shallow_resolve(ty);
284 match ty.kind() {
285 ty::Placeholder(p) => {
286 let replace_var = self.mapped_types.get(&p);
287 match replace_var {
288 Some(replace_var) => {
289 let index = self
290 .universe_indices
291 .iter()
292 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
293 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
294 let db = ty::DebruijnIndex::from_usize(
295 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
296 );
297 Ty::new_bound(self.infcx.cx(), db, *replace_var)
298 }
299 None => {
300 if ty.has_infer() {
301 ty.super_fold_with(self)
302 } else {
303 ty
304 }
305 }
306 }
307 }
308
309 _ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
310 _ => ty,
311 }
312 }
313
314 fn fold_const(&mut self, ct: Const<I>) -> Const<I> {
315 let ct = self.infcx.shallow_resolve_const(ct);
316 if let ty::ConstKind::Placeholder(p) = ct.kind() {
317 let replace_var = self.mapped_consts.get(&p);
318 match replace_var {
319 Some(replace_var) => {
320 let index = self
321 .universe_indices
322 .iter()
323 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
324 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
325 let db = ty::DebruijnIndex::from_usize(
326 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
327 );
328 Const::new_bound(self.infcx.cx(), db, *replace_var)
329 }
330 None => {
331 if ct.has_infer() {
332 ct.super_fold_with(self)
333 } else {
334 ct
335 }
336 }
337 }
338 } else {
339 ct.super_fold_with(self)
340 }
341 }
342}