1use std::fmt::{self, Debug, Display, Formatter};
2use std::ops::Range;
3
4use serde::Serialize;
5use stable_mir::abi::{FnAbi, Layout};
6use stable_mir::crate_def::{CrateDef, CrateDefItems, CrateDefType};
7use stable_mir::mir::alloc::{AllocId, read_target_int, read_target_uint};
8use stable_mir::mir::mono::StaticDef;
9use stable_mir::target::MachineInfo;
10use stable_mir::{Filename, Opaque};
11
12use super::abi::ReprOptions;
13use super::mir::{Body, Mutability, Safety};
14use super::{DefId, Error, Symbol, with};
15use crate::stable_mir;
16
17#[derive(Copy, Clone, Eq, PartialEq, Hash, Serialize)]
18pub struct Ty(usize);
19
20impl Debug for Ty {
21 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
22 f.debug_struct("Ty").field("id", &self.0).field("kind", &self.kind()).finish()
23 }
24}
25
26impl Ty {
28 pub fn from_rigid_kind(kind: RigidTy) -> Ty {
30 with(|cx| cx.new_rigid_ty(kind))
31 }
32
33 pub fn try_new_array(elem_ty: Ty, size: u64) -> Result<Ty, Error> {
35 Ok(Ty::from_rigid_kind(RigidTy::Array(elem_ty, TyConst::try_from_target_usize(size)?)))
36 }
37
38 pub fn new_array_with_const_len(elem_ty: Ty, len: TyConst) -> Ty {
40 Ty::from_rigid_kind(RigidTy::Array(elem_ty, len))
41 }
42
43 pub fn new_ptr(pointee_ty: Ty, mutability: Mutability) -> Ty {
45 Ty::from_rigid_kind(RigidTy::RawPtr(pointee_ty, mutability))
46 }
47
48 pub fn new_ref(reg: Region, pointee_ty: Ty, mutability: Mutability) -> Ty {
50 Ty::from_rigid_kind(RigidTy::Ref(reg, pointee_ty, mutability))
51 }
52
53 pub fn new_tuple(tys: &[Ty]) -> Ty {
55 Ty::from_rigid_kind(RigidTy::Tuple(Vec::from(tys)))
56 }
57
58 pub fn new_closure(def: ClosureDef, args: GenericArgs) -> Ty {
60 Ty::from_rigid_kind(RigidTy::Closure(def, args))
61 }
62
63 pub fn new_coroutine(def: CoroutineDef, args: GenericArgs, mov: Movability) -> Ty {
65 Ty::from_rigid_kind(RigidTy::Coroutine(def, args, mov))
66 }
67
68 pub fn new_coroutine_closure(def: CoroutineClosureDef, args: GenericArgs) -> Ty {
70 Ty::from_rigid_kind(RigidTy::CoroutineClosure(def, args))
71 }
72
73 pub fn new_box(inner_ty: Ty) -> Ty {
75 with(|cx| cx.new_box_ty(inner_ty))
76 }
77
78 pub fn usize_ty() -> Ty {
80 Ty::from_rigid_kind(RigidTy::Uint(UintTy::Usize))
81 }
82
83 pub fn bool_ty() -> Ty {
85 Ty::from_rigid_kind(RigidTy::Bool)
86 }
87
88 pub fn signed_ty(inner: IntTy) -> Ty {
90 Ty::from_rigid_kind(RigidTy::Int(inner))
91 }
92
93 pub fn unsigned_ty(inner: UintTy) -> Ty {
95 Ty::from_rigid_kind(RigidTy::Uint(inner))
96 }
97
98 pub fn layout(self) -> Result<Layout, Error> {
100 with(|cx| cx.ty_layout(self))
101 }
102}
103
104impl Ty {
105 pub fn kind(&self) -> TyKind {
106 with(|context| context.ty_kind(*self))
107 }
108}
109
110#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
112pub enum Pattern {
113 Range { start: Option<TyConst>, end: Option<TyConst>, include_end: bool },
114}
115
116#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
118pub struct TyConst {
119 pub(crate) kind: TyConstKind,
120 pub id: TyConstId,
121}
122
123impl TyConst {
124 pub fn new(kind: TyConstKind, id: TyConstId) -> TyConst {
125 Self { kind, id }
126 }
127
128 pub fn kind(&self) -> &TyConstKind {
130 &self.kind
131 }
132
133 pub fn try_from_target_usize(val: u64) -> Result<Self, Error> {
135 with(|cx| cx.try_new_ty_const_uint(val.into(), UintTy::Usize))
136 }
137
138 pub fn eval_target_usize(&self) -> Result<u64, Error> {
140 with(|cx| cx.eval_target_usize_ty(self))
141 }
142}
143
144#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
145pub enum TyConstKind {
146 Param(ParamConst),
147 Bound(DebruijnIndex, BoundVar),
148 Unevaluated(ConstDef, GenericArgs),
149
150 Value(Ty, Allocation),
152 ZSTValue(Ty),
153}
154
155#[derive(Copy, Clone, Debug, Eq, PartialEq, Serialize)]
156pub struct TyConstId(usize);
157
158#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
160pub struct MirConst {
161 pub(crate) kind: ConstantKind,
163 pub(crate) ty: Ty,
165 pub id: MirConstId,
167}
168
169impl MirConst {
170 pub fn new(kind: ConstantKind, ty: Ty, id: MirConstId) -> MirConst {
172 MirConst { kind, ty, id }
173 }
174
175 pub fn kind(&self) -> &ConstantKind {
177 &self.kind
178 }
179
180 pub fn ty(&self) -> Ty {
182 self.ty
183 }
184
185 pub fn eval_target_usize(&self) -> Result<u64, Error> {
187 with(|cx| cx.eval_target_usize(self))
188 }
189
190 pub fn try_new_zero_sized(ty: Ty) -> Result<MirConst, Error> {
193 with(|cx| cx.try_new_const_zst(ty))
194 }
195
196 pub fn from_str(value: &str) -> MirConst {
202 with(|cx| cx.new_const_str(value))
203 }
204
205 pub fn from_bool(value: bool) -> MirConst {
207 with(|cx| cx.new_const_bool(value))
208 }
209
210 pub fn try_from_uint(value: u128, uint_ty: UintTy) -> Result<MirConst, Error> {
212 with(|cx| cx.try_new_const_uint(value, uint_ty))
213 }
214}
215
216#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
217pub struct MirConstId(usize);
218
219type Ident = Opaque;
220
221#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
222pub struct Region {
223 pub kind: RegionKind,
224}
225
226#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
227pub enum RegionKind {
228 ReEarlyParam(EarlyParamRegion),
229 ReBound(DebruijnIndex, BoundRegion),
230 ReStatic,
231 RePlaceholder(Placeholder<BoundRegion>),
232 ReErased,
233}
234
235pub(crate) type DebruijnIndex = u32;
236
237#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
238pub struct EarlyParamRegion {
239 pub index: u32,
240 pub name: Symbol,
241}
242
243pub(crate) type BoundVar = u32;
244
245#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
246pub struct BoundRegion {
247 pub var: BoundVar,
248 pub kind: BoundRegionKind,
249}
250
251pub(crate) type UniverseIndex = u32;
252
253#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
254pub struct Placeholder<T> {
255 pub universe: UniverseIndex,
256 pub bound: T,
257}
258
259#[derive(Clone, Copy, PartialEq, Eq, Serialize)]
260pub struct Span(usize);
261
262impl Debug for Span {
263 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
264 f.debug_struct("Span")
265 .field("id", &self.0)
266 .field("repr", &with(|cx| cx.span_to_string(*self)))
267 .finish()
268 }
269}
270
271impl Span {
272 pub fn get_filename(&self) -> Filename {
274 with(|c| c.get_filename(self))
275 }
276
277 pub fn get_lines(&self) -> LineInfo {
279 with(|c| c.get_lines(self))
280 }
281
282 pub fn diagnostic(&self) -> String {
287 with(|c| c.span_to_string(*self))
288 }
289}
290
291#[derive(Clone, Copy, Debug, Serialize)]
292pub struct LineInfo {
295 pub start_line: usize,
296 pub start_col: usize,
297 pub end_line: usize,
298 pub end_col: usize,
299}
300
301#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
302pub enum TyKind {
303 RigidTy(RigidTy),
304 Alias(AliasKind, AliasTy),
305 Param(ParamTy),
306 Bound(usize, BoundTy),
307}
308
309impl TyKind {
310 pub fn rigid(&self) -> Option<&RigidTy> {
311 if let TyKind::RigidTy(inner) = self { Some(inner) } else { None }
312 }
313
314 #[inline]
315 pub fn is_unit(&self) -> bool {
316 matches!(self, TyKind::RigidTy(RigidTy::Tuple(data)) if data.is_empty())
317 }
318
319 #[inline]
320 pub fn is_bool(&self) -> bool {
321 matches!(self, TyKind::RigidTy(RigidTy::Bool))
322 }
323
324 #[inline]
325 pub fn is_char(&self) -> bool {
326 matches!(self, TyKind::RigidTy(RigidTy::Char))
327 }
328
329 #[inline]
330 pub fn is_trait(&self) -> bool {
331 matches!(self, TyKind::RigidTy(RigidTy::Dynamic(_, _, DynKind::Dyn)))
332 }
333
334 #[inline]
335 pub fn is_enum(&self) -> bool {
336 matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Enum)
337 }
338
339 #[inline]
340 pub fn is_struct(&self) -> bool {
341 matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Struct)
342 }
343
344 #[inline]
345 pub fn is_union(&self) -> bool {
346 matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.kind() == AdtKind::Union)
347 }
348
349 #[inline]
350 pub fn is_adt(&self) -> bool {
351 matches!(self, TyKind::RigidTy(RigidTy::Adt(..)))
352 }
353
354 #[inline]
355 pub fn is_ref(&self) -> bool {
356 matches!(self, TyKind::RigidTy(RigidTy::Ref(..)))
357 }
358
359 #[inline]
360 pub fn is_fn(&self) -> bool {
361 matches!(self, TyKind::RigidTy(RigidTy::FnDef(..)))
362 }
363
364 #[inline]
365 pub fn is_fn_ptr(&self) -> bool {
366 matches!(self, TyKind::RigidTy(RigidTy::FnPtr(..)))
367 }
368
369 #[inline]
370 pub fn is_primitive(&self) -> bool {
371 matches!(
372 self,
373 TyKind::RigidTy(
374 RigidTy::Bool
375 | RigidTy::Char
376 | RigidTy::Int(_)
377 | RigidTy::Uint(_)
378 | RigidTy::Float(_)
379 )
380 )
381 }
382
383 #[inline]
384 pub fn is_float(&self) -> bool {
385 matches!(self, TyKind::RigidTy(RigidTy::Float(_)))
386 }
387
388 #[inline]
389 pub fn is_integral(&self) -> bool {
390 matches!(self, TyKind::RigidTy(RigidTy::Int(_) | RigidTy::Uint(_)))
391 }
392
393 #[inline]
394 pub fn is_numeric(&self) -> bool {
395 self.is_integral() || self.is_float()
396 }
397
398 #[inline]
399 pub fn is_signed(&self) -> bool {
400 matches!(self, TyKind::RigidTy(RigidTy::Int(_)))
401 }
402
403 #[inline]
404 pub fn is_str(&self) -> bool {
405 *self == TyKind::RigidTy(RigidTy::Str)
406 }
407
408 #[inline]
409 pub fn is_cstr(&self) -> bool {
410 let TyKind::RigidTy(RigidTy::Adt(def, _)) = self else {
411 return false;
412 };
413 with(|cx| cx.adt_is_cstr(*def))
414 }
415
416 #[inline]
417 pub fn is_slice(&self) -> bool {
418 matches!(self, TyKind::RigidTy(RigidTy::Slice(_)))
419 }
420
421 #[inline]
422 pub fn is_array(&self) -> bool {
423 matches!(self, TyKind::RigidTy(RigidTy::Array(..)))
424 }
425
426 #[inline]
427 pub fn is_mutable_ptr(&self) -> bool {
428 matches!(
429 self,
430 TyKind::RigidTy(RigidTy::RawPtr(_, Mutability::Mut))
431 | TyKind::RigidTy(RigidTy::Ref(_, _, Mutability::Mut))
432 )
433 }
434
435 #[inline]
436 pub fn is_raw_ptr(&self) -> bool {
437 matches!(self, TyKind::RigidTy(RigidTy::RawPtr(..)))
438 }
439
440 #[inline]
442 pub fn is_any_ptr(&self) -> bool {
443 self.is_ref() || self.is_raw_ptr() || self.is_fn_ptr()
444 }
445
446 #[inline]
447 pub fn is_coroutine(&self) -> bool {
448 matches!(self, TyKind::RigidTy(RigidTy::Coroutine(..)))
449 }
450
451 #[inline]
452 pub fn is_closure(&self) -> bool {
453 matches!(self, TyKind::RigidTy(RigidTy::Closure(..)))
454 }
455
456 #[inline]
457 pub fn is_box(&self) -> bool {
458 match self {
459 TyKind::RigidTy(RigidTy::Adt(def, _)) => def.is_box(),
460 _ => false,
461 }
462 }
463
464 #[inline]
465 pub fn is_simd(&self) -> bool {
466 matches!(self, TyKind::RigidTy(RigidTy::Adt(def, _)) if def.is_simd())
467 }
468
469 pub fn trait_principal(&self) -> Option<Binder<ExistentialTraitRef>> {
470 if let TyKind::RigidTy(RigidTy::Dynamic(predicates, _, _)) = self {
471 if let Some(Binder { value: ExistentialPredicate::Trait(trait_ref), bound_vars }) =
472 predicates.first()
473 {
474 Some(Binder { value: trait_ref.clone(), bound_vars: bound_vars.clone() })
475 } else {
476 None
477 }
478 } else {
479 None
480 }
481 }
482
483 pub fn builtin_index(&self) -> Option<Ty> {
485 match self.rigid()? {
486 RigidTy::Array(ty, _) | RigidTy::Slice(ty) => Some(*ty),
487 _ => None,
488 }
489 }
490
491 pub fn builtin_deref(&self, explicit: bool) -> Option<TypeAndMut> {
496 match self.rigid()? {
497 RigidTy::Adt(def, args) if def.is_box() => {
498 Some(TypeAndMut { ty: *args.0.first()?.ty()?, mutability: Mutability::Not })
499 }
500 RigidTy::Ref(_, ty, mutability) => {
501 Some(TypeAndMut { ty: *ty, mutability: *mutability })
502 }
503 RigidTy::RawPtr(ty, mutability) if explicit => {
504 Some(TypeAndMut { ty: *ty, mutability: *mutability })
505 }
506 _ => None,
507 }
508 }
509
510 pub fn fn_sig(&self) -> Option<PolyFnSig> {
512 match self {
513 TyKind::RigidTy(RigidTy::FnDef(def, args)) => Some(with(|cx| cx.fn_sig(*def, args))),
514 TyKind::RigidTy(RigidTy::FnPtr(sig)) => Some(sig.clone()),
515 TyKind::RigidTy(RigidTy::Closure(_def, args)) => Some(with(|cx| cx.closure_sig(args))),
516 _ => None,
517 }
518 }
519
520 pub fn discriminant_ty(&self) -> Option<Ty> {
522 self.rigid().map(|ty| with(|cx| cx.rigid_ty_discriminant_ty(ty)))
523 }
524
525 pub fn fn_def(&self) -> Option<(FnDef, &GenericArgs)> {
527 if let TyKind::RigidTy(RigidTy::FnDef(def, args)) = self {
528 Some((*def, args))
529 } else {
530 None
531 }
532 }
533}
534
535pub struct TypeAndMut {
536 pub ty: Ty,
537 pub mutability: Mutability,
538}
539
540#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
541pub enum RigidTy {
542 Bool,
543 Char,
544 Int(IntTy),
545 Uint(UintTy),
546 Float(FloatTy),
547 Adt(AdtDef, GenericArgs),
548 Foreign(ForeignDef),
549 Str,
550 Array(Ty, TyConst),
551 Pat(Ty, Pattern),
552 Slice(Ty),
553 RawPtr(Ty, Mutability),
554 Ref(Region, Ty, Mutability),
555 FnDef(FnDef, GenericArgs),
556 FnPtr(PolyFnSig),
557 Closure(ClosureDef, GenericArgs),
558 Coroutine(CoroutineDef, GenericArgs, Movability),
560 CoroutineClosure(CoroutineClosureDef, GenericArgs),
561 Dynamic(Vec<Binder<ExistentialPredicate>>, Region, DynKind),
562 Never,
563 Tuple(Vec<Ty>),
564 CoroutineWitness(CoroutineWitnessDef, GenericArgs),
565}
566
567impl RigidTy {
568 pub fn discriminant_ty(&self) -> Ty {
570 with(|cx| cx.rigid_ty_discriminant_ty(self))
571 }
572}
573
574impl From<RigidTy> for TyKind {
575 fn from(value: RigidTy) -> Self {
576 TyKind::RigidTy(value)
577 }
578}
579
580#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
581pub enum IntTy {
582 Isize,
583 I8,
584 I16,
585 I32,
586 I64,
587 I128,
588}
589
590impl IntTy {
591 pub fn num_bytes(self) -> usize {
592 match self {
593 IntTy::Isize => MachineInfo::target_pointer_width().bytes(),
594 IntTy::I8 => 1,
595 IntTy::I16 => 2,
596 IntTy::I32 => 4,
597 IntTy::I64 => 8,
598 IntTy::I128 => 16,
599 }
600 }
601}
602
603#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
604pub enum UintTy {
605 Usize,
606 U8,
607 U16,
608 U32,
609 U64,
610 U128,
611}
612
613impl UintTy {
614 pub fn num_bytes(self) -> usize {
615 match self {
616 UintTy::Usize => MachineInfo::target_pointer_width().bytes(),
617 UintTy::U8 => 1,
618 UintTy::U16 => 2,
619 UintTy::U32 => 4,
620 UintTy::U64 => 8,
621 UintTy::U128 => 16,
622 }
623 }
624}
625
626#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
627pub enum FloatTy {
628 F16,
629 F32,
630 F64,
631 F128,
632}
633
634#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
635pub enum Movability {
636 Static,
637 Movable,
638}
639
640crate_def! {
641 #[derive(Serialize)]
642 pub ForeignModuleDef;
643}
644
645impl ForeignModuleDef {
646 pub fn module(&self) -> ForeignModule {
647 with(|cx| cx.foreign_module(*self))
648 }
649}
650
651pub struct ForeignModule {
652 pub def_id: ForeignModuleDef,
653 pub abi: Abi,
654}
655
656impl ForeignModule {
657 pub fn items(&self) -> Vec<ForeignDef> {
658 with(|cx| cx.foreign_items(self.def_id))
659 }
660}
661
662crate_def_with_ty! {
663 #[derive(Serialize)]
665 pub ForeignDef;
666}
667
668impl ForeignDef {
669 pub fn kind(&self) -> ForeignItemKind {
670 with(|cx| cx.foreign_item_kind(*self))
671 }
672}
673
674#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
675pub enum ForeignItemKind {
676 Fn(FnDef),
677 Static(StaticDef),
678 Type(Ty),
679}
680
681crate_def_with_ty! {
682 #[derive(Serialize)]
684 pub FnDef;
685}
686
687impl FnDef {
688 pub fn body(&self) -> Option<Body> {
690 with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
691 }
692
693 pub fn has_body(&self) -> bool {
695 with(|ctx| ctx.has_body(self.0))
696 }
697
698 pub fn as_intrinsic(&self) -> Option<IntrinsicDef> {
700 with(|cx| cx.intrinsic(self.def_id()))
701 }
702
703 #[inline]
705 pub fn is_intrinsic(&self) -> bool {
706 self.as_intrinsic().is_some()
707 }
708
709 pub fn fn_sig(&self) -> PolyFnSig {
711 let kind = self.ty().kind();
712 kind.fn_sig().unwrap()
713 }
714}
715
716crate_def_with_ty! {
717 #[derive(Serialize)]
718 pub IntrinsicDef;
719}
720
721impl IntrinsicDef {
722 pub fn fn_name(&self) -> Symbol {
725 with(|cx| cx.intrinsic_name(*self))
726 }
727
728 pub fn must_be_overridden(&self) -> bool {
731 with(|cx| !cx.has_body(self.0))
732 }
733}
734
735impl From<IntrinsicDef> for FnDef {
736 fn from(def: IntrinsicDef) -> Self {
737 FnDef(def.0)
738 }
739}
740
741crate_def! {
742 #[derive(Serialize)]
743 pub ClosureDef;
744}
745
746impl ClosureDef {
747 pub fn body(&self) -> Option<Body> {
750 with(|ctx| ctx.has_body(self.0).then(|| ctx.mir_body(self.0)))
751 }
752}
753
754crate_def! {
755 #[derive(Serialize)]
756 pub CoroutineDef;
757}
758
759impl CoroutineDef {
760 pub fn discriminant_for_variant(&self, args: &GenericArgs, idx: VariantIdx) -> Discr {
761 with(|cx| cx.coroutine_discr_for_variant(*self, args, idx))
762 }
763}
764
765crate_def! {
766 #[derive(Serialize)]
767 pub CoroutineClosureDef;
768}
769
770crate_def! {
771 #[derive(Serialize)]
772 pub ParamDef;
773}
774
775crate_def! {
776 #[derive(Serialize)]
777 pub BrNamedDef;
778}
779
780crate_def! {
781 #[derive(Serialize)]
782 pub AdtDef;
783}
784
785#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
786pub enum AdtKind {
787 Enum,
788 Union,
789 Struct,
790}
791
792impl AdtDef {
793 pub fn kind(&self) -> AdtKind {
794 with(|cx| cx.adt_kind(*self))
795 }
796
797 pub fn ty(&self) -> Ty {
799 with(|cx| cx.def_ty(self.0))
800 }
801
802 pub fn ty_with_args(&self, args: &GenericArgs) -> Ty {
806 with(|cx| cx.def_ty_with_args(self.0, args))
807 }
808
809 pub fn is_box(&self) -> bool {
810 with(|cx| cx.adt_is_box(*self))
811 }
812
813 pub fn is_simd(&self) -> bool {
814 with(|cx| cx.adt_is_simd(*self))
815 }
816
817 pub fn num_variants(&self) -> usize {
819 with(|cx| cx.adt_variants_len(*self))
820 }
821
822 pub fn variants(&self) -> Vec<VariantDef> {
824 self.variants_iter().collect()
825 }
826
827 pub fn variants_iter(&self) -> impl Iterator<Item = VariantDef> {
829 (0..self.num_variants())
830 .map(|idx| VariantDef { idx: VariantIdx::to_val(idx), adt_def: *self })
831 }
832
833 pub fn variant(&self, idx: VariantIdx) -> Option<VariantDef> {
834 (idx.to_index() < self.num_variants()).then_some(VariantDef { idx, adt_def: *self })
835 }
836
837 pub fn repr(&self) -> ReprOptions {
838 with(|cx| cx.adt_repr(*self))
839 }
840
841 pub fn discriminant_for_variant(&self, idx: VariantIdx) -> Discr {
842 with(|cx| cx.adt_discr_for_variant(*self, idx))
843 }
844}
845
846pub struct Discr {
847 pub val: u128,
848 pub ty: Ty,
849}
850
851#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
853pub struct VariantDef {
854 pub idx: VariantIdx,
859 pub adt_def: AdtDef,
866}
867
868impl VariantDef {
869 pub fn name(&self) -> Symbol {
870 with(|cx| cx.variant_name(*self))
871 }
872
873 pub fn fields(&self) -> Vec<FieldDef> {
877 with(|cx| cx.variant_fields(*self))
878 }
879}
880
881#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
882pub struct FieldDef {
883 pub def: DefId,
888
889 pub name: Symbol,
891}
892
893impl FieldDef {
894 pub fn ty_with_args(&self, args: &GenericArgs) -> Ty {
898 with(|cx| cx.def_ty_with_args(self.def, args))
899 }
900
901 pub fn ty(&self) -> Ty {
903 with(|cx| cx.def_ty(self.def))
904 }
905}
906
907impl Display for AdtKind {
908 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
909 f.write_str(match self {
910 AdtKind::Enum => "enum",
911 AdtKind::Union => "union",
912 AdtKind::Struct => "struct",
913 })
914 }
915}
916
917impl AdtKind {
918 pub fn is_enum(&self) -> bool {
919 matches!(self, AdtKind::Enum)
920 }
921
922 pub fn is_struct(&self) -> bool {
923 matches!(self, AdtKind::Struct)
924 }
925
926 pub fn is_union(&self) -> bool {
927 matches!(self, AdtKind::Union)
928 }
929}
930
931crate_def! {
932 #[derive(Serialize)]
933 pub AliasDef;
934}
935
936crate_def! {
937 #[derive(Serialize)]
939 pub TraitDef;
940}
941
942impl_crate_def_items! {
943 TraitDef;
944}
945
946impl TraitDef {
947 pub fn declaration(trait_def: &TraitDef) -> TraitDecl {
948 with(|cx| cx.trait_decl(trait_def))
949 }
950}
951
952crate_def! {
953 #[derive(Serialize)]
954 pub GenericDef;
955}
956
957crate_def_with_ty! {
958 #[derive(Serialize)]
959 pub ConstDef;
960}
961
962crate_def! {
963 #[derive(Serialize)]
965 pub ImplDef;
966}
967
968impl_crate_def_items! {
969 ImplDef;
970}
971
972impl ImplDef {
973 pub fn trait_impl(&self) -> ImplTrait {
975 with(|cx| cx.trait_impl(self))
976 }
977}
978
979crate_def! {
980 #[derive(Serialize)]
981 pub RegionDef;
982}
983
984crate_def! {
985 #[derive(Serialize)]
986 pub CoroutineWitnessDef;
987}
988
989#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
991pub struct GenericArgs(pub Vec<GenericArgKind>);
992
993impl std::ops::Index<ParamTy> for GenericArgs {
994 type Output = Ty;
995
996 fn index(&self, index: ParamTy) -> &Self::Output {
997 self.0[index.index as usize].expect_ty()
998 }
999}
1000
1001impl std::ops::Index<ParamConst> for GenericArgs {
1002 type Output = TyConst;
1003
1004 fn index(&self, index: ParamConst) -> &Self::Output {
1005 self.0[index.index as usize].expect_const()
1006 }
1007}
1008
1009#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1010pub enum GenericArgKind {
1011 Lifetime(Region),
1012 Type(Ty),
1013 Const(TyConst),
1014}
1015
1016impl GenericArgKind {
1017 #[track_caller]
1020 pub fn expect_ty(&self) -> &Ty {
1021 match self {
1022 GenericArgKind::Type(ty) => ty,
1023 _ => panic!("{self:?}"),
1024 }
1025 }
1026
1027 #[track_caller]
1030 pub fn expect_const(&self) -> &TyConst {
1031 match self {
1032 GenericArgKind::Const(c) => c,
1033 _ => panic!("{self:?}"),
1034 }
1035 }
1036
1037 pub fn ty(&self) -> Option<&Ty> {
1039 match self {
1040 GenericArgKind::Type(ty) => Some(ty),
1041 _ => None,
1042 }
1043 }
1044}
1045
1046#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1047pub enum TermKind {
1048 Type(Ty),
1049 Const(TyConst),
1050}
1051
1052#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1053pub enum AliasKind {
1054 Projection,
1055 Inherent,
1056 Opaque,
1057 Free,
1058}
1059
1060#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1061pub struct AliasTy {
1062 pub def_id: AliasDef,
1063 pub args: GenericArgs,
1064}
1065
1066#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1067pub struct AliasTerm {
1068 pub def_id: AliasDef,
1069 pub args: GenericArgs,
1070}
1071
1072pub type PolyFnSig = Binder<FnSig>;
1073
1074impl PolyFnSig {
1075 pub fn fn_ptr_abi(self) -> Result<FnAbi, Error> {
1080 with(|cx| cx.fn_ptr_abi(self))
1081 }
1082}
1083
1084#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1085pub struct FnSig {
1086 pub inputs_and_output: Vec<Ty>,
1087 pub c_variadic: bool,
1088 pub safety: Safety,
1089 pub abi: Abi,
1090}
1091
1092impl FnSig {
1093 pub fn output(&self) -> Ty {
1094 self.inputs_and_output[self.inputs_and_output.len() - 1]
1095 }
1096
1097 pub fn inputs(&self) -> &[Ty] {
1098 &self.inputs_and_output[..self.inputs_and_output.len() - 1]
1099 }
1100}
1101
1102#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
1103pub enum Abi {
1104 Rust,
1105 C { unwind: bool },
1106 Cdecl { unwind: bool },
1107 Stdcall { unwind: bool },
1108 Fastcall { unwind: bool },
1109 Vectorcall { unwind: bool },
1110 Thiscall { unwind: bool },
1111 Aapcs { unwind: bool },
1112 Win64 { unwind: bool },
1113 SysV64 { unwind: bool },
1114 PtxKernel,
1115 Msp430Interrupt,
1116 X86Interrupt,
1117 GpuKernel,
1118 EfiApi,
1119 AvrInterrupt,
1120 AvrNonBlockingInterrupt,
1121 CCmseNonSecureCall,
1122 CCmseNonSecureEntry,
1123 System { unwind: bool },
1124 RustCall,
1125 Unadjusted,
1126 RustCold,
1127 RiscvInterruptM,
1128 RiscvInterruptS,
1129 RustInvalid,
1130 Custom,
1131}
1132
1133#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1135pub struct Binder<T> {
1136 pub value: T,
1137 pub bound_vars: Vec<BoundVariableKind>,
1138}
1139
1140impl<T> Binder<T> {
1141 pub fn bind_with_vars(value: T, bound_vars: Vec<BoundVariableKind>) -> Self {
1143 Binder { value, bound_vars }
1144 }
1145
1146 pub fn dummy(value: T) -> Self {
1148 Binder { value, bound_vars: vec![] }
1149 }
1150
1151 pub fn skip_binder(self) -> T {
1152 self.value
1153 }
1154
1155 pub fn map_bound_ref<F, U>(&self, f: F) -> Binder<U>
1156 where
1157 F: FnOnce(&T) -> U,
1158 {
1159 let Binder { value, bound_vars } = self;
1160 let new_value = f(value);
1161 Binder { value: new_value, bound_vars: bound_vars.clone() }
1162 }
1163
1164 pub fn map_bound<F, U>(self, f: F) -> Binder<U>
1165 where
1166 F: FnOnce(T) -> U,
1167 {
1168 let Binder { value, bound_vars } = self;
1169 let new_value = f(value);
1170 Binder { value: new_value, bound_vars }
1171 }
1172}
1173
1174#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1175pub struct EarlyBinder<T> {
1176 pub value: T,
1177}
1178
1179#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1180pub enum BoundVariableKind {
1181 Ty(BoundTyKind),
1182 Region(BoundRegionKind),
1183 Const,
1184}
1185
1186#[derive(Clone, PartialEq, Eq, Debug, Serialize)]
1187pub enum BoundTyKind {
1188 Anon,
1189 Param(ParamDef, String),
1190}
1191
1192#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1193pub enum BoundRegionKind {
1194 BrAnon,
1195 BrNamed(BrNamedDef, String),
1196 BrEnv,
1197}
1198
1199#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1200pub enum DynKind {
1201 Dyn,
1202 DynStar,
1203}
1204
1205#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1206pub enum ExistentialPredicate {
1207 Trait(ExistentialTraitRef),
1208 Projection(ExistentialProjection),
1209 AutoTrait(TraitDef),
1210}
1211
1212#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1216pub struct ExistentialTraitRef {
1217 pub def_id: TraitDef,
1218 pub generic_args: GenericArgs,
1219}
1220
1221impl Binder<ExistentialTraitRef> {
1222 pub fn with_self_ty(&self, self_ty: Ty) -> Binder<TraitRef> {
1223 self.map_bound_ref(|trait_ref| trait_ref.with_self_ty(self_ty))
1224 }
1225}
1226
1227impl ExistentialTraitRef {
1228 pub fn with_self_ty(&self, self_ty: Ty) -> TraitRef {
1229 TraitRef::new(self.def_id, self_ty, &self.generic_args)
1230 }
1231}
1232
1233#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1234pub struct ExistentialProjection {
1235 pub def_id: TraitDef,
1236 pub generic_args: GenericArgs,
1237 pub term: TermKind,
1238}
1239
1240#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1241pub struct ParamTy {
1242 pub index: u32,
1243 pub name: String,
1244}
1245
1246#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1247pub struct BoundTy {
1248 pub var: usize,
1249 pub kind: BoundTyKind,
1250}
1251
1252pub type Bytes = Vec<Option<u8>>;
1253
1254pub type Size = usize;
1256
1257#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
1258pub struct Prov(pub AllocId);
1259
1260pub type Align = u64;
1261pub type Promoted = u32;
1262pub type InitMaskMaterialized = Vec<u64>;
1263
1264#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
1266pub struct ProvenanceMap {
1267 pub ptrs: Vec<(Size, Prov)>,
1270}
1271
1272#[derive(Clone, Debug, Eq, PartialEq, Hash, Serialize)]
1273pub struct Allocation {
1274 pub bytes: Bytes,
1275 pub provenance: ProvenanceMap,
1276 pub align: Align,
1277 pub mutability: Mutability,
1278}
1279
1280impl Allocation {
1281 pub fn raw_bytes(&self) -> Result<Vec<u8>, Error> {
1283 self.bytes
1284 .iter()
1285 .copied()
1286 .collect::<Option<Vec<_>>>()
1287 .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))
1288 }
1289
1290 pub fn read_partial_uint(&self, range: Range<usize>) -> Result<u128, Error> {
1292 if range.end - range.start > 16 {
1293 return Err(error!("Allocation is bigger than largest integer"));
1294 }
1295 if range.end > self.bytes.len() {
1296 return Err(error!(
1297 "Range is out of bounds. Allocation length is `{}`, but requested range `{:?}`",
1298 self.bytes.len(),
1299 range
1300 ));
1301 }
1302 let raw = self.bytes[range]
1303 .iter()
1304 .copied()
1305 .collect::<Option<Vec<_>>>()
1306 .ok_or_else(|| error!("Found uninitialized bytes: `{:?}`", self.bytes))?;
1307 read_target_uint(&raw)
1308 }
1309
1310 pub fn read_uint(&self) -> Result<u128, Error> {
1312 if self.bytes.len() > 16 {
1313 return Err(error!("Allocation is bigger than largest integer"));
1314 }
1315 let raw = self.raw_bytes()?;
1316 read_target_uint(&raw)
1317 }
1318
1319 pub fn read_int(&self) -> Result<i128, Error> {
1321 if self.bytes.len() > 16 {
1322 return Err(error!("Allocation is bigger than largest integer"));
1323 }
1324 let raw = self.raw_bytes()?;
1325 read_target_int(&raw)
1326 }
1327
1328 pub fn read_bool(&self) -> Result<bool, Error> {
1330 match self.read_int()? {
1331 0 => Ok(false),
1332 1 => Ok(true),
1333 val => Err(error!("Unexpected value for bool: `{val}`")),
1334 }
1335 }
1336
1337 pub fn is_null(&self) -> Result<bool, Error> {
1339 let len = self.bytes.len();
1340 let ptr_len = MachineInfo::target_pointer_width().bytes();
1341 if len != ptr_len {
1342 return Err(error!("Expected width of pointer (`{ptr_len}`), but found: `{len}`"));
1343 }
1344 Ok(self.read_uint()? == 0 && self.provenance.ptrs.is_empty())
1345 }
1346}
1347
1348#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1349pub enum ConstantKind {
1350 Ty(TyConst),
1351 Allocated(Allocation),
1352 Unevaluated(UnevaluatedConst),
1353 Param(ParamConst),
1354 ZeroSized,
1357}
1358
1359#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1360pub struct ParamConst {
1361 pub index: u32,
1362 pub name: String,
1363}
1364
1365#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1366pub struct UnevaluatedConst {
1367 pub def: ConstDef,
1368 pub args: GenericArgs,
1369 pub promoted: Option<Promoted>,
1370}
1371
1372#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
1373pub enum TraitSpecializationKind {
1374 None,
1375 Marker,
1376 AlwaysApplicable,
1377}
1378
1379#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1380pub struct TraitDecl {
1381 pub def_id: TraitDef,
1382 pub safety: Safety,
1383 pub paren_sugar: bool,
1384 pub has_auto_impl: bool,
1385 pub is_marker: bool,
1386 pub is_coinductive: bool,
1387 pub skip_array_during_method_dispatch: bool,
1388 pub skip_boxed_slice_during_method_dispatch: bool,
1389 pub specialization_kind: TraitSpecializationKind,
1390 pub must_implement_one_of: Option<Vec<Ident>>,
1391 pub implement_via_object: bool,
1392 pub deny_explicit_impl: bool,
1393}
1394
1395impl TraitDecl {
1396 pub fn generics_of(&self) -> Generics {
1397 with(|cx| cx.generics_of(self.def_id.0))
1398 }
1399
1400 pub fn predicates_of(&self) -> GenericPredicates {
1401 with(|cx| cx.predicates_of(self.def_id.0))
1402 }
1403
1404 pub fn explicit_predicates_of(&self) -> GenericPredicates {
1405 with(|cx| cx.explicit_predicates_of(self.def_id.0))
1406 }
1407}
1408
1409pub type ImplTrait = EarlyBinder<TraitRef>;
1410
1411#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1413pub struct TraitRef {
1414 pub def_id: TraitDef,
1415 args: GenericArgs,
1418}
1419
1420impl TraitRef {
1421 pub fn new(def_id: TraitDef, self_ty: Ty, gen_args: &GenericArgs) -> TraitRef {
1422 let mut args = vec![GenericArgKind::Type(self_ty)];
1423 args.extend_from_slice(&gen_args.0);
1424 TraitRef { def_id, args: GenericArgs(args) }
1425 }
1426
1427 pub fn try_new(def_id: TraitDef, args: GenericArgs) -> Result<TraitRef, ()> {
1428 match &args.0[..] {
1429 [GenericArgKind::Type(_), ..] => Ok(TraitRef { def_id, args }),
1430 _ => Err(()),
1431 }
1432 }
1433
1434 pub fn args(&self) -> &GenericArgs {
1435 &self.args
1436 }
1437
1438 pub fn self_ty(&self) -> Ty {
1439 let GenericArgKind::Type(self_ty) = self.args.0[0] else {
1440 panic!("Self must be a type, but found: {:?}", self.args.0[0])
1441 };
1442 self_ty
1443 }
1444}
1445
1446#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1447pub struct Generics {
1448 pub parent: Option<GenericDef>,
1449 pub parent_count: usize,
1450 pub params: Vec<GenericParamDef>,
1451 pub param_def_id_to_index: Vec<(GenericDef, u32)>,
1452 pub has_self: bool,
1453 pub has_late_bound_regions: Option<Span>,
1454}
1455
1456#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1457pub enum GenericParamDefKind {
1458 Lifetime,
1459 Type { has_default: bool, synthetic: bool },
1460 Const { has_default: bool },
1461}
1462
1463#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1464pub struct GenericParamDef {
1465 pub name: super::Symbol,
1466 pub def_id: GenericDef,
1467 pub index: u32,
1468 pub pure_wrt_drop: bool,
1469 pub kind: GenericParamDefKind,
1470}
1471
1472pub struct GenericPredicates {
1473 pub parent: Option<TraitDef>,
1474 pub predicates: Vec<(PredicateKind, Span)>,
1475}
1476
1477#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1478pub enum PredicateKind {
1479 Clause(ClauseKind),
1480 DynCompatible(TraitDef),
1481 SubType(SubtypePredicate),
1482 Coerce(CoercePredicate),
1483 ConstEquate(TyConst, TyConst),
1484 Ambiguous,
1485 AliasRelate(TermKind, TermKind, AliasRelationDirection),
1486}
1487
1488#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1489pub enum ClauseKind {
1490 Trait(TraitPredicate),
1491 RegionOutlives(RegionOutlivesPredicate),
1492 TypeOutlives(TypeOutlivesPredicate),
1493 Projection(ProjectionPredicate),
1494 ConstArgHasType(TyConst, Ty),
1495 WellFormed(TermKind),
1496 ConstEvaluatable(TyConst),
1497}
1498
1499#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1500pub enum ClosureKind {
1501 Fn,
1502 FnMut,
1503 FnOnce,
1504}
1505
1506#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1507pub struct SubtypePredicate {
1508 pub a: Ty,
1509 pub b: Ty,
1510}
1511
1512#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1513pub struct CoercePredicate {
1514 pub a: Ty,
1515 pub b: Ty,
1516}
1517
1518#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1519pub enum AliasRelationDirection {
1520 Equate,
1521 Subtype,
1522}
1523
1524#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1525pub struct TraitPredicate {
1526 pub trait_ref: TraitRef,
1527 pub polarity: PredicatePolarity,
1528}
1529
1530#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1531pub struct OutlivesPredicate<A, B>(pub A, pub B);
1532
1533pub type RegionOutlivesPredicate = OutlivesPredicate<Region, Region>;
1534pub type TypeOutlivesPredicate = OutlivesPredicate<Ty, Region>;
1535
1536#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1537pub struct ProjectionPredicate {
1538 pub projection_term: AliasTerm,
1539 pub term: TermKind,
1540}
1541
1542#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1543pub enum ImplPolarity {
1544 Positive,
1545 Negative,
1546 Reservation,
1547}
1548
1549#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1550pub enum PredicatePolarity {
1551 Positive,
1552 Negative,
1553}
1554
1555pub trait IndexedVal {
1556 fn to_val(index: usize) -> Self;
1557
1558 fn to_index(&self) -> usize;
1559}
1560
1561macro_rules! index_impl {
1562 ($name:ident) => {
1563 impl IndexedVal for $name {
1564 fn to_val(index: usize) -> Self {
1565 $name(index)
1566 }
1567 fn to_index(&self) -> usize {
1568 self.0
1569 }
1570 }
1571 };
1572}
1573
1574index_impl!(TyConstId);
1575index_impl!(MirConstId);
1576index_impl!(Ty);
1577index_impl!(Span);
1578
1579#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize)]
1593pub struct VariantIdx(usize);
1594
1595index_impl!(VariantIdx);
1596
1597crate_def! {
1598 #[derive(Serialize)]
1600 pub OpaqueDef;
1601}
1602
1603crate_def! {
1604 #[derive(Serialize)]
1605 pub AssocDef;
1606}
1607
1608#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1609pub struct AssocItem {
1610 pub def_id: AssocDef,
1611 pub kind: AssocKind,
1612 pub container: AssocItemContainer,
1613
1614 pub trait_item_def_id: Option<AssocDef>,
1617}
1618
1619#[derive(Clone, PartialEq, Debug, Eq, Serialize)]
1620pub enum AssocTypeData {
1621 Normal(Symbol),
1622 Rpitit(ImplTraitInTraitData),
1626}
1627
1628#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1629pub enum AssocKind {
1630 Const { name: Symbol },
1631 Fn { name: Symbol, has_self: bool },
1632 Type { data: AssocTypeData },
1633}
1634
1635#[derive(Clone, Debug, Eq, PartialEq, Serialize)]
1636pub enum AssocItemContainer {
1637 Trait,
1638 Impl,
1639}
1640
1641#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Serialize)]
1642pub enum ImplTraitInTraitData {
1643 Trait { fn_def_id: FnDef, opaque_def_id: OpaqueDef },
1644 Impl { fn_def_id: FnDef },
1645}
1646
1647impl AssocItem {
1648 pub fn is_impl_trait_in_trait(&self) -> bool {
1649 matches!(self.kind, AssocKind::Type { data: AssocTypeData::Rpitit(_) })
1650 }
1651}