Skip to main content

flux_rustc_bridge/ty/
mod.rs

1//! A simplified version of rust types.
2
3mod subst;
4
5use std::fmt;
6
7pub use flux_arc_interner::List;
8use flux_arc_interner::{Interned, impl_internable, impl_slice_internable};
9use flux_common::{bug, tracked_span_assert_eq, tracked_span_bug};
10use itertools::Itertools;
11use rustc_abi;
12pub use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx};
13use rustc_hir::{Safety, def_id::DefId};
14use rustc_index::{IndexSlice, IndexVec};
15use rustc_macros::{Decodable, Encodable, TyDecodable, TyEncodable, extension};
16pub use rustc_middle::{
17    mir::Mutability,
18    ty::{
19        BoundVar, ConstVid, DebruijnIndex, EarlyParamRegion, FloatTy, IntTy, LateParamRegionKind,
20        ParamTy, RegionVid, ScalarInt, UintTy,
21    },
22};
23use rustc_middle::{
24    mir::Promoted,
25    ty::{self as rustc_ty, AdtFlags, ParamConst, TyCtxt},
26};
27use rustc_span::Symbol;
28pub use rustc_type_ir::InferConst;
29
30use self::subst::Subst;
31use super::ToRustc;
32use crate::def_id_to_string;
33
34#[derive(Debug, Clone)]
35pub struct Generics<'tcx> {
36    pub params: List<GenericParamDef>,
37    pub orig: &'tcx rustc_middle::ty::Generics,
38}
39
40#[derive(Clone)]
41pub struct EarlyBinder<T>(pub T);
42
43#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
44pub struct Binder<T>(T, List<BoundVariableKind>);
45
46#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
47pub enum BoundRegionKind {
48    /// An anonymous region parameter for a given fn (&T)
49    Anon,
50    /// An anonymous region parameter with a `Symbol` name.
51    ///
52    /// Used to give late-bound regions names for things like pretty printing.
53    NamedForPrinting(Symbol),
54    /// Late-bound regions that appear in the AST.
55    Named(DefId),
56    /// Anonymous region for the implicit env pointer parameter
57    /// to a closure
58    ClosureEnv,
59}
60
61#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, Encodable, Decodable)]
62pub enum BoundVariableKind {
63    Region(BoundRegionKind),
64}
65
66impl BoundVariableKind {
67    // We can't implement [`ToRustc`] on [`List<BoundVariableKind>`] because of coherence so we add
68    // it here
69    fn to_rustc<'tcx>(
70        vars: &[Self],
71        tcx: TyCtxt<'tcx>,
72    ) -> &'tcx rustc_middle::ty::List<rustc_middle::ty::BoundVariableKind<'tcx>> {
73        tcx.mk_bound_variable_kinds_from_iter(vars.iter().flat_map(|kind| {
74            match kind {
75                BoundVariableKind::Region(brk) => {
76                    Some(rustc_middle::ty::BoundVariableKind::Region(brk.to_rustc(tcx)))
77                }
78            }
79        }))
80    }
81}
82
83impl<'tcx> ToRustc<'tcx> for BoundRegionKind {
84    type T = rustc_middle::ty::BoundRegionKind<'tcx>;
85
86    fn to_rustc(&self, _tcx: TyCtxt<'tcx>) -> Self::T {
87        match *self {
88            BoundRegionKind::Anon => rustc_middle::ty::BoundRegionKind::Anon,
89            BoundRegionKind::NamedForPrinting(name) => {
90                rustc_middle::ty::BoundRegionKind::NamedForPrinting(name)
91            }
92            BoundRegionKind::Named(def_id) => rustc_middle::ty::BoundRegionKind::Named(def_id),
93            BoundRegionKind::ClosureEnv => rustc_middle::ty::BoundRegionKind::ClosureEnv,
94        }
95    }
96}
97
98#[derive(Debug, Hash, Eq, PartialEq, TyEncodable, TyDecodable)]
99pub struct GenericParamDef {
100    pub def_id: DefId,
101    pub index: u32,
102    pub name: Symbol,
103    pub kind: GenericParamDefKind,
104}
105
106#[derive(Debug, Hash, Eq, PartialEq, Clone, Copy, TyEncodable, TyDecodable)]
107pub enum GenericParamDefKind {
108    Type { has_default: bool },
109    Lifetime,
110    Const { has_default: bool },
111}
112
113#[derive(Clone, Debug)]
114pub struct GenericPredicates {
115    pub parent: Option<DefId>,
116    pub predicates: List<Clause>,
117}
118
119#[derive(PartialEq, Eq, Hash, Debug)]
120pub struct Clause {
121    pub kind: Binder<ClauseKind>,
122}
123
124#[derive(PartialEq, Eq, Hash, Debug)]
125pub enum ClauseKind {
126    Trait(TraitPredicate),
127    Projection(ProjectionPredicate),
128    RegionOutlives(RegionOutlivesPredicate),
129    TypeOutlives(TypeOutlivesPredicate),
130    ConstArgHasType(Const, Ty),
131    UnstableFeature(Symbol),
132}
133
134#[derive(Eq, PartialEq, Hash, Clone, Debug, TyEncodable, TyDecodable)]
135pub struct OutlivesPredicate<T>(pub T, pub Region);
136
137pub type TypeOutlivesPredicate = OutlivesPredicate<Ty>;
138pub type RegionOutlivesPredicate = OutlivesPredicate<Region>;
139
140#[derive(PartialEq, Eq, Hash, Debug)]
141pub struct TraitPredicate {
142    pub trait_ref: TraitRef,
143}
144
145#[derive(PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
146pub struct TraitRef {
147    pub def_id: DefId,
148    pub args: GenericArgs,
149}
150
151impl TraitRef {
152    pub fn self_ty(&self) -> &Ty {
153        self.args[0].expect_type()
154    }
155}
156
157pub type PolyTraitRef = Binder<TraitRef>;
158
159#[derive(PartialEq, Eq, Hash, Debug)]
160pub struct ProjectionPredicate {
161    pub projection_term: AliasTerm,
162    pub term: Ty,
163}
164
165/// Mirrors [`rustc_middle::ty::AliasTerm`].
166#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
167pub struct AliasTerm {
168    pub kind: AliasTermKind,
169    pub args: GenericArgs,
170}
171
172impl AliasTerm {
173    pub fn def_id(&self) -> DefId {
174        self.kind.def_id()
175    }
176}
177
178#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
179pub enum AliasTermKind {
180    ProjectionTy { def_id: DefId },
181    OpaqueTy { def_id: DefId },
182    FreeTy { def_id: DefId },
183}
184
185impl AliasTermKind {
186    pub fn def_id(self) -> DefId {
187        let (AliasTermKind::ProjectionTy { def_id }
188        | AliasTermKind::OpaqueTy { def_id }
189        | AliasTermKind::FreeTy { def_id }) = self;
190        def_id
191    }
192
193    pub fn to_rustc_kind<'tcx>(self) -> rustc_middle::ty::AliasTermKind<'tcx> {
194        use rustc_middle::ty;
195        match self {
196            AliasTermKind::ProjectionTy { def_id } => ty::AliasTermKind::ProjectionTy { def_id },
197            AliasTermKind::OpaqueTy { def_id } => ty::AliasTermKind::OpaqueTy { def_id },
198            AliasTermKind::FreeTy { def_id } => ty::AliasTermKind::FreeTy { def_id },
199        }
200    }
201}
202#[derive(Clone, Hash, PartialEq, Eq, TyEncodable, TyDecodable)]
203pub struct FnSig {
204    pub safety: Safety,
205    pub abi: rustc_abi::ExternAbi,
206    pub(crate) inputs_and_output: List<Ty>,
207}
208
209pub type PolyFnSig = Binder<FnSig>;
210
211impl PolyFnSig {
212    pub fn unpack_closure_sig(&self) -> Self {
213        let vars = self.vars().clone();
214        let fn_sig = self.skip_binder_ref();
215        let [input] = &fn_sig.inputs() else {
216            bug!("closure signature should have at least two values");
217        };
218        let fn_sig = FnSig {
219            safety: fn_sig.safety,
220            abi: fn_sig.abi,
221            inputs_and_output: input
222                .tuple_fields()
223                .iter()
224                .cloned()
225                .chain([fn_sig.output().clone()])
226                .collect(),
227        };
228        Binder::bind_with_vars(fn_sig, vars)
229    }
230}
231
232#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
233pub struct Ty(Interned<TyS>);
234
235#[derive(Debug, Eq, PartialEq, Hash, Clone, TyEncodable, TyDecodable)]
236pub struct AdtDef(Interned<AdtDefData>);
237
238#[derive(Debug, TyEncodable, TyDecodable)]
239pub struct AdtDefData {
240    pub did: DefId,
241    variants: IndexVec<VariantIdx, VariantDef>,
242    discrs: IndexVec<VariantIdx, u128>,
243    flags: AdtFlags,
244}
245
246/// There should be only one AdtDef for each `did`, therefore
247/// it is fine to implement `Hash` only based on `did`.
248impl std::hash::Hash for AdtDefData {
249    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
250        self.did.hash(state);
251    }
252}
253
254/// There should be only one AdtDef for each `did`, therefore
255/// it is fine to implement `PartialEq` only based on `did`.
256impl PartialEq for AdtDefData {
257    fn eq(&self, other: &Self) -> bool {
258        self.did == other.did
259    }
260}
261
262impl Eq for AdtDefData {}
263
264#[derive(Debug, TyEncodable, TyDecodable)]
265pub struct VariantDef {
266    pub def_id: DefId,
267    pub name: Symbol,
268    pub fields: IndexVec<FieldIdx, FieldDef>,
269}
270
271#[derive(Debug, Eq, PartialEq, Hash, TyEncodable, TyDecodable)]
272pub struct FieldDef {
273    pub did: DefId,
274    pub name: Symbol,
275}
276
277#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
278struct TyS {
279    kind: TyKind,
280}
281
282#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
283pub enum TyKind {
284    Adt(AdtDef, GenericArgs),
285    Array(Ty, Const),
286    Bool,
287    Str,
288    Char,
289    Float(FloatTy),
290    Int(IntTy),
291    Never,
292    Param(ParamTy),
293    Ref(Region, Ty, Mutability),
294    Tuple(List<Ty>),
295    Uint(UintTy),
296    Slice(Ty),
297    FnPtr(PolyFnSig),
298    FnDef(DefId, GenericArgs),
299    Closure(DefId, GenericArgs),
300    Coroutine(DefId, GenericArgs),
301    CoroutineWitness(DefId, GenericArgs),
302    Alias(AliasTy),
303    RawPtr(Ty, Mutability),
304    Dynamic(List<Binder<ExistentialPredicate>>, Region),
305    Foreign(DefId),
306    Pat,
307}
308
309#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
310pub enum ExistentialPredicate {
311    Trait(ExistentialTraitRef),
312    Projection(ExistentialProjection),
313    AutoTrait(DefId),
314}
315
316pub type PolyExistentialPredicate = Binder<ExistentialPredicate>;
317
318#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
319pub struct ExistentialTraitRef {
320    pub def_id: DefId,
321    pub args: GenericArgs,
322}
323
324#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
325pub struct ExistentialProjection {
326    pub def_id: DefId,
327    pub args: GenericArgs,
328    pub term: Ty,
329}
330
331#[derive(Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
332pub struct AliasTy {
333    pub kind: AliasKind,
334    pub args: GenericArgs,
335}
336
337#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
338pub enum AliasKind {
339    Projection { def_id: DefId },
340    Opaque { def_id: DefId },
341    Free { def_id: DefId },
342}
343
344impl AliasKind {
345    pub fn to_rustc_kind<'tcx>(self) -> rustc_middle::ty::AliasTyKind<'tcx> {
346        use rustc_middle::ty;
347        match self {
348            AliasKind::Opaque { def_id } => ty::AliasTyKind::Opaque { def_id },
349            AliasKind::Projection { def_id } => ty::AliasTyKind::Projection { def_id },
350            AliasKind::Free { def_id } => ty::AliasTyKind::Free { def_id },
351        }
352    }
353}
354
355#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
356pub struct Const {
357    pub kind: ConstKind,
358}
359
360impl<'tcx> ToRustc<'tcx> for AliasConst {
361    type T = rustc_middle::ty::AliasConst<'tcx>;
362
363    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
364        let args = tcx.mk_args_from_iter(self.args.iter().map(|arg| arg.to_rustc(tcx)));
365        rustc_ty::AliasConst::new(tcx, self.kind.to_rustc_kind(), args)
366    }
367}
368
369impl Const {
370    pub fn from_usize(tcx: TyCtxt, v: usize) -> Self {
371        Self {
372            kind: ConstKind::Value(
373                Ty::mk_uint(UintTy::Usize),
374                ValTree::Leaf(ScalarInt::try_from_target_usize(v as u128, tcx).unwrap()),
375            ),
376        }
377    }
378}
379
380impl<'tcx> ToRustc<'tcx> for ValTree {
381    type T = rustc_middle::ty::ValTree<'tcx>;
382
383    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
384        match self {
385            ValTree::Leaf(scalar) => rustc_middle::ty::ValTree::from_scalar_int(tcx, *scalar),
386            ValTree::Branch(consts) => {
387                let consts = consts.iter().map(|c| c.to_rustc(tcx));
388                rustc_middle::ty::ValTree::from_branches(tcx, consts)
389            }
390        }
391    }
392}
393
394impl<'tcx> ToRustc<'tcx> for Const {
395    type T = rustc_ty::Const<'tcx>;
396
397    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
398        let kind = match &self.kind {
399            ConstKind::Param(param_const) => rustc_ty::ConstKind::Param(*param_const),
400            ConstKind::Value(ty, val) => {
401                let val = rustc_ty::Value { ty: ty.to_rustc(tcx), valtree: val.to_rustc(tcx) };
402                rustc_ty::ConstKind::Value(val)
403            }
404            ConstKind::Infer(infer_const) => rustc_ty::ConstKind::Infer(*infer_const),
405            ConstKind::Alias(uneval_const) => {
406                rustc_ty::ConstKind::Alias(rustc_ty::IsRigid::No, uneval_const.to_rustc(tcx))
407            }
408        };
409        rustc_ty::Const::new(tcx, kind)
410    }
411}
412
413#[derive(Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
414pub struct AliasConst {
415    pub kind: AliasConstKind,
416    pub args: GenericArgs,
417    pub promoted: Option<Promoted>,
418}
419
420/// Mirrors [`rustc_middle::ty::AliasConstKind`].
421#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
422pub enum AliasConstKind {
423    Projection { def_id: DefId },
424    InherentSelf { def_id: DefId },
425    InherentImpl { def_id: DefId },
426    Free { def_id: DefId },
427    Anon { def_id: DefId },
428}
429
430impl AliasConstKind {
431    pub fn to_rustc_kind<'tcx>(self) -> rustc_middle::ty::AliasConstKind<'tcx> {
432        use rustc_middle::ty;
433        match self {
434            AliasConstKind::Projection { def_id } => ty::AliasConstKind::Projection { def_id },
435            AliasConstKind::InherentSelf { def_id } => ty::AliasConstKind::InherentSelf { def_id },
436            AliasConstKind::InherentImpl { def_id } => ty::AliasConstKind::InherentImpl { def_id },
437            AliasConstKind::Free { def_id } => ty::AliasConstKind::Free { def_id },
438            AliasConstKind::Anon { def_id } => ty::AliasConstKind::Anon { def_id },
439        }
440    }
441}
442
443#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
444pub enum ValTree {
445    Leaf(ScalarInt),
446    Branch(List<Const>),
447}
448
449#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
450pub enum ConstKind {
451    Param(ParamConst),
452    Value(Ty, ValTree),
453    Infer(InferConst),
454    Alias(AliasConst),
455}
456
457#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
458pub enum GenericArg {
459    Ty(Ty),
460    Lifetime(Region),
461    Const(Const),
462}
463
464pub type GenericArgs = List<GenericArg>;
465
466#[extension(pub trait GenericArgsExt)]
467impl GenericArgs {
468    fn box_args(&self) -> (&Ty, &Ty) {
469        if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
470            (deref, alloc)
471        } else {
472            bug!("invalid generic arguments for box");
473        }
474    }
475
476    fn as_closure(&self) -> ClosureArgs {
477        ClosureArgs { args: self.clone() }
478    }
479
480    fn as_coroutine(&self) -> CoroutineArgs {
481        CoroutineArgs { args: self.clone() }
482    }
483}
484
485pub struct CoroutineArgs {
486    pub args: GenericArgs,
487}
488
489pub struct ClosureArgs {
490    pub args: GenericArgs,
491}
492
493#[expect(unused, reason = "keeping this in case we use it")]
494pub struct ClosureArgsParts<'a, T> {
495    parent_args: &'a [T],
496    closure_kind_ty: &'a T,
497    closure_sig_as_fn_ptr_ty: &'a T,
498    tupled_upvars_ty: &'a T,
499}
500
501#[derive(Debug)]
502pub struct CoroutineArgsParts<'a> {
503    pub parent_args: &'a [GenericArg],
504    pub kind_ty: &'a Ty,
505    pub resume_ty: &'a Ty,
506    pub yield_ty: &'a Ty,
507    pub return_ty: &'a Ty,
508    pub tupled_upvars_ty: &'a Ty,
509}
510
511/// Mirrors [`rustc_middle::ty::LateParamRegion`].
512#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
513pub struct LateParamRegion {
514    pub scope: DefId,
515    pub kind: LateParamRegionKind,
516}
517
518#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
519pub enum Region {
520    ReBound(DebruijnIndex, BoundRegion),
521    ReEarlyParam(EarlyParamRegion),
522    ReStatic,
523    ReVar(RegionVid),
524    ReLateParam(LateParamRegion),
525    ReErased,
526}
527
528impl<'tcx> ToRustc<'tcx> for Region {
529    type T = rustc_middle::ty::Region<'tcx>;
530
531    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
532        match *self {
533            Region::ReBound(debruijn, bound_region) => {
534                rustc_middle::ty::Region::new_bound(tcx, debruijn, bound_region.to_rustc(tcx))
535            }
536            Region::ReEarlyParam(epr) => rustc_middle::ty::Region::new_early_param(tcx, epr),
537            Region::ReStatic => tcx.lifetimes.re_static,
538            Region::ReVar(rvid) => rustc_middle::ty::Region::new_var(tcx, rvid),
539            Region::ReLateParam(LateParamRegion { scope, kind }) => {
540                rustc_middle::ty::Region::new_late_param(tcx, scope, kind)
541            }
542            Region::ReErased => tcx.lifetimes.re_erased,
543        }
544    }
545}
546
547#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
548pub struct BoundRegion {
549    pub var: BoundVar,
550    pub kind: BoundRegionKind,
551}
552
553impl<'tcx> ToRustc<'tcx> for BoundRegion {
554    type T = rustc_middle::ty::BoundRegion<'tcx>;
555
556    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
557        rustc_middle::ty::BoundRegion { var: self.var, kind: self.kind.to_rustc(tcx) }
558    }
559}
560
561impl Generics<'_> {
562    pub fn parent(&self) -> Option<DefId> {
563        self.orig.parent
564    }
565
566    pub fn parent_count(&self) -> usize {
567        self.orig.parent_count
568    }
569}
570
571impl Clause {
572    pub(crate) fn new(kind: Binder<ClauseKind>) -> Clause {
573        Clause { kind }
574    }
575}
576
577impl<T> EarlyBinder<T> {
578    pub fn skip_binder(self) -> T {
579        self.0
580    }
581
582    pub fn instantiate_identity(self) -> T {
583        self.0
584    }
585}
586
587impl EarlyBinder<Ty> {
588    pub fn subst(&self, args: &[GenericArg]) -> Ty {
589        self.0.subst(args)
590    }
591}
592
593impl<T> Binder<T> {
594    pub fn dummy(value: T) -> Binder<T> {
595        Binder(value, List::empty())
596    }
597
598    pub fn bind_with_vars(value: T, vars: impl Into<List<BoundVariableKind>>) -> Binder<T> {
599        Binder(value, vars.into())
600    }
601
602    pub fn skip_binder(self) -> T {
603        self.0
604    }
605
606    pub fn skip_binder_ref(&self) -> &T {
607        self.as_ref().skip_binder()
608    }
609
610    pub fn as_ref(&self) -> Binder<&T> {
611        Binder(&self.0, self.1.clone())
612    }
613
614    pub fn vars(&self) -> &List<BoundVariableKind> {
615        &self.1
616    }
617}
618
619impl FnSig {
620    pub fn inputs(&self) -> &[Ty] {
621        &self.inputs_and_output[..self.inputs_and_output.len() - 1]
622    }
623
624    pub fn output(&self) -> &Ty {
625        &self.inputs_and_output[self.inputs_and_output.len() - 1]
626    }
627}
628
629impl GenericArg {
630    pub fn expect_type(&self) -> &Ty {
631        if let GenericArg::Ty(ty) = self {
632            ty
633        } else {
634            bug!("expected `GenericArg::Ty`, found {:?}", self)
635        }
636    }
637
638    fn expect_lifetime(&self) -> Region {
639        if let GenericArg::Lifetime(re) = self {
640            *re
641        } else {
642            bug!("expected `GenericArg::Lifetime`, found {:?}", self)
643        }
644    }
645
646    fn expect_const(&self) -> &Const {
647        if let GenericArg::Const(c) = self {
648            c
649        } else {
650            bug!("expected `GenericArg::Const`, found {:?}", self)
651        }
652    }
653}
654
655impl<'tcx> ToRustc<'tcx> for GenericArgs {
656    type T = rustc_middle::ty::GenericArgsRef<'tcx>;
657
658    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
659        tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
660    }
661}
662
663impl<'tcx> ToRustc<'tcx> for GenericArg {
664    type T = rustc_middle::ty::GenericArg<'tcx>;
665
666    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
667        use rustc_middle::ty;
668        match self {
669            GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
670            GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
671            GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
672        }
673    }
674}
675
676impl CoroutineArgs {
677    pub fn tupled_upvars_ty(&self) -> &Ty {
678        self.split().tupled_upvars_ty
679    }
680
681    pub fn upvar_tys(&self) -> impl Iterator<Item = &Ty> {
682        self.tupled_upvars_ty().tuple_fields().iter()
683    }
684
685    pub fn resume_ty(&self) -> &Ty {
686        self.split().resume_ty
687    }
688
689    fn split(&self) -> CoroutineArgsParts<'_> {
690        match &self.args[..] {
691            [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
692                CoroutineArgsParts {
693                    parent_args,
694                    kind_ty: kind_ty.expect_type(),
695                    resume_ty: resume_ty.expect_type(),
696                    yield_ty: yield_ty.expect_type(),
697                    return_ty: return_ty.expect_type(),
698                    tupled_upvars_ty: tupled_upvars_ty.expect_type(),
699                }
700            }
701            _ => bug!("generator args missing synthetics"),
702        }
703    }
704}
705
706impl ClosureArgs {
707    pub fn tupled_upvars_ty(&self) -> &Ty {
708        self.split().tupled_upvars_ty.expect_type()
709    }
710
711    pub fn upvar_tys(&self) -> &List<Ty> {
712        self.tupled_upvars_ty().tuple_fields()
713    }
714
715    pub fn split(&self) -> ClosureArgsParts<'_, GenericArg> {
716        match &self.args[..] {
717            [parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
718                ClosureArgsParts {
719                    parent_args,
720                    closure_kind_ty,
721                    closure_sig_as_fn_ptr_ty,
722                    tupled_upvars_ty,
723                }
724            }
725            _ => bug!("closure args missing synthetics"),
726        }
727    }
728
729    pub fn sig_as_fn_ptr_ty(&self) -> &Ty {
730        self.split().closure_sig_as_fn_ptr_ty.expect_type()
731    }
732
733    pub fn kind_ty(&self) -> &Ty {
734        self.split().closure_kind_ty.expect_type()
735    }
736}
737
738impl AdtDef {
739    pub(crate) fn new(data: AdtDefData) -> Self {
740        Self(Interned::new(data))
741    }
742
743    pub fn did(&self) -> DefId {
744        self.0.did
745    }
746
747    pub fn flags(&self) -> AdtFlags {
748        self.0.flags
749    }
750
751    pub fn is_struct(&self) -> bool {
752        self.flags().contains(AdtFlags::IS_STRUCT)
753    }
754
755    pub fn is_union(&self) -> bool {
756        self.flags().contains(AdtFlags::IS_UNION)
757    }
758
759    pub fn is_enum(&self) -> bool {
760        self.flags().contains(AdtFlags::IS_ENUM)
761    }
762
763    pub fn is_box(&self) -> bool {
764        self.flags().contains(AdtFlags::IS_BOX)
765    }
766
767    pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
768        &self.0.variants[idx]
769    }
770
771    pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
772        &self.0.variants
773    }
774
775    pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
776        self.0
777            .discrs
778            .iter_enumerated()
779            .map(|(idx, discr)| (idx, *discr))
780    }
781
782    pub fn non_enum_variant(&self) -> &VariantDef {
783        assert!(self.is_struct() || self.is_union());
784        self.variant(FIRST_VARIANT)
785    }
786}
787
788impl<'tcx> ToRustc<'tcx> for AdtDef {
789    type T = rustc_middle::ty::AdtDef<'tcx>;
790
791    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
792        tcx.adt_def(self.did())
793    }
794}
795
796impl AdtDefData {
797    pub(crate) fn new<'tcx>(
798        tcx: TyCtxt<'tcx>,
799        adt_def: rustc_middle::ty::AdtDef<'tcx>,
800        variants: IndexVec<VariantIdx, VariantDef>,
801    ) -> Self {
802        let discrs: IndexVec<VariantIdx, u128> = if adt_def.is_enum() {
803            adt_def
804                .discriminants(tcx)
805                .map(|(_, discr)| discr.val)
806                .collect()
807        } else {
808            IndexVec::from_raw(vec![0])
809        };
810        tracked_span_assert_eq!(discrs.len(), variants.len());
811        Self { did: adt_def.did(), variants, flags: adt_def.flags(), discrs }
812    }
813}
814
815impl AliasTy {
816    /// This method work only with associated type projections (i.e., no opaque tpes)
817    pub fn self_ty(&self) -> &Ty {
818        self.args[0].expect_type()
819    }
820}
821
822impl TyKind {
823    fn intern(self) -> Ty {
824        Ty(Interned::new(TyS { kind: self }))
825    }
826}
827
828impl Ty {
829    pub fn mk_adt(adt_def: AdtDef, args: impl Into<GenericArgs>) -> Ty {
830        let args = args.into();
831        TyKind::Adt(adt_def, args).intern()
832    }
833
834    pub fn mk_closure(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
835        TyKind::Closure(def_id, args.into()).intern()
836    }
837
838    pub fn mk_fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
839        TyKind::FnDef(def_id, args.into()).intern()
840    }
841
842    pub fn mk_coroutine(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
843        TyKind::Coroutine(def_id, args.into()).intern()
844    }
845
846    pub fn mk_generator_witness(def_id: DefId, args: GenericArgs) -> Ty {
847        TyKind::CoroutineWitness(def_id, args).intern()
848    }
849
850    pub fn mk_alias(kind: AliasKind, args: impl Into<GenericArgs>) -> Ty {
851        TyKind::Alias(AliasTy { kind, args: args.into() }).intern()
852    }
853
854    pub fn mk_array(ty: Ty, c: Const) -> Ty {
855        TyKind::Array(ty, c).intern()
856    }
857
858    pub fn mk_slice(ty: Ty) -> Ty {
859        TyKind::Slice(ty).intern()
860    }
861
862    pub fn mk_fn_ptr(fn_sig: PolyFnSig) -> Ty {
863        TyKind::FnPtr(fn_sig).intern()
864    }
865
866    pub fn mk_raw_ptr(ty: Ty, mutbl: Mutability) -> Ty {
867        TyKind::RawPtr(ty, mutbl).intern()
868    }
869
870    pub fn mk_bool() -> Ty {
871        TyKind::Bool.intern()
872    }
873
874    pub fn mk_float(float_ty: FloatTy) -> Ty {
875        TyKind::Float(float_ty).intern()
876    }
877
878    pub fn mk_int(int_ty: IntTy) -> Ty {
879        TyKind::Int(int_ty).intern()
880    }
881
882    pub fn mk_never() -> Ty {
883        TyKind::Never.intern()
884    }
885
886    pub fn mk_param(param: ParamTy) -> Ty {
887        TyKind::Param(param).intern()
888    }
889
890    pub fn mk_dynamic(exi_preds: impl Into<List<Binder<ExistentialPredicate>>>, r: Region) -> Ty {
891        TyKind::Dynamic(exi_preds.into(), r).intern()
892    }
893
894    pub fn mk_ref(region: Region, ty: Ty, mutability: Mutability) -> Ty {
895        TyKind::Ref(region, ty, mutability).intern()
896    }
897
898    pub fn mk_tuple(tys: impl Into<List<Ty>>) -> Ty {
899        TyKind::Tuple(tys.into()).intern()
900    }
901
902    pub fn mk_uint(uint_ty: UintTy) -> Ty {
903        TyKind::Uint(uint_ty).intern()
904    }
905
906    pub fn mk_str() -> Ty {
907        TyKind::Str.intern()
908    }
909
910    pub fn mk_char() -> Ty {
911        TyKind::Char.intern()
912    }
913
914    pub fn mk_foreign(def_id: DefId) -> Ty {
915        TyKind::Foreign(def_id).intern()
916    }
917
918    pub fn mk_pat() -> Ty {
919        TyKind::Pat.intern()
920    }
921
922    pub fn deref(&self) -> Ty {
923        match self.kind() {
924            TyKind::Adt(adt_def, args) if adt_def.is_box() => args[0].expect_type().clone(),
925            TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => ty.clone(),
926            _ => tracked_span_bug!("deref projection of non-dereferenceable ty `{self:?}`"),
927        }
928    }
929
930    pub fn kind(&self) -> &TyKind {
931        &self.0.kind
932    }
933
934    pub fn tuple_fields(&self) -> &List<Ty> {
935        match self.kind() {
936            TyKind::Tuple(tys) => tys,
937            _ => bug!("tuple_fields called on non-tuple"),
938        }
939    }
940
941    pub fn expect_adt(&self) -> (&AdtDef, &GenericArgs) {
942        match self.kind() {
943            TyKind::Adt(adt_def, args) => (adt_def, args),
944            _ => bug!("expect_adt called on non-adt"),
945        }
946    }
947
948    pub fn is_mut_ref(&self) -> bool {
949        matches!(self.kind(), TyKind::Ref(.., Mutability::Mut))
950    }
951
952    pub fn is_box(&self) -> bool {
953        matches!(self.kind(), TyKind::Adt(adt, ..) if adt.is_box())
954    }
955}
956
957impl<'tcx, V> ToRustc<'tcx> for Binder<V>
958where
959    V: ToRustc<'tcx, T: rustc_middle::ty::TypeVisitable<TyCtxt<'tcx>>>,
960{
961    type T = rustc_middle::ty::Binder<'tcx, V::T>;
962
963    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
964        let vars = BoundVariableKind::to_rustc(self.vars(), tcx);
965        let value = self.skip_binder_ref().to_rustc(tcx);
966        rustc_middle::ty::Binder::bind_with_vars(value, vars)
967    }
968}
969
970impl<'tcx> ToRustc<'tcx> for FnSig {
971    type T = rustc_middle::ty::FnSig<'tcx>;
972
973    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
974        tcx.mk_fn_sig(
975            self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
976            self.output().to_rustc(tcx),
977            rustc_middle::ty::FnSigKind::default()
978                .set_abi(self.abi)
979                .set_safety(self.safety)
980                .set_c_variadic(false),
981        )
982    }
983}
984
985impl<'tcx> ToRustc<'tcx> for AliasTy {
986    type T = rustc_middle::ty::AliasTy<'tcx>;
987
988    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
989        rustc_middle::ty::AliasTy::new_from_args(
990            tcx,
991            self.kind.to_rustc_kind(),
992            self.args.to_rustc(tcx),
993        )
994    }
995}
996
997impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
998    type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
999
1000    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
1001        match self {
1002            ExistentialPredicate::Trait(trait_ref) => {
1003                let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
1004                    tcx,
1005                    trait_ref.def_id,
1006                    trait_ref.args.to_rustc(tcx),
1007                );
1008                rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
1009            }
1010            ExistentialPredicate::Projection(projection) => {
1011                rustc_middle::ty::ExistentialPredicate::Projection(
1012                    rustc_middle::ty::ExistentialProjection::new_from_args(
1013                        tcx,
1014                        projection.def_id,
1015                        projection.args.to_rustc(tcx),
1016                        projection.term.to_rustc(tcx).into(),
1017                    ),
1018                )
1019            }
1020            ExistentialPredicate::AutoTrait(def_id) => {
1021                rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
1022            }
1023        }
1024    }
1025}
1026
1027impl<'tcx> ToRustc<'tcx> for Ty {
1028    type T = rustc_middle::ty::Ty<'tcx>;
1029
1030    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
1031        match self.kind() {
1032            TyKind::Bool => tcx.types.bool,
1033            TyKind::Str => tcx.types.str_,
1034            TyKind::Char => tcx.types.char,
1035            TyKind::Never => tcx.types.never,
1036            TyKind::Foreign(def_id) => rustc_ty::Ty::new_foreign(tcx, *def_id),
1037            TyKind::Float(float_ty) => rustc_ty::Ty::new_float(tcx, *float_ty),
1038            TyKind::Int(int_ty) => rustc_ty::Ty::new_int(tcx, *int_ty),
1039            TyKind::Uint(uint_ty) => rustc_ty::Ty::new_uint(tcx, *uint_ty),
1040            TyKind::Adt(adt_def, args) => {
1041                let adt_def = adt_def.to_rustc(tcx);
1042                let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1043                rustc_ty::Ty::new_adt(tcx, adt_def, args)
1044            }
1045            TyKind::FnDef(def_id, args) => {
1046                let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1047                tcx.type_of(*def_id).instantiate(tcx, args).skip_norm_wip()
1048            }
1049            TyKind::Array(ty, len) => {
1050                let ty = ty.to_rustc(tcx);
1051                let len = len.to_rustc(tcx);
1052                rustc_ty::Ty::new_array_with_const_len(tcx, ty, len)
1053            }
1054            TyKind::Param(pty) => rustc_ty::Ty::new_param(tcx, pty.index, pty.name),
1055            TyKind::Ref(re, ty, mutbl) => {
1056                rustc_ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
1057            }
1058            TyKind::Tuple(tys) => {
1059                let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
1060                rustc_ty::Ty::new_tup(tcx, tcx.mk_type_list(&ts))
1061            }
1062            TyKind::Slice(ty) => rustc_ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
1063            TyKind::RawPtr(ty, mutbl) => rustc_ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
1064            TyKind::Closure(did, args) => rustc_ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
1065            TyKind::FnPtr(poly_sig) => rustc_ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
1066            TyKind::Alias(alias_ty) => {
1067                rustc_ty::Ty::new_alias(tcx, rustc_ty::IsRigid::No, alias_ty.to_rustc(tcx))
1068            }
1069            TyKind::Dynamic(exi_preds, re) => {
1070                let preds = exi_preds
1071                    .iter()
1072                    .map(|pred| pred.to_rustc(tcx))
1073                    .collect_vec();
1074
1075                let preds = tcx.mk_poly_existential_predicates(&preds);
1076                rustc_ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
1077            }
1078            TyKind::Pat => todo!(),
1079            TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
1080                bug!("TODO: to_rustc for `{self:?}`")
1081            }
1082        }
1083    }
1084}
1085
1086impl_internable!(TyS, AdtDefData);
1087impl_slice_internable!(
1088    Ty,
1089    GenericArg,
1090    GenericParamDef,
1091    BoundVariableKind,
1092    Clause,
1093    Const,
1094    Binder<ExistentialPredicate>,
1095);
1096
1097impl fmt::Debug for ExistentialPredicate {
1098    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1099        match self {
1100            ExistentialPredicate::Trait(trait_ref) => write!(f, "{trait_ref:?}"),
1101            ExistentialPredicate::Projection(proj) => write!(f, "({proj:?})"),
1102            ExistentialPredicate::AutoTrait(def_id) => {
1103                write!(f, "{}", def_id_to_string(*def_id))
1104            }
1105        }
1106    }
1107}
1108
1109impl fmt::Debug for ExistentialTraitRef {
1110    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1111        write!(f, "{}", def_id_to_string(self.def_id))?;
1112        if !self.args.is_empty() {
1113            write!(f, "<{:?}>", self.args.iter().format(","))?;
1114        }
1115        Ok(())
1116    }
1117}
1118
1119impl fmt::Debug for ExistentialProjection {
1120    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1121        write!(f, "{}", def_id_to_string(self.def_id))?;
1122        if !self.args.is_empty() {
1123            write!(f, "<{:?}>", self.args.iter().format(","))?;
1124        }
1125        write!(f, " = {:?}", self.term)
1126    }
1127}
1128
1129impl fmt::Debug for GenericArg {
1130    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1131        match self {
1132            GenericArg::Ty(ty) => write!(f, "{ty:?}"),
1133            GenericArg::Lifetime(region) => write!(f, "{region:?}"),
1134            GenericArg::Const(c) => write!(f, "Const({c:?})"),
1135        }
1136    }
1137}
1138
1139impl fmt::Debug for Region {
1140    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1141        write!(f, "{}", region_to_string(*self))
1142    }
1143}
1144
1145impl<T: fmt::Debug> fmt::Debug for Binder<T> {
1146    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1147        if !self.1.is_empty() {
1148            write!(f, "for<{:?}> ", self.1.iter().format(", "))?;
1149        }
1150        write!(f, "{:?}", self.0)
1151    }
1152}
1153
1154impl fmt::Debug for FnSig {
1155    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1156        write!(f, "fn({:?}) -> {:?}", self.inputs().iter().format(", "), self.output())
1157    }
1158}
1159
1160impl fmt::Debug for Ty {
1161    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1162        match self.kind() {
1163            TyKind::Adt(adt_def, args) => {
1164                let adt_name = rustc_middle::ty::tls::with(|tcx| tcx.def_path_str(adt_def.did()));
1165                write!(f, "{adt_name}")?;
1166                if !args.is_empty() {
1167                    write!(f, "<{:?}>", args.iter().format(", "))?;
1168                }
1169                Ok(())
1170            }
1171            TyKind::FnDef(def_id, args) => {
1172                write!(f, "FnDef({:?}[{:?}])", def_id, args.iter().format(", "))
1173            }
1174            TyKind::Bool => write!(f, "bool"),
1175            TyKind::Str => write!(f, "str"),
1176            TyKind::Char => write!(f, "char"),
1177            TyKind::Float(float_ty) => write!(f, "{}", float_ty.name_str()),
1178            TyKind::Int(int_ty) => write!(f, "{}", int_ty.name_str()),
1179            TyKind::Uint(uint_ty) => write!(f, "{}", uint_ty.name_str()),
1180            TyKind::Never => write!(f, "!"),
1181            TyKind::Param(param_ty) => write!(f, "{param_ty}"),
1182            TyKind::Ref(region, ty, Mutability::Mut) => write!(f, "&{region:?} mut {ty:?}"),
1183            TyKind::Ref(region, ty, Mutability::Not) => write!(f, "&{region:?} {ty:?}"),
1184            TyKind::Array(ty, c) => write!(f, "[{ty:?}; {c:?}]"),
1185            TyKind::Tuple(tys) => {
1186                if let [ty] = &tys[..] {
1187                    write!(f, "({ty:?},)")
1188                } else {
1189                    write!(f, "({:?})", tys.iter().format(", "))
1190                }
1191            }
1192            TyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1193            TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1194            TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1195            TyKind::FnPtr(fn_sig) => write!(f, "{fn_sig:?}"),
1196            TyKind::Closure(did, args) => {
1197                write!(f, "{}", def_id_to_string(*did))?;
1198                if !args.is_empty() {
1199                    write!(f, "<{:?}>", args.iter().format(", "))?;
1200                }
1201                Ok(())
1202            }
1203            TyKind::Coroutine(did, args) => {
1204                write!(f, "{}", def_id_to_string(*did))?;
1205                if !args.is_empty() {
1206                    write!(f, "<{:?}>", args.iter().format(", "))?;
1207                }
1208                Ok(())
1209            }
1210            TyKind::CoroutineWitness(did, args) => {
1211                write!(f, "{}", def_id_to_string(*did))?;
1212                if !args.is_empty() {
1213                    write!(f, "<{:?}>", args.iter().format(", "))?;
1214                }
1215                Ok(())
1216            }
1217            TyKind::Alias(AliasTy { kind: AliasKind::Opaque { def_id }, args }) => {
1218                write!(f, "{}", def_id_to_string(*def_id))?;
1219                if !args.is_empty() {
1220                    write!(f, "<{:?}>", args.iter().format(", "))?;
1221                }
1222                Ok(())
1223            }
1224            TyKind::Alias(AliasTy { kind: AliasKind::Projection { def_id }, args }) => {
1225                write!(f, "Alias (Projection, {}, ", def_id_to_string(*def_id))?;
1226                if !args.is_empty() {
1227                    write!(f, "<{:?}>", args.iter().format(", "))?;
1228                }
1229                write!(f, ")")?;
1230                Ok(())
1231            }
1232            TyKind::Alias(AliasTy { kind: AliasKind::Free { def_id }, args }) => {
1233                write!(f, "Alias (Free, {}, ", def_id_to_string(*def_id))?;
1234                if !args.is_empty() {
1235                    write!(f, "<{:?}>", args.iter().format(", "))?;
1236                }
1237                write!(f, ")")?;
1238                Ok(())
1239            }
1240            TyKind::Dynamic(preds, r) => {
1241                write!(f, "dyn {:?} + {r:?}", preds.iter().format(", "))
1242            }
1243            TyKind::Foreign(def_id) => {
1244                write!(f, "Foreign {def_id:?}")
1245            }
1246            TyKind::Pat => todo!(),
1247        }
1248    }
1249}
1250
1251impl fmt::Debug for ValTree {
1252    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1253        match &self {
1254            ValTree::Leaf(scalar_int) => write!(f, "Leaf({scalar_int})"),
1255            ValTree::Branch(vec) => write!(f, "Branch([{:?}])", vec.iter().format(", ")),
1256        }
1257    }
1258}
1259
1260impl fmt::Debug for Const {
1261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1262        match &self.kind {
1263            ConstKind::Param(p) => write!(f, "{}", p.name.as_str()),
1264            ConstKind::Value(_, v) => write!(f, "{v:?}"),
1265            ConstKind::Infer(infer_const) => write!(f, "{infer_const:?}"),
1266            ConstKind::Alias(uneval_const) => write!(f, "{uneval_const:?}"),
1267        }
1268    }
1269}
1270
1271pub fn region_to_string(region: Region) -> String {
1272    match region {
1273        Region::ReBound(debruijn, region) => {
1274            match region.kind {
1275                BoundRegionKind::Anon => "'<annon>".to_string(),
1276                BoundRegionKind::Named(_) => {
1277                    format!("{debruijn:?}{region:?}")
1278                }
1279                BoundRegionKind::ClosureEnv => "'<env>".to_string(),
1280                BoundRegionKind::NamedForPrinting(sym) => format!("{sym}"),
1281            }
1282        }
1283        Region::ReEarlyParam(region) => region.name.to_string(),
1284        Region::ReStatic => "'static".to_string(),
1285        Region::ReVar(rvid) => format!("{rvid:?}"),
1286        Region::ReLateParam(..) => "'<free>".to_string(),
1287        Region::ReErased => "'_".to_string(),
1288    }
1289}