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, RegionExt, 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    Inherent { def_id: DefId },
425    Free { def_id: DefId },
426    Anon { def_id: DefId },
427}
428
429impl AliasConstKind {
430    pub fn to_rustc_kind<'tcx>(self) -> rustc_middle::ty::AliasConstKind<'tcx> {
431        use rustc_middle::ty;
432        match self {
433            AliasConstKind::Projection { def_id } => ty::AliasConstKind::Projection { def_id },
434            AliasConstKind::Inherent { def_id } => ty::AliasConstKind::Inherent { def_id },
435            AliasConstKind::Free { def_id } => ty::AliasConstKind::Free { def_id },
436            AliasConstKind::Anon { def_id } => ty::AliasConstKind::Anon { def_id },
437        }
438    }
439}
440
441#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
442pub enum ValTree {
443    Leaf(ScalarInt),
444    Branch(List<Const>),
445}
446
447#[derive(Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
448pub enum ConstKind {
449    Param(ParamConst),
450    Value(Ty, ValTree),
451    Infer(InferConst),
452    Alias(AliasConst),
453}
454
455#[derive(PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
456pub enum GenericArg {
457    Ty(Ty),
458    Lifetime(Region),
459    Const(Const),
460}
461
462pub type GenericArgs = List<GenericArg>;
463
464#[extension(pub trait GenericArgsExt)]
465impl GenericArgs {
466    fn box_args(&self) -> (&Ty, &Ty) {
467        if let [GenericArg::Ty(deref), GenericArg::Ty(alloc)] = &self[..] {
468            (deref, alloc)
469        } else {
470            bug!("invalid generic arguments for box");
471        }
472    }
473
474    fn as_closure(&self) -> ClosureArgs {
475        ClosureArgs { args: self.clone() }
476    }
477
478    fn as_coroutine(&self) -> CoroutineArgs {
479        CoroutineArgs { args: self.clone() }
480    }
481}
482
483pub struct CoroutineArgs {
484    pub args: GenericArgs,
485}
486
487pub struct ClosureArgs {
488    pub args: GenericArgs,
489}
490
491#[expect(unused, reason = "keeping this in case we use it")]
492pub struct ClosureArgsParts<'a, T> {
493    parent_args: &'a [T],
494    closure_kind_ty: &'a T,
495    closure_sig_as_fn_ptr_ty: &'a T,
496    tupled_upvars_ty: &'a T,
497}
498
499#[derive(Debug)]
500pub struct CoroutineArgsParts<'a> {
501    pub parent_args: &'a [GenericArg],
502    pub kind_ty: &'a Ty,
503    pub resume_ty: &'a Ty,
504    pub yield_ty: &'a Ty,
505    pub return_ty: &'a Ty,
506    pub tupled_upvars_ty: &'a Ty,
507}
508
509/// Mirrors [`rustc_middle::ty::LateParamRegion`].
510#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
511pub struct LateParamRegion {
512    pub scope: DefId,
513    pub kind: LateParamRegionKind,
514}
515
516#[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
517pub enum Region {
518    ReBound(DebruijnIndex, BoundRegion),
519    ReEarlyParam(EarlyParamRegion),
520    ReStatic,
521    ReVar(RegionVid),
522    ReLateParam(LateParamRegion),
523    ReErased,
524}
525
526impl<'tcx> ToRustc<'tcx> for Region {
527    type T = rustc_middle::ty::Region<'tcx>;
528
529    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
530        match *self {
531            Region::ReBound(debruijn, bound_region) => {
532                rustc_middle::ty::Region::new_bound(tcx, debruijn, bound_region.to_rustc(tcx))
533            }
534            Region::ReEarlyParam(epr) => rustc_middle::ty::Region::new_early_param(tcx, epr),
535            Region::ReStatic => tcx.lifetimes.re_static,
536            Region::ReVar(rvid) => rustc_middle::ty::Region::new_var(tcx, rvid),
537            Region::ReLateParam(LateParamRegion { scope, kind }) => {
538                rustc_middle::ty::Region::new_late_param(tcx, scope, kind)
539            }
540            Region::ReErased => tcx.lifetimes.re_erased,
541        }
542    }
543}
544
545#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable)]
546pub struct BoundRegion {
547    pub var: BoundVar,
548    pub kind: BoundRegionKind,
549}
550
551impl<'tcx> ToRustc<'tcx> for BoundRegion {
552    type T = rustc_middle::ty::BoundRegion<'tcx>;
553
554    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
555        rustc_middle::ty::BoundRegion { var: self.var, kind: self.kind.to_rustc(tcx) }
556    }
557}
558
559impl Generics<'_> {
560    pub fn parent(&self) -> Option<DefId> {
561        self.orig.parent
562    }
563
564    pub fn parent_count(&self) -> usize {
565        self.orig.parent_count
566    }
567}
568
569impl Clause {
570    pub(crate) fn new(kind: Binder<ClauseKind>) -> Clause {
571        Clause { kind }
572    }
573}
574
575impl<T> EarlyBinder<T> {
576    pub fn skip_binder(self) -> T {
577        self.0
578    }
579
580    pub fn instantiate_identity(self) -> T {
581        self.0
582    }
583}
584
585impl EarlyBinder<Ty> {
586    pub fn subst(&self, args: &[GenericArg]) -> Ty {
587        self.0.subst(args)
588    }
589}
590
591impl<T> Binder<T> {
592    pub fn dummy(value: T) -> Binder<T> {
593        Binder(value, List::empty())
594    }
595
596    pub fn bind_with_vars(value: T, vars: impl Into<List<BoundVariableKind>>) -> Binder<T> {
597        Binder(value, vars.into())
598    }
599
600    pub fn skip_binder(self) -> T {
601        self.0
602    }
603
604    pub fn skip_binder_ref(&self) -> &T {
605        self.as_ref().skip_binder()
606    }
607
608    pub fn as_ref(&self) -> Binder<&T> {
609        Binder(&self.0, self.1.clone())
610    }
611
612    pub fn vars(&self) -> &List<BoundVariableKind> {
613        &self.1
614    }
615}
616
617impl FnSig {
618    pub fn inputs(&self) -> &[Ty] {
619        &self.inputs_and_output[..self.inputs_and_output.len() - 1]
620    }
621
622    pub fn output(&self) -> &Ty {
623        &self.inputs_and_output[self.inputs_and_output.len() - 1]
624    }
625}
626
627impl GenericArg {
628    pub fn expect_type(&self) -> &Ty {
629        if let GenericArg::Ty(ty) = self {
630            ty
631        } else {
632            bug!("expected `GenericArg::Ty`, found {:?}", self)
633        }
634    }
635
636    fn expect_lifetime(&self) -> Region {
637        if let GenericArg::Lifetime(re) = self {
638            *re
639        } else {
640            bug!("expected `GenericArg::Lifetime`, found {:?}", self)
641        }
642    }
643
644    fn expect_const(&self) -> &Const {
645        if let GenericArg::Const(c) = self {
646            c
647        } else {
648            bug!("expected `GenericArg::Const`, found {:?}", self)
649        }
650    }
651}
652
653impl<'tcx> ToRustc<'tcx> for GenericArgs {
654    type T = rustc_middle::ty::GenericArgsRef<'tcx>;
655
656    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
657        tcx.mk_args_from_iter(self.iter().map(|arg| arg.to_rustc(tcx)))
658    }
659}
660
661impl<'tcx> ToRustc<'tcx> for GenericArg {
662    type T = rustc_middle::ty::GenericArg<'tcx>;
663
664    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
665        use rustc_middle::ty;
666        match self {
667            GenericArg::Ty(ty) => ty::GenericArg::from(ty.to_rustc(tcx)),
668            GenericArg::Lifetime(re) => ty::GenericArg::from(re.to_rustc(tcx)),
669            GenericArg::Const(c) => ty::GenericArg::from(c.to_rustc(tcx)),
670        }
671    }
672}
673
674impl CoroutineArgs {
675    pub fn tupled_upvars_ty(&self) -> &Ty {
676        self.split().tupled_upvars_ty
677    }
678
679    pub fn upvar_tys(&self) -> impl Iterator<Item = &Ty> {
680        self.tupled_upvars_ty().tuple_fields().iter()
681    }
682
683    pub fn resume_ty(&self) -> &Ty {
684        self.split().resume_ty
685    }
686
687    fn split(&self) -> CoroutineArgsParts<'_> {
688        match &self.args[..] {
689            [parent_args @ .., kind_ty, resume_ty, yield_ty, return_ty, tupled_upvars_ty] => {
690                CoroutineArgsParts {
691                    parent_args,
692                    kind_ty: kind_ty.expect_type(),
693                    resume_ty: resume_ty.expect_type(),
694                    yield_ty: yield_ty.expect_type(),
695                    return_ty: return_ty.expect_type(),
696                    tupled_upvars_ty: tupled_upvars_ty.expect_type(),
697                }
698            }
699            _ => bug!("generator args missing synthetics"),
700        }
701    }
702}
703
704impl ClosureArgs {
705    pub fn tupled_upvars_ty(&self) -> &Ty {
706        self.split().tupled_upvars_ty.expect_type()
707    }
708
709    pub fn upvar_tys(&self) -> &List<Ty> {
710        self.tupled_upvars_ty().tuple_fields()
711    }
712
713    pub fn split(&self) -> ClosureArgsParts<'_, GenericArg> {
714        match &self.args[..] {
715            [parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
716                ClosureArgsParts {
717                    parent_args,
718                    closure_kind_ty,
719                    closure_sig_as_fn_ptr_ty,
720                    tupled_upvars_ty,
721                }
722            }
723            _ => bug!("closure args missing synthetics"),
724        }
725    }
726
727    pub fn sig_as_fn_ptr_ty(&self) -> &Ty {
728        self.split().closure_sig_as_fn_ptr_ty.expect_type()
729    }
730
731    pub fn kind_ty(&self) -> &Ty {
732        self.split().closure_kind_ty.expect_type()
733    }
734}
735
736impl AdtDef {
737    pub(crate) fn new(data: AdtDefData) -> Self {
738        Self(Interned::new(data))
739    }
740
741    pub fn did(&self) -> DefId {
742        self.0.did
743    }
744
745    pub fn flags(&self) -> AdtFlags {
746        self.0.flags
747    }
748
749    pub fn is_struct(&self) -> bool {
750        self.flags().contains(AdtFlags::IS_STRUCT)
751    }
752
753    pub fn is_union(&self) -> bool {
754        self.flags().contains(AdtFlags::IS_UNION)
755    }
756
757    pub fn is_enum(&self) -> bool {
758        self.flags().contains(AdtFlags::IS_ENUM)
759    }
760
761    pub fn is_box(&self) -> bool {
762        self.flags().contains(AdtFlags::IS_BOX)
763    }
764
765    pub fn variant(&self, idx: VariantIdx) -> &VariantDef {
766        &self.0.variants[idx]
767    }
768
769    pub fn variants(&self) -> &IndexSlice<VariantIdx, VariantDef> {
770        &self.0.variants
771    }
772
773    pub fn discriminants(&self) -> impl Iterator<Item = (VariantIdx, u128)> + '_ {
774        self.0
775            .discrs
776            .iter_enumerated()
777            .map(|(idx, discr)| (idx, *discr))
778    }
779
780    pub fn non_enum_variant(&self) -> &VariantDef {
781        assert!(self.is_struct() || self.is_union());
782        self.variant(FIRST_VARIANT)
783    }
784}
785
786impl<'tcx> ToRustc<'tcx> for AdtDef {
787    type T = rustc_middle::ty::AdtDef<'tcx>;
788
789    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
790        tcx.adt_def(self.did())
791    }
792}
793
794impl AdtDefData {
795    pub(crate) fn new<'tcx>(
796        tcx: TyCtxt<'tcx>,
797        adt_def: rustc_middle::ty::AdtDef<'tcx>,
798        variants: IndexVec<VariantIdx, VariantDef>,
799    ) -> Self {
800        let discrs: IndexVec<VariantIdx, u128> = if adt_def.is_enum() {
801            adt_def
802                .discriminants(tcx)
803                .map(|(_, discr)| discr.val)
804                .collect()
805        } else {
806            IndexVec::from_raw(vec![0])
807        };
808        tracked_span_assert_eq!(discrs.len(), variants.len());
809        Self { did: adt_def.did(), variants, flags: adt_def.flags(), discrs }
810    }
811}
812
813impl AliasTy {
814    /// This method work only with associated type projections (i.e., no opaque tpes)
815    pub fn self_ty(&self) -> &Ty {
816        self.args[0].expect_type()
817    }
818}
819
820impl TyKind {
821    fn intern(self) -> Ty {
822        Ty(Interned::new(TyS { kind: self }))
823    }
824}
825
826impl Ty {
827    pub fn mk_adt(adt_def: AdtDef, args: impl Into<GenericArgs>) -> Ty {
828        let args = args.into();
829        TyKind::Adt(adt_def, args).intern()
830    }
831
832    pub fn mk_closure(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
833        TyKind::Closure(def_id, args.into()).intern()
834    }
835
836    pub fn mk_fn_def(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
837        TyKind::FnDef(def_id, args.into()).intern()
838    }
839
840    pub fn mk_coroutine(def_id: DefId, args: impl Into<GenericArgs>) -> Ty {
841        TyKind::Coroutine(def_id, args.into()).intern()
842    }
843
844    pub fn mk_generator_witness(def_id: DefId, args: GenericArgs) -> Ty {
845        TyKind::CoroutineWitness(def_id, args).intern()
846    }
847
848    pub fn mk_alias(kind: AliasKind, args: impl Into<GenericArgs>) -> Ty {
849        TyKind::Alias(AliasTy { kind, args: args.into() }).intern()
850    }
851
852    pub fn mk_array(ty: Ty, c: Const) -> Ty {
853        TyKind::Array(ty, c).intern()
854    }
855
856    pub fn mk_slice(ty: Ty) -> Ty {
857        TyKind::Slice(ty).intern()
858    }
859
860    pub fn mk_fn_ptr(fn_sig: PolyFnSig) -> Ty {
861        TyKind::FnPtr(fn_sig).intern()
862    }
863
864    pub fn mk_raw_ptr(ty: Ty, mutbl: Mutability) -> Ty {
865        TyKind::RawPtr(ty, mutbl).intern()
866    }
867
868    pub fn mk_bool() -> Ty {
869        TyKind::Bool.intern()
870    }
871
872    pub fn mk_float(float_ty: FloatTy) -> Ty {
873        TyKind::Float(float_ty).intern()
874    }
875
876    pub fn mk_int(int_ty: IntTy) -> Ty {
877        TyKind::Int(int_ty).intern()
878    }
879
880    pub fn mk_never() -> Ty {
881        TyKind::Never.intern()
882    }
883
884    pub fn mk_param(param: ParamTy) -> Ty {
885        TyKind::Param(param).intern()
886    }
887
888    pub fn mk_dynamic(exi_preds: impl Into<List<Binder<ExistentialPredicate>>>, r: Region) -> Ty {
889        TyKind::Dynamic(exi_preds.into(), r).intern()
890    }
891
892    pub fn mk_ref(region: Region, ty: Ty, mutability: Mutability) -> Ty {
893        TyKind::Ref(region, ty, mutability).intern()
894    }
895
896    pub fn mk_tuple(tys: impl Into<List<Ty>>) -> Ty {
897        TyKind::Tuple(tys.into()).intern()
898    }
899
900    pub fn mk_uint(uint_ty: UintTy) -> Ty {
901        TyKind::Uint(uint_ty).intern()
902    }
903
904    pub fn mk_str() -> Ty {
905        TyKind::Str.intern()
906    }
907
908    pub fn mk_char() -> Ty {
909        TyKind::Char.intern()
910    }
911
912    pub fn mk_foreign(def_id: DefId) -> Ty {
913        TyKind::Foreign(def_id).intern()
914    }
915
916    pub fn mk_pat() -> Ty {
917        TyKind::Pat.intern()
918    }
919
920    pub fn deref(&self) -> Ty {
921        match self.kind() {
922            TyKind::Adt(adt_def, args) if adt_def.is_box() => args[0].expect_type().clone(),
923            TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => ty.clone(),
924            _ => tracked_span_bug!("deref projection of non-dereferenceable ty `{self:?}`"),
925        }
926    }
927
928    pub fn kind(&self) -> &TyKind {
929        &self.0.kind
930    }
931
932    pub fn tuple_fields(&self) -> &List<Ty> {
933        match self.kind() {
934            TyKind::Tuple(tys) => tys,
935            _ => bug!("tuple_fields called on non-tuple"),
936        }
937    }
938
939    pub fn expect_adt(&self) -> (&AdtDef, &GenericArgs) {
940        match self.kind() {
941            TyKind::Adt(adt_def, args) => (adt_def, args),
942            _ => bug!("expect_adt called on non-adt"),
943        }
944    }
945
946    pub fn is_mut_ref(&self) -> bool {
947        matches!(self.kind(), TyKind::Ref(.., Mutability::Mut))
948    }
949
950    pub fn is_box(&self) -> bool {
951        matches!(self.kind(), TyKind::Adt(adt, ..) if adt.is_box())
952    }
953}
954
955impl<'tcx, V> ToRustc<'tcx> for Binder<V>
956where
957    V: ToRustc<'tcx, T: rustc_middle::ty::TypeVisitable<TyCtxt<'tcx>>>,
958{
959    type T = rustc_middle::ty::Binder<'tcx, V::T>;
960
961    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
962        let vars = BoundVariableKind::to_rustc(self.vars(), tcx);
963        let value = self.skip_binder_ref().to_rustc(tcx);
964        rustc_middle::ty::Binder::bind_with_vars(value, vars)
965    }
966}
967
968impl<'tcx> ToRustc<'tcx> for FnSig {
969    type T = rustc_middle::ty::FnSig<'tcx>;
970
971    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
972        tcx.mk_fn_sig(
973            self.inputs().iter().map(|ty| ty.to_rustc(tcx)),
974            self.output().to_rustc(tcx),
975            rustc_middle::ty::FnSigKind::default()
976                .set_abi(self.abi)
977                .set_safety(self.safety)
978                .set_c_variadic(false),
979        )
980    }
981}
982
983impl<'tcx> ToRustc<'tcx> for AliasTy {
984    type T = rustc_middle::ty::AliasTy<'tcx>;
985
986    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
987        rustc_middle::ty::AliasTy::new_from_args(
988            tcx,
989            self.kind.to_rustc_kind(),
990            self.args.to_rustc(tcx),
991        )
992    }
993}
994
995impl<'tcx> ToRustc<'tcx> for ExistentialPredicate {
996    type T = rustc_middle::ty::ExistentialPredicate<'tcx>;
997
998    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> Self::T {
999        match self {
1000            ExistentialPredicate::Trait(trait_ref) => {
1001                let trait_ref = rustc_middle::ty::ExistentialTraitRef::new_from_args(
1002                    tcx,
1003                    trait_ref.def_id,
1004                    trait_ref.args.to_rustc(tcx),
1005                );
1006                rustc_middle::ty::ExistentialPredicate::Trait(trait_ref)
1007            }
1008            ExistentialPredicate::Projection(projection) => {
1009                rustc_middle::ty::ExistentialPredicate::Projection(
1010                    rustc_middle::ty::ExistentialProjection::new_from_args(
1011                        tcx,
1012                        projection.def_id,
1013                        projection.args.to_rustc(tcx),
1014                        projection.term.to_rustc(tcx).into(),
1015                    ),
1016                )
1017            }
1018            ExistentialPredicate::AutoTrait(def_id) => {
1019                rustc_middle::ty::ExistentialPredicate::AutoTrait(*def_id)
1020            }
1021        }
1022    }
1023}
1024
1025impl<'tcx> ToRustc<'tcx> for Ty {
1026    type T = rustc_middle::ty::Ty<'tcx>;
1027
1028    fn to_rustc(&self, tcx: TyCtxt<'tcx>) -> rustc_middle::ty::Ty<'tcx> {
1029        match self.kind() {
1030            TyKind::Bool => tcx.types.bool,
1031            TyKind::Str => tcx.types.str_,
1032            TyKind::Char => tcx.types.char,
1033            TyKind::Never => tcx.types.never,
1034            TyKind::Foreign(def_id) => rustc_ty::Ty::new_foreign(tcx, *def_id),
1035            TyKind::Float(float_ty) => rustc_ty::Ty::new_float(tcx, *float_ty),
1036            TyKind::Int(int_ty) => rustc_ty::Ty::new_int(tcx, *int_ty),
1037            TyKind::Uint(uint_ty) => rustc_ty::Ty::new_uint(tcx, *uint_ty),
1038            TyKind::Adt(adt_def, args) => {
1039                let adt_def = adt_def.to_rustc(tcx);
1040                let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1041                rustc_ty::Ty::new_adt(tcx, adt_def, args)
1042            }
1043            TyKind::FnDef(def_id, args) => {
1044                let args = tcx.mk_args_from_iter(args.iter().map(|arg| arg.to_rustc(tcx)));
1045                tcx.type_of(*def_id).instantiate(tcx, args).skip_norm_wip()
1046            }
1047            TyKind::Array(ty, len) => {
1048                let ty = ty.to_rustc(tcx);
1049                let len = len.to_rustc(tcx);
1050                rustc_ty::Ty::new_array_with_const_len(tcx, ty, len)
1051            }
1052            TyKind::Param(pty) => rustc_ty::Ty::new_param(tcx, pty.index, pty.name),
1053            TyKind::Ref(re, ty, mutbl) => {
1054                rustc_ty::Ty::new_ref(tcx, re.to_rustc(tcx), ty.to_rustc(tcx), *mutbl)
1055            }
1056            TyKind::Tuple(tys) => {
1057                let ts = tys.iter().map(|ty| ty.to_rustc(tcx)).collect_vec();
1058                rustc_ty::Ty::new_tup(tcx, tcx.mk_type_list(&ts))
1059            }
1060            TyKind::Slice(ty) => rustc_ty::Ty::new_slice(tcx, ty.to_rustc(tcx)),
1061            TyKind::RawPtr(ty, mutbl) => rustc_ty::Ty::new_ptr(tcx, ty.to_rustc(tcx), *mutbl),
1062            TyKind::Closure(did, args) => rustc_ty::Ty::new_closure(tcx, *did, args.to_rustc(tcx)),
1063            TyKind::FnPtr(poly_sig) => rustc_ty::Ty::new_fn_ptr(tcx, poly_sig.to_rustc(tcx)),
1064            TyKind::Alias(alias_ty) => {
1065                rustc_ty::Ty::new_alias(tcx, rustc_ty::IsRigid::No, alias_ty.to_rustc(tcx))
1066            }
1067            TyKind::Dynamic(exi_preds, re) => {
1068                let preds = exi_preds
1069                    .iter()
1070                    .map(|pred| pred.to_rustc(tcx))
1071                    .collect_vec();
1072
1073                let preds = tcx.mk_poly_existential_predicates(&preds);
1074                rustc_ty::Ty::new_dynamic(tcx, preds, re.to_rustc(tcx))
1075            }
1076            TyKind::Pat => todo!(),
1077            TyKind::Coroutine(_, _) | TyKind::CoroutineWitness(_, _) => {
1078                bug!("TODO: to_rustc for `{self:?}`")
1079            }
1080        }
1081    }
1082}
1083
1084impl_internable!(TyS, AdtDefData);
1085impl_slice_internable!(
1086    Ty,
1087    GenericArg,
1088    GenericParamDef,
1089    BoundVariableKind,
1090    Clause,
1091    Const,
1092    Binder<ExistentialPredicate>,
1093);
1094
1095impl fmt::Debug for ExistentialPredicate {
1096    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1097        match self {
1098            ExistentialPredicate::Trait(trait_ref) => write!(f, "{trait_ref:?}"),
1099            ExistentialPredicate::Projection(proj) => write!(f, "({proj:?})"),
1100            ExistentialPredicate::AutoTrait(def_id) => {
1101                write!(f, "{}", def_id_to_string(*def_id))
1102            }
1103        }
1104    }
1105}
1106
1107impl fmt::Debug for ExistentialTraitRef {
1108    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1109        write!(f, "{}", def_id_to_string(self.def_id))?;
1110        if !self.args.is_empty() {
1111            write!(f, "<{:?}>", self.args.iter().format(","))?;
1112        }
1113        Ok(())
1114    }
1115}
1116
1117impl fmt::Debug for ExistentialProjection {
1118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1119        write!(f, "{}", def_id_to_string(self.def_id))?;
1120        if !self.args.is_empty() {
1121            write!(f, "<{:?}>", self.args.iter().format(","))?;
1122        }
1123        write!(f, " = {:?}", &self.term)
1124    }
1125}
1126
1127impl fmt::Debug for GenericArg {
1128    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1129        match self {
1130            GenericArg::Ty(ty) => write!(f, "{ty:?}"),
1131            GenericArg::Lifetime(region) => write!(f, "{region:?}"),
1132            GenericArg::Const(c) => write!(f, "Const({c:?})"),
1133        }
1134    }
1135}
1136
1137impl fmt::Debug for Region {
1138    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1139        write!(f, "{}", region_to_string(*self))
1140    }
1141}
1142
1143impl<T: fmt::Debug> fmt::Debug for Binder<T> {
1144    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1145        if !self.1.is_empty() {
1146            write!(f, "for<{:?}> ", self.1.iter().format(", "))?;
1147        }
1148        write!(f, "{:?}", self.0)
1149    }
1150}
1151
1152impl fmt::Debug for FnSig {
1153    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1154        write!(f, "fn({:?}) -> {:?}", self.inputs().iter().format(", "), self.output())
1155    }
1156}
1157
1158impl fmt::Debug for Ty {
1159    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1160        match self.kind() {
1161            TyKind::Adt(adt_def, args) => {
1162                let adt_name = rustc_middle::ty::tls::with(|tcx| tcx.def_path_str(adt_def.did()));
1163                write!(f, "{adt_name}")?;
1164                if !args.is_empty() {
1165                    write!(f, "<{:?}>", args.iter().format(", "))?;
1166                }
1167                Ok(())
1168            }
1169            TyKind::FnDef(def_id, args) => {
1170                write!(f, "FnDef({:?}[{:?}])", def_id, args.iter().format(", "))
1171            }
1172            TyKind::Bool => write!(f, "bool"),
1173            TyKind::Str => write!(f, "str"),
1174            TyKind::Char => write!(f, "char"),
1175            TyKind::Float(float_ty) => write!(f, "{}", float_ty.name_str()),
1176            TyKind::Int(int_ty) => write!(f, "{}", int_ty.name_str()),
1177            TyKind::Uint(uint_ty) => write!(f, "{}", uint_ty.name_str()),
1178            TyKind::Never => write!(f, "!"),
1179            TyKind::Param(param_ty) => write!(f, "{param_ty}"),
1180            TyKind::Ref(region, ty, Mutability::Mut) => write!(f, "&{region:?} mut {ty:?}"),
1181            TyKind::Ref(region, ty, Mutability::Not) => write!(f, "&{region:?} {ty:?}"),
1182            TyKind::Array(ty, c) => write!(f, "[{ty:?}; {c:?}]"),
1183            TyKind::Tuple(tys) => {
1184                if let [ty] = &tys[..] {
1185                    write!(f, "({ty:?},)")
1186                } else {
1187                    write!(f, "({:?})", tys.iter().format(", "))
1188                }
1189            }
1190            TyKind::Slice(ty) => write!(f, "[{ty:?}]"),
1191            TyKind::RawPtr(ty, Mutability::Mut) => write!(f, "*mut {ty:?}"),
1192            TyKind::RawPtr(ty, Mutability::Not) => write!(f, "*const {ty:?}"),
1193            TyKind::FnPtr(fn_sig) => write!(f, "{fn_sig:?}"),
1194            TyKind::Closure(did, args) => {
1195                write!(f, "{}", def_id_to_string(*did))?;
1196                if !args.is_empty() {
1197                    write!(f, "<{:?}>", args.iter().format(", "))?;
1198                }
1199                Ok(())
1200            }
1201            TyKind::Coroutine(did, args) => {
1202                write!(f, "{}", def_id_to_string(*did))?;
1203                if !args.is_empty() {
1204                    write!(f, "<{:?}>", args.iter().format(", "))?;
1205                }
1206                Ok(())
1207            }
1208            TyKind::CoroutineWitness(did, args) => {
1209                write!(f, "{}", def_id_to_string(*did))?;
1210                if !args.is_empty() {
1211                    write!(f, "<{:?}>", args.iter().format(", "))?;
1212                }
1213                Ok(())
1214            }
1215            TyKind::Alias(AliasTy { kind: AliasKind::Opaque { def_id }, args }) => {
1216                write!(f, "{}", def_id_to_string(*def_id))?;
1217                if !args.is_empty() {
1218                    write!(f, "<{:?}>", args.iter().format(", "))?;
1219                }
1220                Ok(())
1221            }
1222            TyKind::Alias(AliasTy { kind: AliasKind::Projection { def_id }, args }) => {
1223                write!(f, "Alias (Projection, {}, ", def_id_to_string(*def_id))?;
1224                if !args.is_empty() {
1225                    write!(f, "<{:?}>", args.iter().format(", "))?;
1226                }
1227                write!(f, ")")?;
1228                Ok(())
1229            }
1230            TyKind::Alias(AliasTy { kind: AliasKind::Free { def_id }, args }) => {
1231                write!(f, "Alias (Free, {}, ", def_id_to_string(*def_id))?;
1232                if !args.is_empty() {
1233                    write!(f, "<{:?}>", args.iter().format(", "))?;
1234                }
1235                write!(f, ")")?;
1236                Ok(())
1237            }
1238            TyKind::Dynamic(preds, r) => {
1239                write!(f, "dyn {:?} + {r:?}", preds.iter().format(", "))
1240            }
1241            TyKind::Foreign(def_id) => {
1242                write!(f, "Foreign {def_id:?}")
1243            }
1244            TyKind::Pat => todo!(),
1245        }
1246    }
1247}
1248
1249impl fmt::Debug for ValTree {
1250    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1251        match &self {
1252            ValTree::Leaf(scalar_int) => write!(f, "Leaf({scalar_int})"),
1253            ValTree::Branch(vec) => write!(f, "Branch([{:?}])", vec.iter().format(", ")),
1254        }
1255    }
1256}
1257
1258impl fmt::Debug for Const {
1259    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1260        match &self.kind {
1261            ConstKind::Param(p) => write!(f, "{}", p.name.as_str()),
1262            ConstKind::Value(_, v) => write!(f, "{v:?}"),
1263            ConstKind::Infer(infer_const) => write!(f, "{infer_const:?}"),
1264            ConstKind::Alias(uneval_const) => write!(f, "{uneval_const:?}"),
1265        }
1266    }
1267}
1268
1269pub fn region_to_string(region: Region) -> String {
1270    match region {
1271        Region::ReBound(debruijn, region) => {
1272            match region.kind {
1273                BoundRegionKind::Anon => "'<annon>".to_string(),
1274                BoundRegionKind::Named(_) => {
1275                    format!("{debruijn:?}{region:?}")
1276                }
1277                BoundRegionKind::ClosureEnv => "'<env>".to_string(),
1278                BoundRegionKind::NamedForPrinting(sym) => format!("{sym}"),
1279            }
1280        }
1281        Region::ReEarlyParam(region) => region.name.to_string(),
1282        Region::ReStatic => "'static".to_string(),
1283        Region::ReVar(rvid) => format!("{rvid:?}"),
1284        Region::ReLateParam(..) => "'<free>".to_string(),
1285        Region::ReErased => "'_".to_string(),
1286    }
1287}