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