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