Skip to main content

flux_rustc_bridge/ty/
mod.rs

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