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