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