1use crate::ast::*;
2use derive_generic_visitor::*;
3use macros::{EnumAsGetters, EnumIsA, EnumToGetters, VariantIndexArity, VariantName};
4use serde::{Deserialize, Serialize};
5use serde_state::{DeserializeState, SerializeState};
6
7#[derive(
12 Debug,
13 Clone,
14 PartialEq,
15 Eq,
16 PartialOrd,
17 Ord,
18 Hash,
19 SerializeState,
20 DeserializeState,
21 Drive,
22 DriveMut,
23 DriveTwo,
24)]
25#[serde_state(state_implements = HashConsSerializerState)] pub struct Ty(pub HashConsed<TyKind>);
27
28#[derive(
29 Debug,
30 Clone,
31 PartialEq,
32 Eq,
33 PartialOrd,
34 Ord,
35 Hash,
36 VariantName,
37 EnumIsA,
38 EnumAsGetters,
39 EnumToGetters,
40 VariantIndexArity,
41 SerializeState,
42 DeserializeState,
43 Drive,
44 DriveMut,
45 DriveTwo,
46)]
47#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
48pub enum TyKind {
49 Adt(TypeDeclRef),
61 #[cfg_attr(feature = "charon_on_charon", charon::rename("TVar"))]
62 TypeVar(TypeDbVar),
63 Literal(LiteralTy),
64 Never,
80 Ref(Region, Ty, RefKind),
83 RawPtr(Ty, RefKind),
85 TraitType(TraitRef, AssocTypeId, GenericArgs),
94 DynTrait(DynPredicate),
96 FnPtr(RegionBinder<FunSig>),
101 FnDef(RegionBinder<FnPtr>),
110 PtrMetadata(Ty),
113 Array(Ty, Box<ConstantExpr>),
115 Slice(Ty),
117 Pattern(Ty, TypePattern),
120 #[drive(skip)]
122 Error(String),
123}
124
125#[derive(
126 Debug,
127 PartialEq,
128 Eq,
129 Copy,
130 Clone,
131 EnumIsA,
132 VariantName,
133 Serialize,
134 Deserialize,
135 Drive,
136 DriveMut,
137 DriveTwo,
138 Hash,
139 Ord,
140 PartialOrd,
141)]
142pub enum IntTy {
143 Isize,
144 I8,
145 I16,
146 I32,
147 I64,
148 I128,
149}
150
151#[derive(
152 Debug,
153 PartialEq,
154 Eq,
155 Copy,
156 Clone,
157 EnumIsA,
158 VariantName,
159 Serialize,
160 Deserialize,
161 Drive,
162 DriveMut,
163 DriveTwo,
164 Hash,
165 Ord,
166 PartialOrd,
167)]
168pub enum UIntTy {
169 Usize,
170 U8,
171 U16,
172 U32,
173 U64,
174 U128,
175}
176
177#[derive(
178 Debug,
179 PartialEq,
180 Eq,
181 Copy,
182 Clone,
183 EnumIsA,
184 VariantName,
185 Serialize,
186 Deserialize,
187 Drive,
188 DriveMut,
189 DriveTwo,
190 Hash,
191 Ord,
192 PartialOrd,
193)]
194#[cfg_attr(feature = "charon_on_charon", charon::rename("IntegerType"))]
195pub enum IntegerTy {
196 Signed(IntTy),
197 Unsigned(UIntTy),
198}
199
200#[derive(
201 Debug,
202 PartialEq,
203 Eq,
204 Copy,
205 Clone,
206 EnumIsA,
207 VariantName,
208 Serialize,
209 Deserialize,
210 Drive,
211 DriveMut,
212 DriveTwo,
213 Hash,
214 Ord,
215 PartialOrd,
216)]
217#[cfg_attr(feature = "charon_on_charon", charon::rename("FloatType"))]
218pub enum FloatTy {
219 F16,
220 F32,
221 F64,
222 F128,
223}
224
225#[derive(
227 Debug,
228 PartialEq,
229 Eq,
230 Clone,
231 Copy,
232 VariantName,
233 EnumIsA,
234 EnumAsGetters,
235 VariantIndexArity,
236 Serialize,
237 Deserialize,
238 SerializeState,
239 DeserializeState,
240 Drive,
241 DriveMut,
242 DriveTwo,
243 Hash,
244 Ord,
245 PartialOrd,
246)]
247#[cfg_attr(feature = "charon_on_charon", charon::rename("LiteralType"))]
248#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
249#[serde_state(stateless)]
250pub enum LiteralTy {
251 Int(IntTy),
252 UInt(UIntTy),
253 Float(FloatTy),
254 Bool,
255 Char,
256}
257
258#[derive(
269 Debug,
270 PartialEq,
271 Eq,
272 Clone,
273 Copy,
274 EnumIsA,
275 EnumAsGetters,
276 VariantName,
277 Serialize,
278 Deserialize,
279 Drive,
280 DriveMut,
281 DriveTwo,
282 Hash,
283 Ord,
284 PartialOrd,
285)]
286#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
287pub enum BuiltinTy {
288 Tuple,
290 Box,
292 Str,
294}
295
296impl BuiltinTy {
297 pub fn get_name(self) -> Name {
298 let name: &[_] = match self {
299 BuiltinTy::Box => &["alloc", "boxed", "Box"],
300 BuiltinTy::Str => &["str"],
301 BuiltinTy::Tuple => &["Tuple"],
302 };
303 Name::from_path(name)
304 }
305}
306
307#[derive(
308 Debug,
309 PartialEq,
310 Eq,
311 Clone,
312 Copy,
313 Hash,
314 VariantName,
315 EnumIsA,
316 Serialize,
317 Deserialize,
318 SerializeState,
319 DeserializeState,
320 Drive,
321 DriveMut,
322 DriveTwo,
323 Ord,
324 PartialOrd,
325)]
326#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
327#[serde_state(stateless)]
328pub enum RefKind {
329 Mut,
330 Shared,
331}
332
333#[derive(
335 Debug,
336 Clone,
337 PartialEq,
338 Eq,
339 PartialOrd,
340 Ord,
341 Hash,
342 SerializeState,
343 DeserializeState,
344 Drive,
345 DriveMut,
346 DriveTwo,
347)]
348pub struct DynPredicate {
349 pub binder: Binder<Ty>,
356}
357
358#[derive(
360 Debug,
361 Clone,
362 PartialEq,
363 Eq,
364 PartialOrd,
365 Ord,
366 Hash,
367 VariantName,
368 EnumIsA,
369 SerializeState,
370 DeserializeState,
371 Drive,
372 DriveMut,
373 DriveTwo,
374)]
375#[serde_state(state_implements = HashConsSerializerState)] pub enum TypePattern {
377 Range(Box<ConstantExpr>, Box<ConstantExpr>),
378 OrPattern(Vec<TypePattern>),
379 NotNull,
380}
381
382macro_rules! static_type {
383 ($e:expr) => {{
384 use std::sync::LazyLock;
385 static TY: LazyLock<Ty> = LazyLock::new(|| $e.into_ty());
386 TY.clone()
387 }};
388}
389
390impl Ty {
391 pub fn new(kind: TyKind) -> Self {
392 Ty(HashConsed::new(kind))
393 }
394
395 pub fn kind(&self) -> &TyKind {
396 self.0.inner()
397 }
398
399 pub fn with_kind_mut<R>(&mut self, f: impl FnOnce(&mut TyKind) -> R) -> R {
400 self.0.with_inner_mut(f)
401 }
402
403 pub fn mk_unit() -> Ty {
405 static_type!(Ty::mk_tuple(vec![]).kind().clone())
406 }
407
408 pub fn mk_bool() -> Ty {
409 static_type!(TyKind::Literal(LiteralTy::Bool))
410 }
411
412 pub fn mk_usize() -> Ty {
413 static_type!(TyKind::Literal(LiteralTy::UInt(UIntTy::Usize)))
414 }
415
416 pub fn mk_tuple(tys: Vec<Ty>) -> Ty {
417 TyKind::Adt(TypeDeclRef {
418 id: TypeId::Builtin(BuiltinTy::Tuple),
419 generics: Box::new(GenericArgs::new_types(tys.into())),
420 })
421 .into_ty()
422 }
423
424 pub fn mk_array(ty: Ty, len: ConstantExpr) -> Ty {
425 TyKind::Array(ty, Box::new(len)).into_ty()
426 }
427
428 pub fn mk_slice(ty: Ty) -> Ty {
429 TyKind::Slice(ty).into_ty()
430 }
431 pub fn is_unit(&self) -> bool {
433 match self.as_tuple() {
434 Some(tys) => tys.is_empty(),
435 None => false,
436 }
437 }
438
439 pub fn is_scalar(&self) -> bool {
441 match self.kind() {
442 TyKind::Literal(kind) => kind.is_int() || kind.is_uint(),
443 TyKind::Pattern(ty, _) => ty.is_scalar(),
444 _ => false,
445 }
446 }
447
448 pub fn is_unsigned_scalar(&self) -> bool {
449 match self.kind() {
450 TyKind::Literal(LiteralTy::UInt(_)) => true,
451 TyKind::Pattern(ty, _) => ty.is_unsigned_scalar(),
452 _ => false,
453 }
454 }
455
456 pub fn is_signed_scalar(&self) -> bool {
457 match self.kind() {
458 TyKind::Literal(LiteralTy::Int(_)) => true,
459 TyKind::Pattern(ty, _) => ty.is_signed_scalar(),
460 _ => false,
461 }
462 }
463
464 pub fn is_str(&self) -> bool {
465 match self.kind() {
466 TyKind::Adt(ty_ref) => ty_ref.is_str(),
467 _ => false,
468 }
469 }
470
471 pub fn is_box(&self) -> bool {
473 match self.kind() {
474 TyKind::Adt(ty_ref) => ty_ref.is_box(),
475 _ => false,
476 }
477 }
478
479 pub fn as_box(&self) -> Option<&Ty> {
480 match self.kind() {
481 TyKind::Adt(ty_ref) if ty_ref.is_box() => Some(&ty_ref.generics.types[0]),
482 _ => None,
483 }
484 }
485
486 pub fn as_adt_id(&self) -> Option<TypeDeclId> {
487 self.kind().as_adt()?.as_adt()
488 }
489
490 pub fn get_ptr_metadata(&self, translated: &TranslatedCrate) -> PtrMetadata {
491 let ty_decls = &translated.type_decls;
492 match self.kind() {
493 TyKind::Pattern(ty, _) => ty.get_ptr_metadata(translated),
494 TyKind::Adt(ty_ref) => {
495 match ty_ref.as_builtin() {
499 None => {
500 let Some(decl) = ty_decls.get(ty_ref.adt_id()) else {
501 return PtrMetadata::InheritFrom(self.clone());
502 };
503 match decl.ptr_metadata.clone().substitute(&ty_ref.generics) {
504 PtrMetadata::InheritFrom(ty) => ty.get_ptr_metadata(translated),
506 meta => meta,
508 }
509 }
510 Some(BuiltinTy::Tuple) => {
512 match ty_ref.generics.types.iter().last() {
513 None => PtrMetadata::None,
515 Some(ty) => ty.get_ptr_metadata(translated),
517 }
518 }
519 Some(BuiltinTy::Box) => PtrMetadata::None,
521 Some(BuiltinTy::Str) => PtrMetadata::Length,
523 }
524 }
525 TyKind::DynTrait(pred) => match pred.vtable_ref(translated) {
526 Some(vtable) => PtrMetadata::VTable(vtable),
527 None => PtrMetadata::InheritFrom(self.clone()),
528 },
529 TyKind::Slice(..) => PtrMetadata::Length,
531 TyKind::TraitType(..) | TyKind::TypeVar(_) => PtrMetadata::InheritFrom(self.clone()),
532 TyKind::Literal(_)
533 | TyKind::Never
534 | TyKind::Ref(..)
535 | TyKind::RawPtr(..)
536 | TyKind::FnPtr(..)
537 | TyKind::FnDef(..)
538 | TyKind::Array(..)
539 | TyKind::Error(_) => PtrMetadata::None,
540 TyKind::PtrMetadata(_) => PtrMetadata::None,
542 }
543 }
544
545 pub fn as_ref_or_ptr(&self) -> Option<&Ty> {
546 match self.kind() {
547 TyKind::RawPtr(ty, _) | TyKind::Ref(_, ty, _) => Some(ty),
548 _ => None,
549 }
550 }
551
552 pub fn as_array_or_slice(&self) -> Option<&Ty> {
553 match self.kind() {
554 TyKind::Slice(ty) | TyKind::Array(ty, _) => Some(ty),
555 _ => None,
556 }
557 }
558
559 pub fn as_tuple(&self) -> Option<&IndexVec<TypeVarId, Ty>> {
560 match self.kind() {
561 TyKind::Adt(ty_ref) if ty_ref.is_tuple() => Some(&ty_ref.generics.types),
562 _ => None,
563 }
564 }
565
566 pub fn as_adt(&self) -> Option<&TypeDeclRef> {
567 self.kind().as_adt()
568 }
569}
570
571impl TyKind {
572 pub fn into_ty(self) -> Ty {
573 Ty::new(self)
574 }
575}
576
577impl IntegerTy {
578 pub fn to_unsigned(&self) -> Self {
579 match self {
580 IntegerTy::Signed(IntTy::Isize) => IntegerTy::Unsigned(UIntTy::Usize),
581 IntegerTy::Signed(IntTy::I8) => IntegerTy::Unsigned(UIntTy::U8),
582 IntegerTy::Signed(IntTy::I16) => IntegerTy::Unsigned(UIntTy::U16),
583 IntegerTy::Signed(IntTy::I32) => IntegerTy::Unsigned(UIntTy::U32),
584 IntegerTy::Signed(IntTy::I64) => IntegerTy::Unsigned(UIntTy::U64),
585 IntegerTy::Signed(IntTy::I128) => IntegerTy::Unsigned(UIntTy::U128),
586 _ => *self,
587 }
588 }
589
590 pub fn target_size(&self, ptr_size: ByteCount) -> usize {
593 match self {
594 IntegerTy::Signed(ty) => ty.target_size(ptr_size),
595 IntegerTy::Unsigned(ty) => ty.target_size(ptr_size),
596 }
597 }
598}
599
600impl LiteralTy {
601 pub fn to_integer_ty(&self) -> Option<IntegerTy> {
602 match self {
603 Self::Int(int_ty) => Some(IntegerTy::Signed(*int_ty)),
604 Self::UInt(uint_ty) => Some(IntegerTy::Unsigned(*uint_ty)),
605 _ => None,
606 }
607 }
608
609 pub fn target_size(&self, ptr_size: ByteCount) -> usize {
612 match self {
613 LiteralTy::Int(int_ty) => int_ty.target_size(ptr_size),
614 LiteralTy::UInt(uint_ty) => uint_ty.target_size(ptr_size),
615 LiteralTy::Float(float_ty) => float_ty.target_size(),
616 LiteralTy::Char => 4,
617 LiteralTy::Bool => 1,
618 }
619 }
620}
621
622impl RefKind {
623 pub fn mutable(x: bool) -> Self {
624 if x { Self::Mut } else { Self::Shared }
625 }
626}
627
628impl DynPredicate {
629 pub fn vtable_ref(&self, translated: &TranslatedCrate) -> Option<TypeDeclRef> {
631 let dyn_ty = TyKind::DynTrait(self.clone()).into_ty();
632 let relevant_tref = self.binder.params.trait_clauses[0]
635 .trait_
636 .clone()
637 .erase()
638 .substitute(&GenericArgs::new_types([dyn_ty].into_iter().collect()));
639
640 let trait_decl = translated.trait_decls.get(relevant_tref.id)?;
642 let vtable_ref = trait_decl
643 .vtable
644 .clone()?
645 .substitute_with_self(&relevant_tref.generics, &TraitRefKind::Dyn);
646 Some(vtable_ref)
647 }
648}
649
650impl From<LiteralTy> for Ty {
651 fn from(value: LiteralTy) -> Self {
652 TyKind::Literal(value).into_ty()
653 }
654}
655
656impl From<TyKind> for Ty {
657 fn from(kind: TyKind) -> Ty {
658 kind.into_ty()
659 }
660}
661
662impl std::ops::Deref for Ty {
664 type Target = TyKind;
665
666 fn deref(&self) -> &Self::Target {
667 self.kind()
668 }
669}