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