1//! A folding traversal mechanism for complex data structures that contain type
2//! information.
3//!
4//! This is a modifying traversal. It consumes the data structure, producing a
5//! (possibly) modified version of it. Both fallible and infallible versions are
6//! available. The name is potentially confusing, because this traversal is more
7//! like `Iterator::map` than `Iterator::fold`.
8//!
9//! This traversal has limited flexibility. Only a small number of "types of
10//! interest" within the complex data structures can receive custom
11//! modification. These are the ones containing the most important type-related
12//! information, such as `Ty`, `Predicate`, `Region`, and `Const`.
13//!
14//! There are three traits involved in each traversal.
15//! - `TypeFoldable`. This is implemented once for many types, including:
16//! - Types of interest, for which the methods delegate to the folder.
17//! - All other types, including generic containers like `Vec` and `Option`.
18//! It defines a "skeleton" of how they should be folded.
19//! - `TypeSuperFoldable`. This is implemented only for recursive types of
20//! interest, and defines the folding "skeleton" for these types. (This
21//! excludes `Region` because it is non-recursive, i.e. it never contains
22//! other types of interest.)
23//! - `TypeFolder`/`FallibleTypeFolder`. One of these is implemented for each
24//! folder. This defines how types of interest are folded.
25//!
26//! This means each fold is a mixture of (a) generic folding operations, and (b)
27//! custom fold operations that are specific to the folder.
28//! - The `TypeFoldable` impls handle most of the traversal, and call into
29//! `TypeFolder`/`FallibleTypeFolder` when they encounter a type of interest.
30//! - A `TypeFolder`/`FallibleTypeFolder` may call into another `TypeFoldable`
31//! impl, because some of the types of interest are recursive and can contain
32//! other types of interest.
33//! - A `TypeFolder`/`FallibleTypeFolder` may also call into a `TypeSuperFoldable`
34//! impl, because each folder might provide custom handling only for some types
35//! of interest, or only for some variants of each type of interest, and then
36//! use default traversal for the remaining cases.
37//!
38//! For example, if you have `struct S(Ty, U)` where `S: TypeFoldable` and `U:
39//! TypeFoldable`, and an instance `s = S(ty, u)`, it would be folded like so:
40//! ```text
41//! s.fold_with(folder) calls
42//! - ty.fold_with(folder) calls
43//! - folder.fold_ty(ty) may call
44//! - ty.super_fold_with(folder)
45//! - u.fold_with(folder)
46//! ```
4748use std::convert::Infallible;
49use std::mem;
50use std::sync::Arc;
5152use rustc_index::{Idx, IndexVec};
53use thin_vec::ThinVec;
54use tracing::{debug, instrument};
5556use crate::inherent::*;
57use crate::visit::{TypeVisitable, TypeVisitableExtas _};
58use crate::{
59selfas ty, Binder, BoundVarIndexKind, ClauseKind, Flags, Interner, ProjectionClause, Region,
60TypeSuperVisitable,
61};
6263/// This trait is implemented for every type that can be folded,
64/// providing the skeleton of the traversal.
65///
66/// To implement this conveniently, use the derive macro located in
67/// `rustc_macros`.
68///
69/// This trait is a sub-trait of `TypeVisitable`. This is because many
70/// `TypeFolder` instances use the methods in `TypeVisitableExt` while folding,
71/// which means in practice almost every foldable type needs to also be
72/// visitable. (However, there are some types that are visitable without being
73/// foldable.)
74pub trait TypeFoldable<I: Interner>: TypeVisitable<I> + Clone {
75/// The entry point for folding. To fold a value `t` with a folder `f`
76 /// call: `t.try_fold_with(f)`.
77 ///
78 /// For most types, this just traverses the value, calling `try_fold_with`
79 /// on each field/element.
80 ///
81 /// For types of interest (such as `Ty`), the implementation of this method
82 /// calls a folder method specifically for that type (such as
83 /// `F::try_fold_ty`). This is where control transfers from [`TypeFoldable`]
84 /// to [`FallibleTypeFolder`].
85fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error>;
8687/// The entry point for folding. To fold a value `t` with a folder `f`
88 /// call: `t.fold_with(f)`.
89 ///
90 /// For most types, this just traverses the value, calling `fold_with`
91 /// on each field/element.
92 ///
93 /// For types of interest (such as `Ty`), the implementation of this method
94 /// calls a folder method specifically for that type (such as
95 /// `F::fold_ty`). This is where control transfers from `TypeFoldable`
96 /// to `TypeFolder`.
97 ///
98 /// Same as [`TypeFoldable::try_fold_with`], but not fallible. Make sure to keep
99 /// the behavior in sync across functions.
100fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
101}
102103// This trait is implemented for types of interest.
104pub trait TypeSuperFoldable<I: Interner>: TypeFoldable<I> {
105/// Provides a default fold for a recursive type of interest. This should
106 /// only be called within `TypeFolder` methods, when a non-custom traversal
107 /// is desired for the value of the type of interest passed to that method.
108 /// For example, in `MyFolder::try_fold_ty(ty)`, it is valid to call
109 /// `ty.try_super_fold_with(self)`, but any other folding should be done
110 /// with `xyz.try_fold_with(self)`.
111fn try_super_fold_with<F: FallibleTypeFolder<I>>(
112self,
113 folder: &mut F,
114 ) -> Result<Self, F::Error>;
115116/// A convenient alternative to `try_super_fold_with` for use with
117 /// infallible folders. Do not override this method, to ensure coherence
118 /// with `try_super_fold_with`.
119fn super_fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self;
120}
121122/// This trait is implemented for every infallible folding traversal. There is
123/// a fold method defined for every type of interest. Each such method has a
124/// default that does an "identity" fold. Implementations of these methods
125/// often fall back to a `super_fold_with` method if the primary argument
126/// doesn't satisfy a particular condition.
127pub trait TypeFolder<I: Interner>: Sized {
128fn cx(&self) -> I;
129130fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
131where
132T: TypeFoldable<I>,
133 {
134t.super_fold_with(self)
135 }
136137fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
138t.super_fold_with(self)
139 }
140141// The default region folder is a no-op because `Region` is non-recursive
142 // and has no `super_fold_with` method to call.
143fn fold_region(&mut self, r: Region<I>) -> Region<I> {
144r145 }
146147fn fold_const(&mut self, c: I::Const) -> I::Const {
148c.super_fold_with(self)
149 }
150151fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
152p.super_fold_with(self)
153 }
154155fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
156c.super_fold_with(self)
157 }
158}
159160/// [Fold predicate](TypeFolder::fold_predicate) deliberately doesn't get access
161/// to an actual predicate. This way, we can compress lists of predicates, and hide
162/// this detail to folders. Instead, some type implementing this trait, [`PredicateProxy`]
163/// is passed, with its limited API.
164///
165/// Most [`TypeFolder`]s only use `fold_predicate` to inspect type flags.
166pub trait PredicateProxy<I: Interner>:
167TypeSuperFoldable<I> + TypeSuperVisitable<I> + Flags + Copy168{
169fn allow_normalization(&self) -> bool;
170171/// Gets the underlying clause kind (if this predicate is a clause, otherwise `None`).
172 /// The fact that it's `unchecked`, is because no attempt is made to hide implementation
173 /// details. For example, in the future we may compress clauses together. Code calling
174 /// `clause_kind_unchecked` will have to correctly deal with these implementation details,
175 /// and have code handling any edgecase arising as a result.
176fn clause_kind_unchecked(&self) -> Option<Binder<I, ClauseKind<I>>>;
177178/// If self is a projection clause, call `f` with it. The result will be rebound and returned as `Some`.
179 /// Otherwise, when self is not a projection clause, `None` is returned.
180fn map_projection(
181self,
182 cx: I,
183 f: impl FnOnce(Binder<I, ProjectionClause<I>>) -> Binder<I, ProjectionClause<I>>,
184 ) -> Option<Self>;
185}
186187/// This trait is implemented for every folding traversal. There is a fold
188/// method defined for every type of interest. Each such method has a default
189/// that does an "identity" fold.
190///
191/// A blanket implementation of this trait (that defers to the relevant
192/// method of [`TypeFolder`]) is provided for all infallible folders in
193/// order to ensure the two APIs are coherent.
194pub trait FallibleTypeFolder<I: Interner>: Sized {
195type Error;
196197fn cx(&self) -> I;
198199fn try_fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> Result<ty::Binder<I, T>, Self::Error>
200where
201T: TypeFoldable<I>,
202 {
203t.try_super_fold_with(self)
204 }
205206fn try_fold_ty(&mut self, t: I::Ty) -> Result<I::Ty, Self::Error> {
207t.try_super_fold_with(self)
208 }
209210// The default region folder is a no-op because `Region` is non-recursive
211 // and has no `super_fold_with` method to call.
212fn try_fold_region(&mut self, r: Region<I>) -> Result<Region<I>, Self::Error> {
213Ok(r)
214 }
215216fn try_fold_const(&mut self, c: I::Const) -> Result<I::Const, Self::Error> {
217c.try_super_fold_with(self)
218 }
219220fn try_fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> Result<P, Self::Error> {
221p.try_super_fold_with(self)
222 }
223224fn try_fold_clauses(&mut self, c: I::Clauses) -> Result<I::Clauses, Self::Error> {
225c.try_super_fold_with(self)
226 }
227}
228229///////////////////////////////////////////////////////////////////////////
230// Traversal implementations.
231232impl<I: Interner, T: TypeFoldable<I>, U: TypeFoldable<I>> TypeFoldable<I> for (T, U) {
233fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<(T, U), F::Error> {
234Ok((self.0.try_fold_with(folder)?, self.1.try_fold_with(folder)?))
235 }
236237fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
238 (self.0.fold_with(folder), self.1.fold_with(folder))
239 }
240}
241242impl<I: Interner, A: TypeFoldable<I>, B: TypeFoldable<I>, C: TypeFoldable<I>> TypeFoldable<I>
243for (A, B, C)
244{
245fn try_fold_with<F: FallibleTypeFolder<I>>(
246self,
247 folder: &mut F,
248 ) -> Result<(A, B, C), F::Error> {
249Ok((
250self.0.try_fold_with(folder)?,
251self.1.try_fold_with(folder)?,
252self.2.try_fold_with(folder)?,
253 ))
254 }
255256fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
257 (self.0.fold_with(folder), self.1.fold_with(folder), self.2.fold_with(folder))
258 }
259}
260261impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Option<T> {
262fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
263Ok(match self {
264Some(v) => Some(v.try_fold_with(folder)?),
265None => None,
266 })
267 }
268269fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
270Some(self?.fold_with(folder))
271 }
272}
273274impl<I: Interner, T: TypeFoldable<I>, E: TypeFoldable<I>> TypeFoldable<I> for Result<T, E> {
275fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
276Ok(match self {
277Ok(v) => Ok(v.try_fold_with(folder)?),
278Err(e) => Err(e.try_fold_with(folder)?),
279 })
280 }
281282fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
283match self {
284Ok(v) => Ok(v.fold_with(folder)),
285Err(e) => Err(e.fold_with(folder)),
286 }
287 }
288}
289290fn fold_arc<T: Clone, E>(
291mut arc: Arc<T>,
292 fold: impl FnOnce(T) -> Result<T, E>,
293) -> Result<Arc<T>, E> {
294// We merely want to replace the contained `T`, if at all possible,
295 // so that we don't needlessly allocate a new `Arc` or indeed clone
296 // the contained type.
297unsafe {
298// First step is to ensure that we have a unique reference to
299 // the contained type, which `Arc::make_mut` will accomplish (by
300 // allocating a new `Arc` and cloning the `T` only if required).
301 // This is done *before* casting to `Arc<ManuallyDrop<T>>` so that
302 // panicking during `make_mut` does not leak the `T`.
303Arc::make_mut(&mut arc);
304305// Casting to `Arc<ManuallyDrop<T>>` is safe because `ManuallyDrop`
306 // is `repr(transparent)`.
307let ptr = Arc::into_raw(arc).cast::<mem::ManuallyDrop<T>>();
308let mut unique = Arc::from_raw(ptr);
309310// Call to `Arc::make_mut` above guarantees that `unique` is the
311 // sole reference to the contained value, so we can avoid doing
312 // a checked `get_mut` here.
313let slot = Arc::get_mut(&mut unique).unwrap_unchecked();
314315// Semantically move the contained type out from `unique`, fold
316 // it, then move the folded value back into `unique`. Should
317 // folding fail, `ManuallyDrop` ensures that the "moved-out"
318 // value is not re-dropped.
319let owned = mem::ManuallyDrop::take(slot);
320let folded = fold(owned)?;
321*slot = mem::ManuallyDrop::new(folded);
322323// Cast back to `Arc<T>`.
324Ok(Arc::from_raw(Arc::into_raw(unique).cast()))
325 }
326}
327328impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Arc<T> {
329fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
330fold_arc(self, |t| t.try_fold_with(folder))
331 }
332333fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
334match fold_arc::<T, Infallible>(self, |t| Ok(t.fold_with(folder))) {
335Ok(t) => t,
336 }
337 }
338}
339340impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<T> {
341fn try_fold_with<F: FallibleTypeFolder<I>>(mut self, folder: &mut F) -> Result<Self, F::Error> {
342*self = (*self).try_fold_with(folder)?;
343Ok(self)
344 }
345346fn fold_with<F: TypeFolder<I>>(mut self, folder: &mut F) -> Self {
347*self = (*self).fold_with(folder);
348self349 }
350}
351352impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Vec<T> {
353fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
354self.into_iter().map(|t| t.try_fold_with(folder)).collect()
355 }
356357fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
358self.into_iter().map(|t| t.fold_with(folder)).collect()
359 }
360}
361362impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for ThinVec<T> {
363fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
364self.into_iter().map(|t| t.try_fold_with(folder)).collect()
365 }
366367fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
368self.into_iter().map(|t| t.fold_with(folder)).collect()
369 }
370}
371372impl<I: Interner, T: TypeFoldable<I>> TypeFoldable<I> for Box<[T]> {
373fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
374Vec::from(self).try_fold_with(folder).map(Vec::into_boxed_slice)
375 }
376377fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
378Vec::into_boxed_slice(Vec::from(self).fold_with(folder))
379 }
380}
381382impl<I: Interner, T: TypeFoldable<I>, Ix: Idx> TypeFoldable<I> for IndexVec<Ix, T> {
383fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
384self.raw.try_fold_with(folder).map(IndexVec::from_raw)
385 }
386387fn fold_with<F: TypeFolder<I>>(self, folder: &mut F) -> Self {
388IndexVec::from_raw(self.raw.fold_with(folder))
389 }
390}
391392///////////////////////////////////////////////////////////////////////////
393// Shifter
394//
395// Shifts the De Bruijn indices on all escaping bound vars by a
396// fixed amount. Useful in instantiation or when otherwise introducing
397// a binding level that is not intended to capture the existing bound
398// vars. See comment on `shift_vars_through_binders` method in
399// `rustc_middle/src/ty/generic_args.rs` for more details.
400401struct Shifter<I: Interner> {
402 cx: I,
403 current_index: ty::DebruijnIndex,
404 amount: u32,
405}
406407impl<I: Interner> Shifter<I> {
408fn new(cx: I, amount: u32) -> Self {
409Shifter { cx, current_index: ty::INNERMOST, amount }
410 }
411}
412413impl<I: Interner> TypeFolder<I> for Shifter<I> {
414fn cx(&self) -> I {
415self.cx
416 }
417418fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
419self.current_index.shift_in(1);
420let t = t.super_fold_with(self);
421self.current_index.shift_out(1);
422t423 }
424425fn fold_region(&mut self, r: Region<I>) -> Region<I> {
426match r.kind() {
427 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br)
428if debruijn >= self.current_index =>
429 {
430let debruijn = debruijn.shifted_in(self.amount);
431Region::new_bound(self.cx, debruijn, br)
432 }
433_ => r,
434 }
435 }
436437fn fold_ty(&mut self, ty: I::Ty) -> I::Ty {
438match ty.kind() {
439 ty::Bound(BoundVarIndexKind::Bound(debruijn), bound_ty)
440if debruijn >= self.current_index =>
441 {
442let debruijn = debruijn.shifted_in(self.amount);
443 Ty::new_bound(self.cx, debruijn, bound_ty)
444 }
445446_ if ty.has_vars_bound_at_or_above(self.current_index) => ty.super_fold_with(self),
447_ => ty,
448 }
449 }
450451fn fold_const(&mut self, ct: I::Const) -> I::Const {
452match ct.kind() {
453 ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ct)
454if debruijn >= self.current_index =>
455 {
456let debruijn = debruijn.shifted_in(self.amount);
457 Const::new_bound(self.cx, debruijn, bound_ct)
458 }
459_ => ct.super_fold_with(self),
460 }
461 }
462463fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
464if p.has_vars_bound_at_or_above(self.current_index) { p.super_fold_with(self) } else { p }
465 }
466467fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
468if c.has_vars_bound_at_or_above(self.current_index) { c.super_fold_with(self) } else { c }
469 }
470}
471472pub fn shift_region<I: Interner>(cx: I, region: Region<I>, amount: u32) -> Region<I> {
473match region.kind() {
474 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), br) if amount > 0 => {
475Region::new_bound(cx, debruijn.shifted_in(amount), br)
476 }
477_ => region,
478 }
479}
480481{}
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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(481u32),
::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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:481",
"rustc_type_ir::fold", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(481u32),
::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)]482pub fn shift_vars<I: Interner, T>(cx: I, value: T, amount: u32) -> T
483where
484T: TypeFoldable<I>,
485{
486if amount == 0 || !value.has_escaping_bound_vars() {
487 value
488 } else {
489 value.fold_with(&mut Shifter::new(cx, amount))
490 }
491}
492493///////////////////////////////////////////////////////////////////////////
494// Region folder
495496pub fn fold_regions<I: Interner, T>(
497 cx: I,
498 value: T,
499 f: impl FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
500) -> T
501where
502T: TypeFoldable<I>,
503{
504value.fold_with(&mut RegionFolder::new(cx, f))
505}
506507/// Folds over the substructure of a type, visiting its component
508/// types and all regions that occur *free* within it.
509///
510/// That is, function pointer types and trait objects can introduce
511/// new bound regions which are not visited by this visitor as
512/// they are not free; only regions that occur free will be
513/// visited by `fold_region_fn`.
514pub struct RegionFolder<I, F> {
515 cx: I,
516517/// Stores the index of a binder *just outside* the stuff we have
518 /// visited. So this begins as INNERMOST; when we pass through a
519 /// binder, it is incremented (via `shift_in`).
520current_index: ty::DebruijnIndex,
521522/// Callback invoked for each free region. The `DebruijnIndex`
523 /// points to the binder *just outside* the ones we have passed
524 /// through.
525fold_region_fn: F,
526}
527528impl<I, F> RegionFolder<I, F> {
529#[inline]
530pub fn new(cx: I, fold_region_fn: F) -> RegionFolder<I, F> {
531RegionFolder { cx, current_index: ty::INNERMOST, fold_region_fn }
532 }
533}
534535impl<I, F> TypeFolder<I> for RegionFolder<I, F>
536where
537I: Interner,
538 F: FnMut(Region<I>, ty::DebruijnIndex) -> Region<I>,
539{
540fn cx(&self) -> I {
541self.cx
542 }
543544fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
545self.current_index.shift_in(1);
546let t = t.super_fold_with(self);
547self.current_index.shift_out(1);
548t549 }
550551{}
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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(551u32),
::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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:557",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(557u32),
::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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:561",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(561u32),
::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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:565",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(565u32),
::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/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs:551",
"rustc_type_ir::fold", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/0fc141305da7a8a222f65aef1f1acc739c46282b/compiler/rustc_type_ir/src/fold.rs"),
::tracing_core::__macro_support::Option::Some(551u32),
::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)]552fn fold_region(&mut self, r: Region<I>) -> Region<I> {
553match r.kind() {
554 ty::ReBound(ty::BoundVarIndexKind::Bound(debruijn), _)
555if debruijn < self.current_index =>
556 {
557debug!(?self.current_index, "skipped bound region");
558 r
559 }
560 ty::ReBound(ty::BoundVarIndexKind::Canonical, _) => {
561debug!(?self.current_index, "skipped bound region");
562 r
563 }
564_ => {
565debug!(?self.current_index, "folding free region");
566 (self.fold_region_fn)(r, self.current_index)
567 }
568 }
569 }
570571fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
572if t.has_regions() { t.super_fold_with(self) } else { t }
573 }
574575fn fold_const(&mut self, ct: I::Const) -> I::Const {
576if ct.has_regions() { ct.super_fold_with(self) } else { ct }
577 }
578579fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
580if p.has_regions() { p.super_fold_with(self) } else { p }
581 }
582583fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
584if c.has_regions() { c.super_fold_with(self) } else { c }
585 }
586}
587588/// This function should ideally only be used if either the `TypingMode`
589/// or the `ParamEnv` differs from the environment the aliases were normalized
590/// in.
591///
592/// Cases outside these two should consider whether the problem can be
593/// fixed at the root instead.
594pub fn set_aliases_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
595where
596T: TypeFoldable<I>,
597{
598let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToNonRigid);
599 ty::Unnormalized::new(folded)
600}
601602pub fn set_opaques_to_non_rigid<I: Interner, T>(cx: I, value: T) -> ty::Unnormalized<I, T>
603where
604T: TypeFoldable<I>,
605{
606let folded = set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::OpaqueToNonRigid);
607 ty::Unnormalized::new(folded)
608}
609610pub fn set_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
611where
612T: TypeFoldable<I>,
613{
614set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::AllToRigid)
615}
616617pub fn set_type_aliases_to_rigid<I: Interner, T>(cx: I, value: T) -> T
618where
619T: TypeFoldable<I>,
620{
621set_aliases_rigidness_with_mode(cx, value, RigidnessFoldMode::TypeToRigid)
622}
623624fn set_aliases_rigidness_with_mode<I: Interner, T>(cx: I, value: T, mode: RigidnessFoldMode) -> T
625where
626T: TypeFoldable<I>,
627{
628if !mode.needs_change(&value) {
629return value;
630 }
631632let mut folder = RigidnessFolder { cx, mode };
633value.fold_with(&mut folder)
634}
635636enum RigidnessFoldMode {
637 AllToRigid,
638 AllToNonRigid,
639 TypeToRigid,
640 OpaqueToNonRigid,
641}
642643impl RigidnessFoldMode {
644fn needs_change<I: Interner, T: TypeVisitable<I>>(&self, v: &T) -> bool {
645match self {
646 RigidnessFoldMode::AllToRigid => v.has_non_rigid_aliases(),
647 RigidnessFoldMode::AllToNonRigid => v.has_rigid_aliases(),
648 RigidnessFoldMode::TypeToRigid => {
649v.has_non_rigid_aliases()
650 && v.has_type_flags(ty::TypeFlags::HAS_ALIAS - ty::TypeFlags::HAS_CONST_ALIAS)
651 }
652 RigidnessFoldMode::OpaqueToNonRigid => v.has_rigid_aliases() && v.has_opaque_types(),
653 }
654 }
655}
656657// Set aliases to be rigid or non-rigid according to the mode.
658struct RigidnessFolder<I: Interner> {
659 cx: I,
660 mode: RigidnessFoldMode,
661}
662663impl<I: Interner> TypeFolder<I> for RigidnessFolder<I> {
664#[inline]
665fn cx(&self) -> I {
666self.cx
667 }
668669fn fold_binder<T: TypeFoldable<I>>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T> {
670if self.mode.needs_change(&t) { t.super_fold_with(self) } else { t }
671 }
672673fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
674if !self.mode.needs_change(&t) {
675return t;
676 }
677678match t.kind() {
679 ty::Alias(is_rigid, alias_ty) => {
680let alias_ty = alias_ty.fold_with(self);
681match self.mode {
682 RigidnessFoldMode::AllToRigid | RigidnessFoldMode::TypeToRigid => {
683 I::Ty::new_alias(self.cx(), ty::IsRigid::Yes, alias_ty)
684 }
685 RigidnessFoldMode::AllToNonRigid => {
686 I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
687 }
688 RigidnessFoldMode::OpaqueToNonRigid => {
689if let ty::AliasTyKind::Opaque { .. } = alias_ty.kind {
690 I::Ty::new_alias(self.cx(), ty::IsRigid::No, alias_ty)
691 } else {
692 I::Ty::new_alias(self.cx(), is_rigid, alias_ty)
693 }
694 }
695 }
696 }
697_ => t.super_fold_with(self),
698 }
699 }
700701fn fold_const(&mut self, c: I::Const) -> I::Const {
702if !self.mode.needs_change(&c) {
703return c;
704 }
705706match c.kind() {
707 ty::ConstKind::Alias(is_rigid, alias_const) => {
708let alias_const = alias_const.fold_with(self);
709match self.mode {
710 RigidnessFoldMode::AllToRigid => {
711 I::Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const)
712 }
713 RigidnessFoldMode::AllToNonRigid => {
714 I::Const::new_alias(self.cx(), ty::IsRigid::No, alias_const)
715 }
716 RigidnessFoldMode::OpaqueToNonRigid | RigidnessFoldMode::TypeToRigid => {
717 I::Const::new_alias(self.cx(), is_rigid, alias_const)
718 }
719 }
720 }
721_ => c.super_fold_with(self),
722 }
723 }
724725fn fold_predicate<P: PredicateProxy<I>>(&mut self, p: P) -> P {
726if self.mode.needs_change(&p) { p.super_fold_with(self) } else { p }
727 }
728729fn fold_clauses(&mut self, c: I::Clauses) -> I::Clauses {
730if self.mode.needs_change(&c) { c.super_fold_with(self) } else { c }
731 }
732}