1use std::convert::Infallible;
49use std::mem;
50use std::sync::Arc;
51
52use rustc_index::{Idx, IndexVec};
53use smallvec::SmallVec;
54use thin_vec::ThinVec;
55use tracing::{debug, instrument};
56
57use crate::data_structures::DelayedMap;
58use crate::inherent::*;
59use crate::visit::{TypeVisitable, TypeVisitableExt as _};
60use crate::{
61 self as ty, Binder, BoundVarIndexKind, ClauseKind, Const, Flags, Interner, ProjectionClause,
62 Region, TypeSuperVisitable,
63};
64
65pub trait TypeFoldable<I: Interner>: TypeVisitable<I> + Clone {
77 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error>;
88
89 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
103}
104
105pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
107 fn try_super_fold_with<F: FallibleTypeFolder<I>>(
114 self,
115 folder: &mut F,
116 ) -> Result<Self, F::Error>;
117
118 fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
122}
123
124pub trait TypeFolder<I: Interner>: Sized {
130 fn cx(&self) -> I;
131
132 fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
133 where
134 T: TypeFoldable<I>,
135 {
136 t.super_fold_with(self)
137 }
138
139 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
140 t.super_fold_with(self)
141 }
142
143 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
146 r
147 }
148
149 fn fold_const(&mut self, c: Const<I>) -> Const<I> {
150 c.super_fold_with(self)
151 }
152
153 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
154 p.super_fold_with(self)
155 }
156
157 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
158 c.super_fold_with(self)
159 }
160}
161
162pub trait PredicateProxy<I: Interner>:
169 TypeSuperFoldable<I> + TypeSuperVisitable<I> + Flags + Copy
170{
171 fn allow_normalization(&self) -> bool;
172
173 fn clause_kind_unchecked(&self) -> Option<Binder<I, ClauseKind<I>>>;
179
180 fn map_projection(
183 self,
184 cx: I,
185 f: impl FnOnce(Binder<I, ProjectionClause<I>>) -> Binder<I, ProjectionClause<I>>,
186 ) -> Option<Self>;
187}
188
189pub trait FallibleTypeFolder<I: Interner>: Sized {
197 type Error;
198
199 fn cx(&self) -> I;
200
201 fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Self::Error>
202 where
203 T: TypeFoldable<I>,
204 {
205 t.try_super_fold_with(self)
206 }
207
208 fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> {
209 t.try_super_fold_with(self)
210 }
211
212 fn try_fold_region(&mut self, r: Region<I>) -> Result<Region<I>, Self::Error> {
215 Ok(r)
216 }
217
218 fn try_fold_const(&mut self, c: Const<I>) -> Result<Const<I>, Self::Error> {
219 c.try_super_fold_with(self)
220 }
221
222 fn try_fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> Result<P, Self::Error> {
223 p.try_super_fold_with(self)
224 }
225
226 fn try_fold_clauses(&mut self, c: I::Clauses) -> Result<I::Clauses, Self::Error> {
227 c.try_super_fold_with(self)
228 }
229}
230
231impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
235 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
236 Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
237 }
238
239 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
240 (self.0.fold_with(folder), self.1.fold_with(folder))
241 }
242}
243
244impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
245 for (A, B, C)
246{
247 fn try_fold_with<F: FallibleTypeFolder<I>>(
248 self,
249 folder: &mut F,
250 ) -> Result<(A, B, C), F::Error> {
251 Ok((
252 self.0.try_fold_with(folder)?,
253 self.1.try_fold_with(folder)?,
254 self.2.try_fold_with(folder)?,
255 ))
256 }
257
258 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
259 (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
260 }
261}
262
263impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
264 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
265 Ok(match self {
266 Some(v) => Some(v.try_fold_with(folder)?),
267 None => None,
268 })
269 }
270
271 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
272 Some(self?.fold_with(folder))
273 }
274}
275
276impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
277 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
278 Ok(match self {
279 Ok(v) => Ok(v.try_fold_with(folder)?),
280 Err(e) => Err(e.try_fold_with(folder)?),
281 })
282 }
283
284 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
285 match self {
286 Ok(v) => Ok(v.fold_with(folder)),
287 Err(e) => Err(e.fold_with(folder)),
288 }
289 }
290}
291
292fn fold_arc<T: Clone, E>(
293 mut arc: Arc<T>,
294 fold: impl FnOnce(T) -> Result<T, E>,
295) -> Result<Arc<T>, E> {
296 unsafe {
300 Arc::make_mut(&mut arc);
306
307 let ptr = Arc::into_raw(arc).cast::<mem::ManuallyDrop<T>>();
310 let mut unique = Arc::from_raw(ptr);
311
312 let slot = Arc::get_mut(&mut unique).unwrap_unchecked();
316
317 let owned = mem::ManuallyDrop::take(slot);
322 let folded = fold(owned)?;
323 *slot = mem::ManuallyDrop::new(folded);
324
325 Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
327 }
328}
329
330impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
331 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
332 fold_arc(self, |t| t.try_fold_with(folder))
333 }
334
335 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
336 match fold_arc::<T, Infallible>(self, |t| Ok(t.fold_with(folder))) {
337 Ok(t) => t,
338 }
339 }
340}
341
342impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
343 fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
344 *self = (*self).try_fold_with(folder)?;
345 Ok(self)
346 }
347
348 fn fold_with<F: TypeFolder<I>>(mut self, folder: &mut F) -> Self {
349 *self = (*self).fold_with(folder);
350 self
351 }
352}
353
354impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
355 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
356 self.into_iter().map(|t| t.try_fold_with(folder)).collect()
357 }
358
359 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
360 self.into_iter().map(|t| t.fold_with(folder)).collect()
361 }
362}
363
364impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for ThinVec<T> {
365 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
366 self.into_iter().map(|t| t.try_fold_with(folder)).collect()
367 }
368
369 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
370 self.into_iter().map(|t| t.fold_with(folder)).collect()
371 }
372}
373
374impl<I: Interner, T: TypeFoldable<I>, const N: usize> TypeFoldable<I> for SmallVec<[T; N]> {
375 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
376 self.into_iter().map(|t| t.try_fold_with(folder)).collect()
377 }
378
379 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
380 self.into_iter().map(|t| t.fold_with(folder)).collect()
381 }
382}
383
384impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
385 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
386 Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice)
387 }
388
389 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
390 Vec::into_boxed_slice(Vec::from(self).fold_with(folder))
391 }
392}
393
394impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
395 fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
396 self.raw.try_fold_with(folder).map(IndexVec::from_raw)
397 }
398
399 fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
400 IndexVec::from_raw(self.raw.fold_with(folder))
401 }
402}
403
404struct Shifter<I: Interner> {
414 cx: I,
415 current_index: ty::DebruijnIndex,
416 amount: u32,
417}
418
419impl<I: Interner> Shifter<I> {
420 fn new(cx: I, amount: u32) -> Self {
421 Shifter { cx, current_index: ty::INNERMOST, amount }
422 }
423}
424
425impl<I: Interner> TypeFolder<I> for Shifter<I> {
426 fn cx(&self) -> I {
427 self.cx
428 }
429
430 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
431 self.current_index.shift_in(1);
432 let t = t.super_fold_with(self);
433 self.current_index.shift_out(1);
434 t
435 }
436
437 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
438 match r.kind() {
439 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
440 if debruijn >= self.current_index =>
441 {
442 let debruijn = debruijn.shifted_in(self.amount);
443 Region::new_bound(self.cx, debruijn, br)
444 }
445 _ => r,
446 }
447 }
448
449 fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
450 match ty.kind() {
451 ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty)
452 if debruijn >= self.current_index =>
453 {
454 let debruijn = debruijn.shifted_in(self.amount);
455 Ty::new_bound(self.cx, debruijn, bound_ty)
456 }
457
458 _ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
459 _ => ty,
460 }
461 }
462
463 fn fold_const(&mut self, ct: Const<I>) -> Const<I> {
464 match ct.kind() {
465 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ct)
466 if debruijn >= self.current_index =>
467 {
468 let debruijn = debruijn.shifted_in(self.amount);
469 Const::new_bound(self.cx, debruijn, bound_ct)
470 }
471 _ => ct.super_fold_with(self),
472 }
473 }
474
475 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
476 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
477 }
478
479 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
480 if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
481 }
482}
483
484pub fn shift_region<I: Interner>(cx: I, region: Region<I>, amount: u32) -> Region<I> {
485 match region.kind() {
486 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) if amount > 0 => {
487 Region::new_bound(cx, debruijn.shifted_in(amount), br)
488 }
489 _ => region,
490 }
491}
492
493{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() || { false }
{
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("shift_vars",
"rustc_type_ir::fold", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(493u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("amount")
}> =
::tracing::__macro_support::FieldName::new("amount");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&amount as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: T = loop {};
return __tracing_attr_fake_return;
}
{
if amount == 0 || !value.has_escaping_bound_vars() {
value
} else { value.fold_with(&mut Shifter::new(cx, amount)) }
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs:493",
"rustc_type_ir::fold", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(493u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(level = "trace", skip(cx), ret)]
494pub fn shift_vars<I: Interner, T>(cx: I, value: T, amount: u32) -> T
495where
496 T: TypeFoldable<I>,
497{
498 if amount == 0 || !value.has_escaping_bound_vars() {
499 value
500 } else {
501 value.fold_with(&mut Shifter::new(cx, amount))
502 }
503}
504
505pub trait BoundVarReplacerDelegate<I: Interner> {
513 fn replace_region(&mut self, br: ty::BoundRegion<I>) -> Region<I>;
514 fn replace_ty(&mut self, bt: ty::BoundTy<I>) -> I::Ty;
515 fn replace_const(&mut self, bc: ty::BoundConst<I>) -> Const<I>;
516}
517
518pub struct FnMutDelegate<'a, I: Interner> {
520 pub regions: &'a mut (dyn FnMut(ty::BoundRegion<I>) -> Region<I> + 'a),
521 pub types: &'a mut (dyn FnMut(ty::BoundTy<I>) -> I::Ty + 'a),
522 pub consts: &'a mut (dyn FnMut(ty::BoundConst<I>) -> Const<I> + 'a),
523}
524
525impl<I: Interner> BoundVarReplacerDelegate<I> for FnMutDelegate<'_, I> {
526 fn replace_region(&mut self, br: ty::BoundRegion<I>) -> Region<I> {
527 (self.regions)(br)
528 }
529
530 fn replace_ty(&mut self, bt: ty::BoundTy<I>) -> I::Ty {
531 (self.types)(bt)
532 }
533
534 fn replace_const(&mut self, bc: ty::BoundConst<I>) -> Const<I> {
535 (self.consts)(bc)
536 }
537}
538
539pub struct BoundVarReplacer<I: Interner, D> {
541 cx: I,
542 current_index: ty::DebruijnIndex,
545 delegate: D,
546 cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
549}
550
551impl<I: Interner, D: BoundVarReplacerDelegate<I>> BoundVarReplacer<I, D> {
552 pub fn new(cx: I, delegate: D) -> Self {
553 Self { cx, current_index: ty::INNERMOST, delegate, cache: Default::default() }
554 }
555}
556
557impl<I: Interner, D: BoundVarReplacerDelegate<I>> TypeFolder<I> for BoundVarReplacer<I, D> {
558 fn cx(&self) -> I {
559 self.cx
560 }
561
562 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
563 self.current_index.shift_in(1);
564 let t = t.super_fold_with(self);
565 self.current_index.shift_out(1);
566 t
567 }
568
569 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
570 match t.kind() {
571 ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty)
572 if debruijn == self.current_index =>
573 {
574 let ty = self.delegate.replace_ty(bound_ty);
575 if true {
if !!ty.has_vars_bound_above(ty::INNERMOST) {
::core::panicking::panic("assertion failed: !ty.has_vars_bound_above(ty::INNERMOST)")
};
};debug_assert!(!ty.has_vars_bound_above(ty::INNERMOST));
576 shift_vars(self.cx, ty, self.current_index.as_u32())
577 }
578 _ => {
579 if !t.has_vars_bound_at_or_above(self.current_index) {
580 t
581 } else if let Some(&t) = self.cache.get(&(self.current_index, t)) {
582 t
583 } else {
584 let res = t.super_fold_with(self);
585 if !self.cache.insert((self.current_index, t), res) {
::core::panicking::panic("assertion failed: self.cache.insert((self.current_index, t), res)")
};assert!(self.cache.insert((self.current_index, t), res));
586 res
587 }
588 }
589 }
590 }
591
592 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
593 match r.kind() {
594 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
595 if debruijn == self.current_index =>
596 {
597 let region = self.delegate.replace_region(br);
598 if let ty::ReBound(ty::BoundVarIndexKind::Bound(inner), br) = region.kind() {
599 {
match (&inner, &ty::INNERMOST) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(inner, ty::INNERMOST);
602 Region::new_bound(self.cx, debruijn, br)
603 } else {
604 region
605 }
606 }
607 _ => r,
608 }
609 }
610
611 fn fold_const(&mut self, ct: Const<I>) -> Const<I> {
612 match ct.kind() {
613 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)
614 if debruijn == self.current_index =>
615 {
616 let ct = self.delegate.replace_const(bound_const);
617 if true {
if !!ct.has_vars_bound_above(ty::INNERMOST) {
::core::panicking::panic("assertion failed: !ct.has_vars_bound_above(ty::INNERMOST)")
};
};debug_assert!(!ct.has_vars_bound_above(ty::INNERMOST));
618 shift_vars(self.cx, ct, self.current_index.as_u32())
619 }
620 _ => ct.super_fold_with(self),
621 }
622 }
623
624 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
625 if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
626 }
627
628 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
629 if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
630 }
631}
632
633pub fn replace_escaping_bound_vars_uncached<I: Interner, T: TypeFoldable<I>>(
635 cx: I,
636 value: T,
637 delegate: impl BoundVarReplacerDelegate<I>,
638) -> T {
639 if !value.has_escaping_bound_vars() {
640 value
641 } else {
642 value.fold_with(&mut BoundVarReplacer::new(cx, delegate))
643 }
644}
645
646pub fn shift_bound_var_indices<I: Interner, T: TypeFoldable<I>>(
649 cx: I,
650 bound_vars: usize,
651 value: T,
652) -> T {
653 if bound_vars == 0 || !value.has_escaping_bound_vars() {
654 return value;
655 }
656
657 let shift_bv = |bv: ty::BoundVar| bv + bound_vars;
658 replace_escaping_bound_vars_uncached(
659 cx,
660 value,
661 FnMutDelegate {
662 regions: &mut |r: ty::BoundRegion<I>| {
663 Region::new_bound(
664 cx,
665 ty::INNERMOST,
666 ty::BoundRegion { var: shift_bv(r.var), kind: r.kind },
667 )
668 },
669 types: &mut |t: ty::BoundTy<I>| {
670 Ty::new_bound(cx, ty::INNERMOST, ty::BoundTy { var: shift_bv(t.var), kind: t.kind })
671 },
672 consts: &mut |c: ty::BoundConst<I>| {
673 Const::new_bound(cx, ty::INNERMOST, ty::BoundConst::new(shift_bv(c.var)))
674 },
675 },
676 )
677}
678
679pub fn fold_regions<I: Interner, T>(
683 cx: I,
684 value: T,
685 f: impl FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
686) -> T
687where
688 T: TypeFoldable<I>,
689{
690 value.fold_with(&mut RegionFolder::new(cx, f))
691}
692
693pub struct RegionFolder<I, F> {
701 cx: I,
702
703 current_index: ty::DebruijnIndex,
707
708 fold_region_fn: F,
712}
713
714impl<I, F> RegionFolder<I, F> {
715 #[inline]
716 pub fn new(cx: I, fold_region_fn: F) -> RegionFolder<I, F> {
717 RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn }
718 }
719}
720
721impl<I, F> TypeFolder<I> for RegionFolder<I, F>
722where
723 I: Interner,
724 F: FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
725{
726 fn cx(&self) -> I {
727 self.cx
728 }
729
730 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
731 self.current_index.shift_in(1);
732 let t = t.super_fold_with(self);
733 self.current_index.shift_out(1);
734 t
735 }
736
737 {}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() || { false }
{
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("fold_region",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(737u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("r")
}> =
::tracing::__macro_support::FieldName::new("r");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&r)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Region<I> = loop {};
return __tracing_attr_fake_return;
}
{
match r.kind() {
ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _) if
debruijn < self.current_index => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs:743",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(743u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.current_index")
}> =
::tracing::__macro_support::FieldName::new("self.current_index");
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!("skipped bound region")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
r
}
ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs:747",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(747u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.current_index")
}> =
::tracing::__macro_support::FieldName::new("self.current_index");
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!("skipped bound region")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
r
}
_ => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs:751",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(751u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.current_index")
}> =
::tracing::__macro_support::FieldName::new("self.current_index");
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!("folding free region")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.current_index)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
(self.fold_region_fn)(r, self.current_index)
}
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs:737",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/5d8fec0669a64607db9ccbf663e7c23125bf4748/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(737u32),
::tracing_core::__macro_support::Option::Some("rustc_type_ir::fold"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
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(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(skip(self), level = "debug", ret)]
738 fn fold_region(&mut self, r: Region<I>) -> Region<I> {
739 match r.kind() {
740 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
741 if debruijn < self.current_index =>
742 {
743 debug!(?self.current_index, "skipped bound region");
744 r
745 }
746 ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
747 debug!(?self.current_index, "skipped bound region");
748 r
749 }
750 _ => {
751 debug!(?self.current_index, "folding free region");
752 (self.fold_region_fn)(r, self.current_index)
753 }
754 }
755 }
756
757 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
758 if t.has_regions() { t.super_fold_with(self) } else { t }
759 }
760
761 fn fold_const(&mut self, ct: Const<I>) -> Const<I> {
762 if ct.has_regions() { ct.super_fold_with(self) } else { ct }
763 }
764
765 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
766 if p.has_regions() { p.super_fold_with(self) } else { p }
767 }
768
769 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
770 if c.has_regions() { c.super_fold_with(self) } else { c }
771 }
772}
773
774pub fn set_aliases_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
781where
782 T: TypeFoldable<I>,
783{
784 let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToNonRigid);
785 ty::Unnormalized::new(folded)
786}
787
788pub fn set_opaques_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
789where
790 T: TypeFoldable<I>,
791{
792 let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::OpaqueToNonRigid);
793 ty::Unnormalized::new(folded)
794}
795
796pub fn set_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
797where
798 T: TypeFoldable<I>,
799{
800 set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToRigid)
801}
802
803pub fn set_type_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
804where
805 T: TypeFoldable<I>,
806{
807 set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::TypeToRigid)
808}
809
810fn set_aliases_rigidness_with_mode<I: Interner, T>(cx: I, value: T, mode: RigidnessFoldMode) -> T
811where
812 T: TypeFoldable<I>,
813{
814 if !mode.needs_change(&value) {
815 return value;
816 }
817
818 let mut folder = RigidnessFolder { cx, mode };
819 value.fold_with(&mut folder)
820}
821
822enum RigidnessFoldMode {
823 AllToRigid,
824 AllToNonRigid,
825 TypeToRigid,
826 OpaqueToNonRigid,
827}
828
829impl RigidnessFoldMode {
830 fn needs_change<I: Interner, T: TypeVisitable<I>>(&self, v: &T) -> bool {
831 match self {
832 RigidnessFoldMode::AllToRigid => v.has_non_rigid_aliases(),
833 RigidnessFoldMode::AllToNonRigid => v.has_rigid_aliases(),
834 RigidnessFoldMode::TypeToRigid => {
835 v.has_non_rigid_aliases()
836 && v.has_type_flags(ty::TypeFlags::HAS_ALIAS - ty::TypeFlags::HAS_CONST_ALIAS)
837 }
838 RigidnessFoldMode::OpaqueToNonRigid => v.has_rigid_aliases() && v.has_opaque_types(),
839 }
840 }
841}
842
843struct RigidnessFolder<I: Interner> {
845 cx: I,
846 mode: RigidnessFoldMode,
847}
848
849impl<I: Interner> TypeFolder<I> for RigidnessFolder<I> {
850 #[inline]
851 fn cx(&self) -> I {
852 self.cx
853 }
854
855 fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
856 if self.mode.needs_change(&t) { t.super_fold_with(self) } else { t }
857 }
858
859 fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
860 if !self.mode.needs_change(&t) {
861 return t;
862 }
863
864 match t.kind() {
865 ty::Alias(is_rigid, alias_ty) => {
866 let alias_ty = alias_ty.fold_with(self);
867 match self.mode {
868 RigidnessFoldMode::AllToRigid | RigidnessFoldMode::TypeToRigid => {
869 I::Ty::new_alias(self.cx(), ty::IsRigid::Yes, alias_ty)
870 }
871 RigidnessFoldMode::AllToNonRigid => {
872 I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
873 }
874 RigidnessFoldMode::OpaqueToNonRigid => {
875 if let ty::AliasTyKind::Opaque { .. } = alias_ty.kind {
876 I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
877 } else {
878 I::Ty::new_alias(self.cx(), is_rigid, alias_ty)
879 }
880 }
881 }
882 }
883 _ => t.super_fold_with(self),
884 }
885 }
886
887 fn fold_const(&mut self, c: Const<I>) -> Const<I> {
888 if !self.mode.needs_change(&c) {
889 return c;
890 }
891
892 match c.kind() {
893 ty::ConstKind::Alias(is_rigid, alias_const) => {
894 let alias_const = alias_const.fold_with(self);
895 match self.mode {
896 RigidnessFoldMode::AllToRigid => {
897 Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const)
898 }
899 RigidnessFoldMode::AllToNonRigid => {
900 Const::new_alias(self.cx(), ty::IsRigid::No, alias_const)
901 }
902 RigidnessFoldMode::OpaqueToNonRigid | RigidnessFoldMode::TypeToRigid => {
903 Const::new_alias(self.cx(), is_rigid, alias_const)
904 }
905 }
906 }
907 _ => c.super_fold_with(self),
908 }
909 }
910
911 fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
912 if self.mode.needs_change(&p) { p.super_fold_with(self) } else { p }
913 }
914
915 fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
916 if self.mode.needs_change(&c) { c.super_fold_with(self) } else { c }
917 }
918}