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