rustc_middle/ty/
structural_impls.rs

1//! This module contains implementations of the `Lift`, `TypeFoldable` and
2//! `TypeVisitable` traits for various types in the Rust compiler. Most are
3//! written by hand, though we've recently added some macros and proc-macros
4//! to help with the tedium.
5
6use std::fmt::{self, Debug};
7use std::marker::PhantomData;
8
9use rustc_abi::TyAndLayout;
10use rustc_hir::def::Namespace;
11use rustc_hir::def_id::LocalDefId;
12use rustc_span::source_map::Spanned;
13use rustc_type_ir::{ConstKind, TypeFolder, VisitorResult, try_visit};
14
15use super::{GenericArg, GenericArgKind, Pattern, Region};
16use crate::mir::PlaceElem;
17use crate::ty::print::{FmtPrinter, Printer, with_no_trimmed_paths};
18use crate::ty::{
19    self, FallibleTypeFolder, Lift, Term, TermKind, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable,
20    TypeSuperVisitable, TypeVisitable, TypeVisitor,
21};
22
23impl fmt::Debug for ty::TraitDef {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        ty::tls::with(|tcx| {
26            with_no_trimmed_paths!({
27                let s = FmtPrinter::print_string(tcx, Namespace::TypeNS, |p| {
28                    p.print_def_path(self.def_id, &[])
29                })?;
30                f.write_str(&s)
31            })
32        })
33    }
34}
35
36impl<'tcx> fmt::Debug for ty::AdtDef<'tcx> {
37    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
38        ty::tls::with(|tcx| {
39            with_no_trimmed_paths!({
40                let s = FmtPrinter::print_string(tcx, Namespace::TypeNS, |p| {
41                    p.print_def_path(self.did(), &[])
42                })?;
43                f.write_str(&s)
44            })
45        })
46    }
47}
48
49impl fmt::Debug for ty::UpvarId {
50    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
51        let name = ty::tls::with(|tcx| tcx.hir_name(self.var_path.hir_id));
52        write!(f, "UpvarId({:?};`{}`;{:?})", self.var_path.hir_id, name, self.closure_expr_id)
53    }
54}
55
56impl<'tcx> fmt::Debug for ty::adjustment::Adjustment<'tcx> {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        write!(f, "{:?} -> {}", self.kind, self.target)
59    }
60}
61
62impl<'tcx> fmt::Debug for ty::adjustment::PatAdjustment<'tcx> {
63    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
64        write!(f, "{} -> {:?}", self.source, self.kind)
65    }
66}
67
68impl fmt::Debug for ty::BoundRegionKind {
69    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70        match *self {
71            ty::BoundRegionKind::Anon => write!(f, "BrAnon"),
72            ty::BoundRegionKind::NamedAnon(name) => {
73                write!(f, "BrNamedAnon({name})")
74            }
75            ty::BoundRegionKind::Named(did) => {
76                write!(f, "BrNamed({did:?})")
77            }
78            ty::BoundRegionKind::ClosureEnv => write!(f, "BrEnv"),
79        }
80    }
81}
82
83impl fmt::Debug for ty::LateParamRegion {
84    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85        write!(f, "ReLateParam({:?}, {:?})", self.scope, self.kind)
86    }
87}
88
89impl fmt::Debug for ty::LateParamRegionKind {
90    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91        match *self {
92            ty::LateParamRegionKind::Anon(idx) => write!(f, "LateAnon({idx})"),
93            ty::LateParamRegionKind::NamedAnon(idx, name) => {
94                write!(f, "LateNamedAnon({idx:?}, {name})")
95            }
96            ty::LateParamRegionKind::Named(did) => {
97                write!(f, "LateNamed({did:?})")
98            }
99            ty::LateParamRegionKind::ClosureEnv => write!(f, "LateEnv"),
100        }
101    }
102}
103
104impl<'tcx> fmt::Debug for Ty<'tcx> {
105    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
106        with_no_trimmed_paths!(fmt::Debug::fmt(self.kind(), f))
107    }
108}
109
110impl fmt::Debug for ty::ParamTy {
111    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112        write!(f, "{}/#{}", self.name, self.index)
113    }
114}
115
116impl fmt::Debug for ty::ParamConst {
117    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
118        write!(f, "{}/#{}", self.name, self.index)
119    }
120}
121
122impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
123    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
124        write!(f, "{:?}", self.kind())
125    }
126}
127
128impl<'tcx> fmt::Debug for ty::Clause<'tcx> {
129    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
130        write!(f, "{:?}", self.kind())
131    }
132}
133
134impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
135    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
136        match self.kind {
137            ty::ExprKind::Binop(op) => {
138                let (lhs_ty, rhs_ty, lhs, rhs) = self.binop_args();
139                write!(f, "({op:?}: ({:?}: {:?}), ({:?}: {:?}))", lhs, lhs_ty, rhs, rhs_ty,)
140            }
141            ty::ExprKind::UnOp(op) => {
142                let (rhs_ty, rhs) = self.unop_args();
143                write!(f, "({op:?}: ({:?}: {:?}))", rhs, rhs_ty)
144            }
145            ty::ExprKind::FunctionCall => {
146                let (func_ty, func, args) = self.call_args();
147                let args = args.collect::<Vec<_>>();
148                write!(f, "({:?}: {:?})(", func, func_ty)?;
149                for arg in args.iter().rev().skip(1).rev() {
150                    write!(f, "{:?}, ", arg)?;
151                }
152                if let Some(arg) = args.last() {
153                    write!(f, "{:?}", arg)?;
154                }
155
156                write!(f, ")")
157            }
158            ty::ExprKind::Cast(kind) => {
159                let (value_ty, value, to_ty) = self.cast_args();
160                write!(f, "({kind:?}: ({:?}: {:?}), {:?})", value, value_ty, to_ty)
161            }
162        }
163    }
164}
165
166impl<'tcx> fmt::Debug for ty::Const<'tcx> {
167    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
168        // If this is a value, we spend some effort to make it look nice.
169        if let ConstKind::Value(cv) = self.kind() {
170            write!(f, "{}", cv)
171        } else {
172            // Fall back to something verbose.
173            write!(f, "{:?}", self.kind())
174        }
175    }
176}
177
178impl fmt::Debug for ty::BoundTy {
179    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180        match self.kind {
181            ty::BoundTyKind::Anon => write!(f, "{:?}", self.var),
182            ty::BoundTyKind::Param(def_id) => write!(f, "{def_id:?}"),
183        }
184    }
185}
186
187impl<'tcx> fmt::Debug for GenericArg<'tcx> {
188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189        match self.kind() {
190            GenericArgKind::Lifetime(lt) => lt.fmt(f),
191            GenericArgKind::Type(ty) => ty.fmt(f),
192            GenericArgKind::Const(ct) => ct.fmt(f),
193        }
194    }
195}
196
197impl<'tcx> fmt::Debug for Region<'tcx> {
198    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
199        write!(f, "{:?}", self.kind())
200    }
201}
202
203///////////////////////////////////////////////////////////////////////////
204// Atomic structs
205//
206// For things that don't carry any arena-allocated data (and are
207// copy...), just add them to one of these lists as appropriate.
208
209// For things for which the type library provides traversal implementations
210// for all Interners, we only need to provide a Lift implementation.
211TrivialLiftImpls! {
212    (),
213    bool,
214    usize,
215    u64,
216    // tidy-alphabetical-start
217    crate::mir::Promoted,
218    crate::mir::interpret::AllocId,
219    crate::mir::interpret::Scalar,
220    crate::ty::ParamConst,
221    rustc_abi::ExternAbi,
222    rustc_abi::Size,
223    rustc_hir::Safety,
224    rustc_middle::mir::ConstValue,
225    rustc_type_ir::BoundConstness,
226    rustc_type_ir::PredicatePolarity,
227    // tidy-alphabetical-end
228}
229
230// For some things about which the type library does not know, or does not
231// provide any traversal implementations, we need to provide a traversal
232// implementation (only for TyCtxt<'_> interners).
233TrivialTypeTraversalImpls! {
234    // tidy-alphabetical-start
235    crate::infer::canonical::Certainty,
236    crate::mir::BasicBlock,
237    crate::mir::BindingForm<'tcx>,
238    crate::mir::BlockTailInfo,
239    crate::mir::BorrowKind,
240    crate::mir::CastKind,
241    crate::mir::ConstValue,
242    crate::mir::CoroutineSavedLocal,
243    crate::mir::FakeReadCause,
244    crate::mir::Local,
245    crate::mir::MirPhase,
246    crate::mir::NullOp,
247    crate::mir::Promoted,
248    crate::mir::RawPtrKind,
249    crate::mir::RetagKind,
250    crate::mir::SourceInfo,
251    crate::mir::SourceScope,
252    crate::mir::SourceScopeLocalData,
253    crate::mir::SwitchTargets,
254    crate::traits::IsConstable,
255    crate::traits::OverflowError,
256    crate::ty::AdtKind,
257    crate::ty::AssocItem,
258    crate::ty::AssocKind,
259    crate::ty::BoundRegion,
260    crate::ty::UserTypeAnnotationIndex,
261    crate::ty::ValTree<'tcx>,
262    crate::ty::abstract_const::NotConstEvaluatable,
263    crate::ty::adjustment::AutoBorrowMutability,
264    crate::ty::adjustment::PointerCoercion,
265    rustc_abi::FieldIdx,
266    rustc_abi::VariantIdx,
267    rustc_ast::InlineAsmOptions,
268    rustc_ast::InlineAsmTemplatePiece,
269    rustc_hir::CoroutineKind,
270    rustc_hir::HirId,
271    rustc_hir::MatchSource,
272    rustc_hir::RangeEnd,
273    rustc_hir::def_id::LocalDefId,
274    rustc_span::Ident,
275    rustc_span::Span,
276    rustc_span::Symbol,
277    rustc_target::asm::InlineAsmRegOrRegClass,
278    // tidy-alphabetical-end
279}
280
281// For some things about which the type library does not know, or does not
282// provide any traversal implementations, we need to provide a traversal
283// implementation and a lift implementation (the former only for TyCtxt<'_>
284// interners).
285TrivialTypeTraversalAndLiftImpls! {
286    // tidy-alphabetical-start
287    crate::ty::BoundTy,
288    crate::ty::ParamTy,
289    crate::ty::instance::ReifyReason,
290    rustc_hir::def_id::DefId,
291    // tidy-alphabetical-end
292}
293
294///////////////////////////////////////////////////////////////////////////
295// Lift implementations
296
297impl<'tcx> Lift<TyCtxt<'tcx>> for PhantomData<&()> {
298    type Lifted = PhantomData<&'tcx ()>;
299    fn lift_to_interner(self, _: TyCtxt<'tcx>) -> Option<Self::Lifted> {
300        Some(PhantomData)
301    }
302}
303
304impl<'tcx, T: Lift<TyCtxt<'tcx>>> Lift<TyCtxt<'tcx>> for Option<T> {
305    type Lifted = Option<T::Lifted>;
306    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
307        Some(match self {
308            Some(x) => Some(tcx.lift(x)?),
309            None => None,
310        })
311    }
312}
313
314impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for Term<'a> {
315    type Lifted = ty::Term<'tcx>;
316    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
317        match self.kind() {
318            TermKind::Ty(ty) => tcx.lift(ty).map(Into::into),
319            TermKind::Const(c) => tcx.lift(c).map(Into::into),
320        }
321    }
322}
323
324///////////////////////////////////////////////////////////////////////////
325// Traversal implementations.
326
327impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::AdtDef<'tcx> {
328    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, _visitor: &mut V) -> V::Result {
329        V::Result::output()
330    }
331}
332
333impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Pattern<'tcx> {
334    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
335        self,
336        folder: &mut F,
337    ) -> Result<Self, F::Error> {
338        let pat = (*self).clone().try_fold_with(folder)?;
339        Ok(if pat == *self { self } else { folder.cx().mk_pat(pat) })
340    }
341
342    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
343        let pat = (*self).clone().fold_with(folder);
344        if pat == *self { self } else { folder.cx().mk_pat(pat) }
345    }
346}
347
348impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Pattern<'tcx> {
349    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
350        (**self).visit_with(visitor)
351    }
352}
353
354impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
355    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
356        self,
357        folder: &mut F,
358    ) -> Result<Self, F::Error> {
359        folder.try_fold_ty(self)
360    }
361
362    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
363        folder.fold_ty(self)
364    }
365}
366
367impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
368    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
369        visitor.visit_ty(*self)
370    }
371}
372
373impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for Ty<'tcx> {
374    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
375        self,
376        folder: &mut F,
377    ) -> Result<Self, F::Error> {
378        let kind = match *self.kind() {
379            ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.try_fold_with(folder)?, mutbl),
380            ty::Array(typ, sz) => ty::Array(typ.try_fold_with(folder)?, sz.try_fold_with(folder)?),
381            ty::Slice(typ) => ty::Slice(typ.try_fold_with(folder)?),
382            ty::Adt(tid, args) => ty::Adt(tid, args.try_fold_with(folder)?),
383            ty::Dynamic(trait_ty, region) => {
384                ty::Dynamic(trait_ty.try_fold_with(folder)?, region.try_fold_with(folder)?)
385            }
386            ty::Tuple(ts) => ty::Tuple(ts.try_fold_with(folder)?),
387            ty::FnDef(def_id, args) => ty::FnDef(def_id, args.try_fold_with(folder)?),
388            ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.try_fold_with(folder)?, hdr),
389            ty::UnsafeBinder(f) => ty::UnsafeBinder(f.try_fold_with(folder)?),
390            ty::Ref(r, ty, mutbl) => {
391                ty::Ref(r.try_fold_with(folder)?, ty.try_fold_with(folder)?, mutbl)
392            }
393            ty::Coroutine(did, args) => ty::Coroutine(did, args.try_fold_with(folder)?),
394            ty::CoroutineWitness(did, args) => {
395                ty::CoroutineWitness(did, args.try_fold_with(folder)?)
396            }
397            ty::Closure(did, args) => ty::Closure(did, args.try_fold_with(folder)?),
398            ty::CoroutineClosure(did, args) => {
399                ty::CoroutineClosure(did, args.try_fold_with(folder)?)
400            }
401            ty::Alias(kind, data) => ty::Alias(kind, data.try_fold_with(folder)?),
402            ty::Pat(ty, pat) => ty::Pat(ty.try_fold_with(folder)?, pat.try_fold_with(folder)?),
403
404            ty::Bool
405            | ty::Char
406            | ty::Str
407            | ty::Int(_)
408            | ty::Uint(_)
409            | ty::Float(_)
410            | ty::Error(_)
411            | ty::Infer(_)
412            | ty::Param(..)
413            | ty::Bound(..)
414            | ty::Placeholder(..)
415            | ty::Never
416            | ty::Foreign(..) => return Ok(self),
417        };
418
419        Ok(if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) })
420    }
421
422    fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
423        let kind = match *self.kind() {
424            ty::RawPtr(ty, mutbl) => ty::RawPtr(ty.fold_with(folder), mutbl),
425            ty::Array(typ, sz) => ty::Array(typ.fold_with(folder), sz.fold_with(folder)),
426            ty::Slice(typ) => ty::Slice(typ.fold_with(folder)),
427            ty::Adt(tid, args) => ty::Adt(tid, args.fold_with(folder)),
428            ty::Dynamic(trait_ty, region) => {
429                ty::Dynamic(trait_ty.fold_with(folder), region.fold_with(folder))
430            }
431            ty::Tuple(ts) => ty::Tuple(ts.fold_with(folder)),
432            ty::FnDef(def_id, args) => ty::FnDef(def_id, args.fold_with(folder)),
433            ty::FnPtr(sig_tys, hdr) => ty::FnPtr(sig_tys.fold_with(folder), hdr),
434            ty::UnsafeBinder(f) => ty::UnsafeBinder(f.fold_with(folder)),
435            ty::Ref(r, ty, mutbl) => ty::Ref(r.fold_with(folder), ty.fold_with(folder), mutbl),
436            ty::Coroutine(did, args) => ty::Coroutine(did, args.fold_with(folder)),
437            ty::CoroutineWitness(did, args) => ty::CoroutineWitness(did, args.fold_with(folder)),
438            ty::Closure(did, args) => ty::Closure(did, args.fold_with(folder)),
439            ty::CoroutineClosure(did, args) => ty::CoroutineClosure(did, args.fold_with(folder)),
440            ty::Alias(kind, data) => ty::Alias(kind, data.fold_with(folder)),
441            ty::Pat(ty, pat) => ty::Pat(ty.fold_with(folder), pat.fold_with(folder)),
442
443            ty::Bool
444            | ty::Char
445            | ty::Str
446            | ty::Int(_)
447            | ty::Uint(_)
448            | ty::Float(_)
449            | ty::Error(_)
450            | ty::Infer(_)
451            | ty::Param(..)
452            | ty::Bound(..)
453            | ty::Placeholder(..)
454            | ty::Never
455            | ty::Foreign(..) => return self,
456        };
457
458        if *self.kind() == kind { self } else { folder.cx().mk_ty_from_kind(kind) }
459    }
460}
461
462impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for Ty<'tcx> {
463    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
464        match self.kind() {
465            ty::RawPtr(ty, _mutbl) => ty.visit_with(visitor),
466            ty::Array(typ, sz) => {
467                try_visit!(typ.visit_with(visitor));
468                sz.visit_with(visitor)
469            }
470            ty::Slice(typ) => typ.visit_with(visitor),
471            ty::Adt(_, args) => args.visit_with(visitor),
472            ty::Dynamic(trait_ty, reg) => {
473                try_visit!(trait_ty.visit_with(visitor));
474                reg.visit_with(visitor)
475            }
476            ty::Tuple(ts) => ts.visit_with(visitor),
477            ty::FnDef(_, args) => args.visit_with(visitor),
478            ty::FnPtr(sig_tys, _) => sig_tys.visit_with(visitor),
479            ty::UnsafeBinder(f) => f.visit_with(visitor),
480            ty::Ref(r, ty, _) => {
481                try_visit!(r.visit_with(visitor));
482                ty.visit_with(visitor)
483            }
484            ty::Coroutine(_did, args) => args.visit_with(visitor),
485            ty::CoroutineWitness(_did, args) => args.visit_with(visitor),
486            ty::Closure(_did, args) => args.visit_with(visitor),
487            ty::CoroutineClosure(_did, args) => args.visit_with(visitor),
488            ty::Alias(_, data) => data.visit_with(visitor),
489
490            ty::Pat(ty, pat) => {
491                try_visit!(ty.visit_with(visitor));
492                pat.visit_with(visitor)
493            }
494
495            ty::Error(guar) => guar.visit_with(visitor),
496
497            ty::Bool
498            | ty::Char
499            | ty::Str
500            | ty::Int(_)
501            | ty::Uint(_)
502            | ty::Float(_)
503            | ty::Infer(_)
504            | ty::Bound(..)
505            | ty::Placeholder(..)
506            | ty::Param(..)
507            | ty::Never
508            | ty::Foreign(..) => V::Result::output(),
509        }
510    }
511}
512
513impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Region<'tcx> {
514    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
515        self,
516        folder: &mut F,
517    ) -> Result<Self, F::Error> {
518        folder.try_fold_region(self)
519    }
520
521    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
522        folder.fold_region(self)
523    }
524}
525
526impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Region<'tcx> {
527    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
528        visitor.visit_region(*self)
529    }
530}
531
532impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
533    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
534        self,
535        folder: &mut F,
536    ) -> Result<Self, F::Error> {
537        folder.try_fold_predicate(self)
538    }
539
540    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
541        folder.fold_predicate(self)
542    }
543}
544
545// FIXME(clause): This is wonky
546impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
547    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
548        self,
549        folder: &mut F,
550    ) -> Result<Self, F::Error> {
551        Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
552    }
553
554    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
555        folder.fold_predicate(self.as_predicate()).expect_clause()
556    }
557}
558
559impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
560    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
561        self,
562        folder: &mut F,
563    ) -> Result<Self, F::Error> {
564        folder.try_fold_clauses(self)
565    }
566
567    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
568        folder.fold_clauses(self)
569    }
570}
571
572impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
573    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
574        visitor.visit_predicate(*self)
575    }
576}
577
578impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clause<'tcx> {
579    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
580        visitor.visit_predicate(self.as_predicate())
581    }
582}
583
584impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
585    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
586        self,
587        folder: &mut F,
588    ) -> Result<Self, F::Error> {
589        let new = self.kind().try_fold_with(folder)?;
590        Ok(folder.cx().reuse_or_mk_predicate(self, new))
591    }
592
593    fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
594        let new = self.kind().fold_with(folder);
595        folder.cx().reuse_or_mk_predicate(self, new)
596    }
597}
598
599impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Predicate<'tcx> {
600    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
601        self.kind().visit_with(visitor)
602    }
603}
604
605impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
606    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
607        visitor.visit_clauses(self)
608    }
609}
610
611impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
612    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
613        self.as_slice().visit_with(visitor)
614    }
615}
616
617impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Clauses<'tcx> {
618    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
619        self,
620        folder: &mut F,
621    ) -> Result<Self, F::Error> {
622        ty::util::try_fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
623    }
624
625    fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
626        ty::util::fold_list(self, folder, |tcx, v| tcx.mk_clauses(v))
627    }
628}
629
630impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
631    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
632        self,
633        folder: &mut F,
634    ) -> Result<Self, F::Error> {
635        folder.try_fold_const(self)
636    }
637
638    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
639        folder.fold_const(self)
640    }
641}
642
643impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
644    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
645        visitor.visit_const(*self)
646    }
647}
648
649impl<'tcx> TypeSuperFoldable<TyCtxt<'tcx>> for ty::Const<'tcx> {
650    fn try_super_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
651        self,
652        folder: &mut F,
653    ) -> Result<Self, F::Error> {
654        let kind = match self.kind() {
655            ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.try_fold_with(folder)?),
656            ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?),
657            ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?),
658
659            ConstKind::Param(_)
660            | ConstKind::Infer(_)
661            | ConstKind::Bound(..)
662            | ConstKind::Placeholder(_)
663            | ConstKind::Error(_) => return Ok(self),
664        };
665        if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) }
666    }
667
668    fn super_fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
669        let kind = match self.kind() {
670            ConstKind::Unevaluated(uv) => ConstKind::Unevaluated(uv.fold_with(folder)),
671            ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)),
672            ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)),
673
674            ConstKind::Param(_)
675            | ConstKind::Infer(_)
676            | ConstKind::Bound(..)
677            | ConstKind::Placeholder(_)
678            | ConstKind::Error(_) => return self,
679        };
680        if kind != self.kind() { folder.cx().mk_ct_from_kind(kind) } else { self }
681    }
682}
683
684impl<'tcx> TypeSuperVisitable<TyCtxt<'tcx>> for ty::Const<'tcx> {
685    fn super_visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
686        match self.kind() {
687            ConstKind::Unevaluated(uv) => uv.visit_with(visitor),
688            ConstKind::Value(v) => v.visit_with(visitor),
689            ConstKind::Expr(e) => e.visit_with(visitor),
690            ConstKind::Error(e) => e.visit_with(visitor),
691
692            ConstKind::Param(_)
693            | ConstKind::Infer(_)
694            | ConstKind::Bound(..)
695            | ConstKind::Placeholder(_) => V::Result::output(),
696        }
697    }
698}
699
700impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
701    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
702        visitor.visit_error(*self)
703    }
704}
705
706impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for rustc_span::ErrorGuaranteed {
707    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
708        self,
709        _folder: &mut F,
710    ) -> Result<Self, F::Error> {
711        Ok(self)
712    }
713
714    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, _folder: &mut F) -> Self {
715        self
716    }
717}
718
719impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for TyAndLayout<'tcx, Ty<'tcx>> {
720    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
721        visitor.visit_ty(self.ty)
722    }
723}
724
725impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>> + Debug + Clone> TypeVisitable<TyCtxt<'tcx>>
726    for Spanned<T>
727{
728    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
729        try_visit!(self.node.visit_with(visitor));
730        self.span.visit_with(visitor)
731    }
732}
733
734impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>> + Debug + Clone> TypeFoldable<TyCtxt<'tcx>>
735    for Spanned<T>
736{
737    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
738        self,
739        folder: &mut F,
740    ) -> Result<Self, F::Error> {
741        Ok(Spanned {
742            node: self.node.try_fold_with(folder)?,
743            span: self.span.try_fold_with(folder)?,
744        })
745    }
746
747    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, folder: &mut F) -> Self {
748        Spanned { node: self.node.fold_with(folder), span: self.span.fold_with(folder) }
749    }
750}
751
752impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<LocalDefId> {
753    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
754        self,
755        _folder: &mut F,
756    ) -> Result<Self, F::Error> {
757        Ok(self)
758    }
759
760    fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(self, _folder: &mut F) -> Self {
761        self
762    }
763}
764
765macro_rules! list_fold {
766    ($($ty:ty : $mk:ident),+ $(,)?) => {
767        $(
768            impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for $ty {
769                fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
770                    self,
771                    folder: &mut F,
772                ) -> Result<Self, F::Error> {
773                    ty::util::try_fold_list(self, folder, |tcx, v| tcx.$mk(v))
774                }
775
776                fn fold_with<F: TypeFolder<TyCtxt<'tcx>>>(
777                    self,
778                    folder: &mut F,
779                ) -> Self {
780                    ty::util::fold_list(self, folder, |tcx, v| tcx.$mk(v))
781                }
782            }
783        )*
784    }
785}
786
787list_fold! {
788    &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>> : mk_poly_existential_predicates,
789    &'tcx ty::List<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>: mk_predefined_opaques_in_body,
790    &'tcx ty::List<PlaceElem<'tcx>> : mk_place_elems,
791    &'tcx ty::List<ty::Pattern<'tcx>> : mk_patterns,
792    &'tcx ty::List<ty::ArgOutlivesPredicate<'tcx>> : mk_outlives,
793}