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 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 mut replacer = BoundVarReplacer {
51 infcx,
52 mapped_regions: Default::default(),
53 mapped_types: Default::default(),
54 mapped_consts: Default::default(),
55 current_index: ty::INNERMOST,
56 universe_indices,
57 };
58
59 let value = value.fold_with(&mut replacer);
60
61 (value, replacer.mapped_regions, replacer.mapped_types, replacer.mapped_consts)
62 }
63
64 fn universe_for(&mut self, debruijn: ty::DebruijnIndex) -> ty::UniverseIndex {
65 let infcx = self.infcx;
66 let index =
67 self.universe_indices.len() + self.current_index.as_usize() - debruijn.as_usize() - 1;
68 let universe = self.universe_indices[index].unwrap_or_else(|| {
69 for i in self.universe_indices.iter_mut().take(index + 1) {
70 *i = i.or_else(|| Some(infcx.create_next_universe()))
71 }
72 self.universe_indices[index].unwrap()
73 });
74 universe
75 }
76}
77
78impl<Infcx, I> TypeFolder<I> for BoundVarReplacer<'_, Infcx, I>
79where
80 Infcx: InferCtxtLike<Interner = I>,
81 I: Interner,
82{
83 fn cx(&self) -> I {
84 self.infcx.cx()
85 }
86
87 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
88 self.current_index.shift_in(1);
89 let t = t.super_fold_with(self);
90 self.current_index.shift_out(1);
91 t
92 }
93
94 fn fold_region(&mut self, r: I::Region) -> I::Region {
95 match r.kind() {
96 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
97 if debruijn.as_usize()
98 >= self.current_index.as_usize() + self.universe_indices.len() =>
99 {
100 {
::core::panicking::panic_fmt(format_args!("Bound vars {1:#?} outside of `self.universe_indices`: {0:#?}",
self.universe_indices, r));
};panic!(
101 "Bound vars {r:#?} outside of `self.universe_indices`: {:#?}",
102 self.universe_indices
103 );
104 }
105 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
106 if debruijn >= self.current_index =>
107 {
108 let universe = self.universe_for(debruijn);
109 let p = PlaceholderRegion::new(universe, br);
110 self.mapped_regions.insert(p, br);
111 Region::new_placeholder(self.cx(), p)
112 }
113 _ => r,
114 }
115 }
116
117 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
118 match t.kind() {
119 ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
120 if debruijn.as_usize() + 1
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, t));
};panic!(
124 "Bound vars {t:#?} outside of `self.universe_indices`: {:#?}",
125 self.universe_indices
126 );
127 }
128 ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
129 if debruijn >= self.current_index =>
130 {
131 let universe = self.universe_for(debruijn);
132 let p = PlaceholderType::new(universe, bound_ty);
133 self.mapped_types.insert(p, bound_ty);
134 Ty::new_placeholder(self.cx(), p)
135 }
136 _ if t.has_vars_bound_at_or_above(self.current_index) => t.super_fold_with(self),
137 _ => t,
138 }
139 }
140
141 fn fold_const(&mut self, ct: I::Const) -> I::Const {
142 match ct.kind() {
143 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _)
144 if debruijn.as_usize() + 1
145 > self.current_index.as_usize() + self.universe_indices.len() =>
146 {
147 {
::core::panicking::panic_fmt(format_args!("Bound vars {1:#?} outside of `self.universe_indices`: {0:#?}",
self.universe_indices, ct));
};panic!(
148 "Bound vars {ct:#?} outside of `self.universe_indices`: {:#?}",
149 self.universe_indices
150 );
151 }
152 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)
153 if debruijn >= self.current_index =>
154 {
155 let universe = self.universe_for(debruijn);
156 let p = PlaceholderConst::new(universe, bound_const);
157 self.mapped_consts.insert(p, bound_const);
158 Const::new_placeholder(self.cx(), p)
159 }
160 _ => ct.super_fold_with(self),
161 }
162 }
163
164 fn fold_predicate(&mut self, p: I::Predicate) -> I::Predicate {
165 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
166 }
167}
168
169pub struct PlaceholderReplacer<'a, Infcx, I = <Infcx as InferCtxtLike>::Interner>
171where
172 Infcx: InferCtxtLike<Interner = I>,
173 I: Interner,
174{
175 infcx: &'a Infcx,
176 mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
177 mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
178 mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
179 universe_indices: &'a [Option<ty::UniverseIndex>],
180 current_index: ty::DebruijnIndex,
181}
182
183impl<'a, Infcx, I> PlaceholderReplacer<'a, Infcx, I>
184where
185 Infcx: InferCtxtLike<Interner = I>,
186 I: Interner,
187{
188 pub fn replace_placeholders<T: TypeFoldable<I>>(
189 infcx: &'a Infcx,
190 mapped_regions: IndexMap<ty::PlaceholderRegion<I>, ty::BoundRegion<I>>,
191 mapped_types: IndexMap<ty::PlaceholderType<I>, ty::BoundTy<I>>,
192 mapped_consts: IndexMap<ty::PlaceholderConst<I>, ty::BoundConst<I>>,
193 universe_indices: &'a [Option<ty::UniverseIndex>],
194 value: T,
195 ) -> T {
196 let mut replacer = PlaceholderReplacer {
197 infcx,
198 mapped_regions,
199 mapped_types,
200 mapped_consts,
201 universe_indices,
202 current_index: ty::INNERMOST,
203 };
204 value.fold_with(&mut replacer)
205 }
206}
207
208impl<'a, Infcx, I> TypeFolder<I> for PlaceholderReplacer<'a, Infcx, I>
209where
210 Infcx: InferCtxtLike<Interner = I>,
211 I: Interner,
212{
213 fn cx(&self) -> I {
214 self.infcx.cx()
215 }
216
217 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
218 if !t.has_placeholders() && !t.has_infer() {
219 return t;
220 }
221 self.current_index.shift_in(1);
222 let t = t.super_fold_with(self);
223 self.current_index.shift_out(1);
224 t
225 }
226
227 fn fold_region(&mut self, r0: I::Region) -> I::Region {
228 let r1 = match r0.kind() {
229 ty::ReVar(vid) => self.infcx.opportunistic_resolve_lt_var(vid),
230 _ => r0,
231 };
232
233 let r2 = match r1.kind() {
234 ty::RePlaceholder(p) => {
235 let replace_var = self.mapped_regions.get(&p);
236 match replace_var {
237 Some(replace_var) => {
238 let index = self
239 .universe_indices
240 .iter()
241 .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))
242 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
243 let db = ty::DebruijnIndex::from_usize(
244 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
245 );
246 Region::new_bound(self.cx(), db, *replace_var)
247 }
248 None => r1,
249 }
250 }
251 _ => r1,
252 };
253
254 {
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:254",
"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(254u32),
::tracing_core::__macro_support::Option::Some("rustc_next_trait_solver::placeholder"),
::tracing_core::field::FieldSet::new(&["message", "r0",
"r1", "r2"],
::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};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("fold_region")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r0) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r1) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r2) as
&dyn Value))])
});
} else { ; }
};debug!(?r0, ?r1, ?r2, "fold_region");
255
256 r2
257 }
258
259 fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
260 let ty = self.infcx.shallow_resolve(ty);
261 match ty.kind() {
262 ty::Placeholder(p) => {
263 let replace_var = self.mapped_types.get(&p);
264 match replace_var {
265 Some(replace_var) => {
266 let index = self
267 .universe_indices
268 .iter()
269 .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))
270 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
271 let db = ty::DebruijnIndex::from_usize(
272 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
273 );
274 Ty::new_bound(self.infcx.cx(), db, *replace_var)
275 }
276 None => {
277 if ty.has_infer() {
278 ty.super_fold_with(self)
279 } else {
280 ty
281 }
282 }
283 }
284 }
285
286 _ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
287 _ => ty,
288 }
289 }
290
291 fn fold_const(&mut self, ct: I::Const) -> I::Const {
292 let ct = self.infcx.shallow_resolve_const(ct);
293 if let ty::ConstKind::Placeholder(p) = ct.kind() {
294 let replace_var = self.mapped_consts.get(&p);
295 match replace_var {
296 Some(replace_var) => {
297 let index = self
298 .universe_indices
299 .iter()
300 .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))
301 .unwrap_or_else(|| {
::core::panicking::panic_fmt(format_args!("Unexpected placeholder universe."));
}panic!("Unexpected placeholder universe."));
302 let db = ty::DebruijnIndex::from_usize(
303 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
304 );
305 Const::new_bound(self.infcx.cx(), db, *replace_var)
306 }
307 None => {
308 if ct.has_infer() {
309 ct.super_fold_with(self)
310 } else {
311 ct
312 }
313 }
314 }
315 } else {
316 ct.super_fold_with(self)
317 }
318 }
319}