1use crate::ast::*;
2use derive_generic_visitor::*;
3use macros::{EnumAsGetters, EnumIsA, EnumToGetters, VariantIndexArity, VariantName};
4use serde::{Deserialize, Serialize};
5use serde_state::{DeserializeState, SerializeState};
6use std::ops::DerefMut;
7
8#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
12#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
13#[serde_state(state_implements = DedupSerializerState)] pub struct Ty(pub HashConsed<WithCachedTypeInfo<TyKind>>);
15
16#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
20#[derive(VariantName, EnumIsA, EnumAsGetters, EnumToGetters, VariantIndexArity)]
21#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
22#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
23pub enum TyKind {
24 Scalar(ScalarTy),
26 Array(Ty, ConstantExpr, Option<TraitRef>),
29 Slice(Ty, Option<TraitRef>),
32 Adt(TypeDeclRef),
34 Ref(Region, Ty, RefKind),
36 RawPtr(Ty, RefKind),
38 FnDef(RegionBinder<FnPtr>),
58 FnPtr(RegionBinder<FunSig>),
64 DynTrait(DynPredicate),
67 Pattern(Ty, TypePattern),
70 Never,
72
73 #[cfg_attr(feature = "charon_on_charon", charon::rename("TVar"))]
75 TypeVar(TypeDbVar),
76 TraitType(TraitRef, AssocTypeId, GenericArgs),
78 PtrMetadata(Ty),
81
82 Error(String),
84}
85
86#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
88#[derive(VariantName, EnumIsA, EnumAsGetters, VariantIndexArity)]
89#[derive(
90 Serialize,
91 Deserialize,
92 SerializeState,
93 DeserializeState,
94 Drive,
95 DriveMut,
96 DriveTwo
97)]
98#[cfg_attr(feature = "charon_on_charon", charon::rename("ScalarType"))]
99#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
100#[serde_state(stateless)]
101pub enum ScalarTy {
102 Integer(IntegerTy),
103 Float(FloatTy),
104 Bool,
105 Char,
106}
107
108#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
109#[derive(EnumIsA, VariantName)]
110#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
111#[cfg_attr(feature = "charon_on_charon", charon::rename("IntegerType"))]
112pub enum IntegerTy {
113 Signed(IntTy),
114 Unsigned(UIntTy),
115}
116
117#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
118#[derive(EnumIsA, VariantName)]
119#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
120pub enum IntTy {
121 Isize,
122 I8,
123 I16,
124 I32,
125 I64,
126 I128,
127}
128
129#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
130#[derive(EnumIsA, VariantName)]
131#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
132pub enum UIntTy {
133 Usize,
134 U8,
135 U16,
136 U32,
137 U64,
138 U128,
139}
140
141#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
142#[derive(EnumIsA, VariantName)]
143#[derive(Serialize, Deserialize, Drive, DriveMut, DriveTwo)]
144#[cfg_attr(feature = "charon_on_charon", charon::rename("FloatType"))]
145pub enum FloatTy {
146 F16,
147 F32,
148 F64,
149 F128,
150}
151
152#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
154#[derive(EnumIsA, EnumAsGetters, VariantName)]
155#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
156#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("T"))]
157pub enum BuiltinAdt {
158 Tuple,
160 Box,
162 Str,
164}
165
166#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
167#[derive(VariantName, EnumIsA)]
168#[derive(
169 Serialize,
170 Deserialize,
171 SerializeState,
172 DeserializeState,
173 Drive,
174 DriveMut,
175 DriveTwo
176)]
177#[cfg_attr(feature = "charon_on_charon", charon::variants_prefix("R"))]
178#[serde_state(stateless)]
179pub enum RefKind {
180 Mut,
181 Shared,
182}
183
184#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
186#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
187pub struct DynPredicate {
188 pub binder: Binder<Ty>,
195}
196
197#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
199#[derive(VariantName, EnumIsA)]
200#[derive(SerializeState, DeserializeState, Drive, DriveMut, DriveTwo)]
201#[serde_state(state_implements = DedupSerializerState)] pub enum TypePattern {
203 Range(ConstantExpr, ConstantExpr),
204 OrPattern(Vec<TypePattern>),
205 NotNull,
206}
207
208macro_rules! static_type {
209 ($e:expr) => {{
210 use std::sync::LazyLock;
211 static TY: LazyLock<Ty> = LazyLock::new(|| $e.into_ty());
212 TY.clone()
213 }};
214}
215
216impl Ty {
217 pub fn new(kind: TyKind) -> Self {
218 Ty(HashConsed::new(WithCachedTypeInfo::new(kind)))
219 }
220
221 pub fn kind(&self) -> &TyKind {
222 self.0.inner()
223 }
224
225 pub fn as_mut(&mut self) -> impl DerefMut<Target = TyKind> {
227 struct TyMutRef<T: DerefMut<Target = WithCachedTypeInfo<TyKind>>>(T);
228
229 impl<T: DerefMut<Target = WithCachedTypeInfo<TyKind>>> std::ops::Deref for TyMutRef<T> {
230 type Target = TyKind;
231 fn deref(&self) -> &Self::Target {
232 &self.0
233 }
234 }
235 impl<T: DerefMut<Target = WithCachedTypeInfo<TyKind>>> DerefMut for TyMutRef<T> {
236 fn deref_mut(&mut self) -> &mut Self::Target {
237 self.0.value_mut()
238 }
239 }
240
241 impl<T: DerefMut<Target = WithCachedTypeInfo<TyKind>>> Drop for TyMutRef<T> {
242 fn drop(&mut self) {
243 self.0.recompute_type_info();
244 }
245 }
246
247 TyMutRef(self.0.as_mut())
248 }
249 pub fn with_kind_mut<R>(&mut self, f: impl FnOnce(&mut TyKind) -> R) -> R {
250 f(&mut self.as_mut())
251 }
252
253 pub fn mk_unit() -> Ty {
255 static_type!(TyKind::Adt(TypeDeclRef {
256 id: TypeDeclId::UNIT,
257 generics: Box::new(GenericArgs::empty()),
258 builtin: Some(BuiltinAdt::Tuple),
259 }))
260 }
261
262 pub fn mk_bool() -> Ty {
263 static_type!(TyKind::Scalar(ScalarTy::Bool))
264 }
265
266 pub fn mk_u8() -> Ty {
267 static_type!(TyKind::Scalar(ScalarTy::Integer(IntegerTy::Unsigned(
268 UIntTy::U8
269 ))))
270 }
271
272 pub fn mk_usize() -> Ty {
273 static_type!(TyKind::Scalar(ScalarTy::Integer(IntegerTy::Unsigned(
274 UIntTy::Usize
275 ))))
276 }
277
278 pub fn mk_array(ty: Ty, len: ConstantExpr, ty_is_sized: Option<TraitRef>) -> Ty {
279 TyKind::Array(ty, len, ty_is_sized).into_ty()
280 }
281
282 pub fn mk_slice(ty: Ty, ty_is_sized: Option<TraitRef>) -> Ty {
283 TyKind::Slice(ty, ty_is_sized).into_ty()
284 }
285
286 pub fn is_unit(&self) -> bool {
288 *self == Ty::mk_unit()
289 }
290
291 pub fn get_ptr_metadata(&self, translated: &TranslatedCrate) -> PtrMetadata {
292 let ty_decls = &translated.type_decls;
293 match self.kind() {
294 TyKind::Pattern(ty, _) => ty.get_ptr_metadata(translated),
295 TyKind::Adt(ty_ref) => {
296 let Some(decl) = ty_decls.get(ty_ref.id) else {
300 return PtrMetadata::InheritFrom(self.clone());
301 };
302 match decl.ptr_metadata.clone().substitute(&ty_ref.generics) {
303 PtrMetadata::InheritFrom(ty) => ty.get_ptr_metadata(translated),
305 meta => meta,
307 }
308 }
309 TyKind::DynTrait(pred) => match pred.vtable_ref(translated) {
310 Some(vtable) => PtrMetadata::VTable(vtable),
311 None => PtrMetadata::InheritFrom(self.clone()),
312 },
313 TyKind::Slice(..) => PtrMetadata::Length,
315 TyKind::TraitType(..) | TyKind::TypeVar(_) => PtrMetadata::InheritFrom(self.clone()),
316 TyKind::Scalar(_)
317 | TyKind::Never
318 | TyKind::Ref(..)
319 | TyKind::RawPtr(..)
320 | TyKind::FnPtr(..)
321 | TyKind::FnDef(..)
322 | TyKind::Array(..)
323 | TyKind::Error(_) => PtrMetadata::None,
324 TyKind::PtrMetadata(_) => PtrMetadata::None,
326 }
327 }
328
329 pub fn as_tuple_fields(&self, translated: &TranslatedCrate) -> Vec<Ty> {
332 let Some(tref) = self.as_adt().filter(|tref| tref.is_tuple()) else {
333 unreachable!("as_tuple_fields called on non-tuple type {:?}", self);
334 };
335
336 let is_instantiated = translated
340 .item_names
341 .get(&ItemId::Type(tref.id))
342 .map(|name| name.name.iter().any(|elem| elem.is_instantiated()))
343 .unwrap_or(false);
344 if !is_instantiated {
345 return tref.generics.types.as_vec().clone();
346 }
347
348 translated
349 .type_decls
350 .get(tref.id)
351 .and_then(|decl| decl.kind.as_struct())
352 .expect("the declaration of specialized tuple {tref:?} is missing")
353 .iter()
354 .map(|f| f.ty.clone().substitute(&tref.generics))
355 .collect()
356 }
357
358 pub fn as_adt(&self) -> Option<&TypeDeclRef> {
359 self.kind().as_adt()
360 }
361}
362
363impl TyKind {
364 pub fn into_ty(self) -> Ty {
365 Ty::new(self)
366 }
367
368 pub fn is_usize(&self) -> bool {
369 self.as_scalar().is_some_and(|s| s.is_usize())
370 }
371
372 pub fn is_unsigned_scalar(&self) -> bool {
373 match self {
374 TyKind::Scalar(ScalarTy::Integer(IntegerTy::Unsigned(_))) => true,
375 TyKind::Pattern(ty, _) => ty.is_unsigned_scalar(),
376 _ => false,
377 }
378 }
379
380 pub fn is_signed_scalar(&self) -> bool {
381 match self {
382 TyKind::Scalar(ScalarTy::Integer(IntegerTy::Signed(_))) => true,
383 TyKind::Pattern(ty, _) => ty.is_signed_scalar(),
384 _ => false,
385 }
386 }
387
388 pub fn is_bool(&self) -> bool {
389 matches!(self, TyKind::Scalar(ScalarTy::Bool))
390 }
391
392 pub fn is_str(&self) -> bool {
393 match self {
394 TyKind::Adt(ty_ref) => ty_ref.is_str(),
395 _ => false,
396 }
397 }
398
399 pub fn is_box(&self) -> bool {
401 match self {
402 TyKind::Adt(ty_ref) => ty_ref.is_box(),
403 _ => false,
404 }
405 }
406
407 pub fn is_tuple(&self) -> bool {
408 match self {
409 TyKind::Adt(ty_ref) => ty_ref.is_tuple(),
410 _ => false,
411 }
412 }
413
414 pub fn as_adt_id(&self) -> Option<TypeDeclId> {
415 self.as_adt().map(|a| a.id)
416 }
417
418 pub fn as_box(&self) -> Option<&Ty> {
419 match self {
420 TyKind::Adt(ty_ref) if ty_ref.is_box() => Some(&ty_ref.generics.types[0]),
421 _ => None,
422 }
423 }
424
425 pub fn as_box_mut(&mut self) -> Option<&mut Ty> {
426 match self {
427 TyKind::Adt(ty_ref) if ty_ref.is_box() => Some(&mut ty_ref.generics.types[0]),
428 _ => None,
429 }
430 }
431
432 pub fn builtin_deref<'a>(&'a self, krate: &'a TranslatedCrate) -> Option<&'a Ty> {
433 match self {
434 TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => Some(ty),
435 TyKind::Adt(tref) if tref.is_box() => tref
436 .generics
437 .types
438 .first()
439 .or_else(|| krate.item_name(tref.id).mono_args()?.types.first()),
440
441 _ => None,
442 }
443 }
444
445 pub fn builtin_deref_mut(&mut self) -> Option<&mut Ty> {
446 match self {
447 TyKind::Ref(_, ty, _) | TyKind::RawPtr(ty, _) => Some(ty),
448 TyKind::Adt(ty_ref) if ty_ref.is_box() => Some(&mut ty_ref.generics.types[0]),
449 _ => None,
450 }
451 }
452
453 pub fn as_array_or_slice(&self) -> Option<&Ty> {
454 match self {
455 TyKind::Slice(ty, _) | TyKind::Array(ty, ..) => Some(ty),
456 _ => None,
457 }
458 }
459
460 pub fn as_array_or_slice_mut(&mut self) -> Option<&mut Ty> {
461 match self {
462 TyKind::Slice(ty, _) | TyKind::Array(ty, ..) => Some(ty),
463 _ => None,
464 }
465 }
466}
467
468impl IntegerTy {
469 pub fn to_unsigned(&self) -> Self {
470 match self {
471 IntegerTy::Signed(IntTy::Isize) => IntegerTy::Unsigned(UIntTy::Usize),
472 IntegerTy::Signed(IntTy::I8) => IntegerTy::Unsigned(UIntTy::U8),
473 IntegerTy::Signed(IntTy::I16) => IntegerTy::Unsigned(UIntTy::U16),
474 IntegerTy::Signed(IntTy::I32) => IntegerTy::Unsigned(UIntTy::U32),
475 IntegerTy::Signed(IntTy::I64) => IntegerTy::Unsigned(UIntTy::U64),
476 IntegerTy::Signed(IntTy::I128) => IntegerTy::Unsigned(UIntTy::U128),
477 _ => *self,
478 }
479 }
480
481 pub fn target_size(&self, ptr_size: ByteCount) -> usize {
484 match self {
485 IntegerTy::Signed(ty) => ty.target_size(ptr_size),
486 IntegerTy::Unsigned(ty) => ty.target_size(ptr_size),
487 }
488 }
489}
490
491impl ScalarTy {
492 pub fn is_usize(&self) -> bool {
493 matches!(self, ScalarTy::Integer(IntegerTy::Unsigned(UIntTy::Usize)))
494 }
495
496 pub fn target_size(&self, ptr_size: ByteCount) -> usize {
499 match self {
500 ScalarTy::Integer(int_ty) => int_ty.target_size(ptr_size),
501 ScalarTy::Float(float_ty) => float_ty.target_size(),
502 ScalarTy::Char => 4,
503 ScalarTy::Bool => 1,
504 }
505 }
506}
507
508impl RefKind {
509 pub fn mutable(x: bool) -> Self {
510 if x { Self::Mut } else { Self::Shared }
511 }
512}
513
514impl DynPredicate {
515 pub fn vtable_ref(&self, translated: &TranslatedCrate) -> Option<TypeDeclRef> {
517 let dyn_ty = TyKind::DynTrait(self.clone()).into_ty();
518 let relevant_tref = self.binder.params.trait_clauses[0]
521 .trait_
522 .clone()
523 .erase()
524 .substitute(&GenericArgs::new_types([dyn_ty].into()));
525
526 let trait_decl = translated.trait_decls.get(relevant_tref.id)?;
528 let vtable_ref = trait_decl
529 .vtable
530 .clone()?
531 .substitute_with_self(&relevant_tref.generics, &TraitRefKind::Dyn);
532 Some(vtable_ref)
533 }
534}
535
536impl From<ScalarTy> for Ty {
537 fn from(value: ScalarTy) -> Self {
538 TyKind::Scalar(value).into_ty()
539 }
540}
541
542impl From<TyKind> for Ty {
543 fn from(kind: TyKind) -> Ty {
544 kind.into_ty()
545 }
546}
547
548impl std::ops::Deref for Ty {
550 type Target = WithCachedTypeInfo<TyKind>;
551 fn deref(&self) -> &Self::Target {
552 &self.0
553 }
554}
555
556unsafe impl Send for Ty {}