1use super::translate_ctx::*;
2use charon_lib::ast::*;
3use charon_lib::ids::Vector;
4use core::convert::*;
5use hax::{HasOwnerId, HasParamEnv, Visibility};
6use itertools::Itertools;
7
8impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
9 pub(crate) fn translate_region(
11 &mut self,
12 span: Span,
13 region: &hax::Region,
14 ) -> Result<Region, Error> {
15 use hax::RegionKind::*;
16 match ®ion.kind {
17 ReErased => Ok(Region::Erased),
18 ReStatic => Ok(Region::Static),
19 ReBound(hax::BoundVarIndexKind::Bound(id), br) => {
20 Ok(match self.lookup_bound_region(span, *id, br.var) {
21 Ok(var) => Region::Var(var),
22 Err(_) => Region::Erased,
23 })
24 }
25 ReEarlyParam(region) => Ok(match self.lookup_early_region(span, region) {
26 Ok(var) => Region::Var(var),
27 Err(_) => Region::Erased,
28 }),
29 ReVar(..) | RePlaceholder(..) => {
30 raise_error!(
32 self,
33 span,
34 "Should not exist outside of type inference: {region:?}"
35 )
36 }
37 ReBound(..) | ReLateParam(..) | ReError(..) => {
38 raise_error!(self, span, "Unexpected region kind: {region:?}")
39 }
40 }
41 }
42
43 pub(crate) fn translate_hax_int_ty(int_ty: &hax::IntTy) -> IntTy {
44 match int_ty {
45 hax::IntTy::Isize => IntTy::Isize,
46 hax::IntTy::I8 => IntTy::I8,
47 hax::IntTy::I16 => IntTy::I16,
48 hax::IntTy::I32 => IntTy::I32,
49 hax::IntTy::I64 => IntTy::I64,
50 hax::IntTy::I128 => IntTy::I128,
51 }
52 }
53
54 pub(crate) fn translate_hax_uint_ty(uint_ty: &hax::UintTy) -> UIntTy {
55 use hax::UintTy;
56 match uint_ty {
57 UintTy::Usize => UIntTy::Usize,
58 UintTy::U8 => UIntTy::U8,
59 UintTy::U16 => UIntTy::U16,
60 UintTy::U32 => UIntTy::U32,
61 UintTy::U64 => UIntTy::U64,
62 UintTy::U128 => UIntTy::U128,
63 }
64 }
65
66 #[tracing::instrument(skip(self, span))]
75 pub(crate) fn translate_ty(&mut self, span: Span, hax_ty: &hax::Ty) -> Result<Ty, Error> {
76 if let Some(ty) = self
77 .innermost_binder()
78 .type_trans_cache
79 .get(&hax_ty)
80 .cloned()
81 {
82 return Ok(ty);
83 }
84 let ty = self
86 .translate_ty_inner(span, hax_ty)
87 .unwrap_or_else(|e| TyKind::Error(e.msg).into_ty());
88 self.innermost_binder_mut()
89 .type_trans_cache
90 .insert(hax_ty.clone(), ty.clone());
91 Ok(ty)
92 }
93
94 fn translate_ty_inner(&mut self, span: Span, ty: &hax::Ty) -> Result<Ty, Error> {
95 trace!("{:?}", ty);
96 let kind = match ty.kind() {
97 hax::TyKind::Bool => TyKind::Literal(LiteralTy::Bool),
98 hax::TyKind::Char => TyKind::Literal(LiteralTy::Char),
99 hax::TyKind::Int(int_ty) => {
100 TyKind::Literal(LiteralTy::Int(Self::translate_hax_int_ty(int_ty)))
101 }
102 hax::TyKind::Uint(uint_ty) => {
103 TyKind::Literal(LiteralTy::UInt(Self::translate_hax_uint_ty(uint_ty)))
104 }
105 hax::TyKind::Float(float_ty) => {
106 use hax::FloatTy;
107 TyKind::Literal(LiteralTy::Float(match float_ty {
108 FloatTy::F16 => types::FloatTy::F16,
109 FloatTy::F32 => types::FloatTy::F32,
110 FloatTy::F64 => types::FloatTy::F64,
111 FloatTy::F128 => types::FloatTy::F128,
112 }))
113 }
114 hax::TyKind::Never => TyKind::Never,
115
116 hax::TyKind::Alias(alias) => match &alias.kind {
117 hax::AliasKind::Projection {
118 impl_expr,
119 assoc_item,
120 } => {
121 let trait_ref = self.translate_trait_impl_expr(span, impl_expr)?;
122 let name = self.t_ctx.translate_trait_item_name(&assoc_item.def_id)?;
123 TyKind::TraitType(trait_ref, name)
124 }
125 hax::AliasKind::Opaque { hidden_ty, .. } => {
126 return self.translate_ty(span, hidden_ty);
127 }
128 _ => {
129 raise_error!(self, span, "Unsupported alias type: {:?}", alias.kind)
130 }
131 },
132
133 hax::TyKind::Adt(item) => {
134 let tref = self.translate_type_decl_ref(span, item)?;
135 TyKind::Adt(tref)
136 }
137 hax::TyKind::Str => {
138 let tref = TypeDeclRef::new(TypeId::Builtin(BuiltinTy::Str), GenericArgs::empty());
139 TyKind::Adt(tref)
140 }
141 hax::TyKind::Array(item_ref) => {
142 let args = self.translate_generic_args(span, &item_ref.generic_args, &[])?;
143 let tref = TypeDeclRef::new(TypeId::Builtin(BuiltinTy::Array), args);
144 TyKind::Adt(tref)
145 }
146 hax::TyKind::Slice(item_ref) => {
147 let args = self.translate_generic_args(span, &item_ref.generic_args, &[])?;
148 let tref = TypeDeclRef::new(TypeId::Builtin(BuiltinTy::Slice), args);
149 TyKind::Adt(tref)
150 }
151 hax::TyKind::Tuple(item_ref) => {
152 let args = self.translate_generic_args(span, &item_ref.generic_args, &[])?;
153 let tref = TypeDeclRef::new(TypeId::Tuple, args);
154 TyKind::Adt(tref)
155 }
156 hax::TyKind::Ref(region, ty, mutability) => {
157 trace!("Ref");
158
159 let region = self.translate_region(span, region)?;
160 let ty = self.translate_ty(span, ty)?;
161 let kind = if *mutability {
162 RefKind::Mut
163 } else {
164 RefKind::Shared
165 };
166 TyKind::Ref(region, ty, kind)
167 }
168 hax::TyKind::RawPtr(ty, mutbl) => {
169 trace!("RawPtr: {:?}", (ty, mutbl));
170 let ty = self.translate_ty(span, ty)?;
171 let kind = if *mutbl {
172 RefKind::Mut
173 } else {
174 RefKind::Shared
175 };
176 TyKind::RawPtr(ty, kind)
177 }
178
179 hax::TyKind::Param(param) => {
180 match self.lookup_type_var(span, param) {
188 Ok(var) => TyKind::TypeVar(var),
189 Err(err) => TyKind::Error(err.msg),
190 }
191 }
192
193 hax::TyKind::Foreign(item) => {
194 let tref = self.translate_type_decl_ref(span, item)?;
195 TyKind::Adt(tref)
196 }
197
198 hax::TyKind::Arrow(sig) => {
199 trace!("Arrow");
200 trace!("bound vars: {:?}", sig.bound_vars);
201 let sig = self.translate_fun_sig(span, sig)?;
202 TyKind::FnPtr(sig)
203 }
204 hax::TyKind::FnDef { item, .. } => {
205 let fnref = self.translate_fn_ptr(span, item, TransItemSourceKind::Fun)?;
206 TyKind::FnDef(fnref)
207 }
208 hax::TyKind::Closure(args) => {
209 let tref = self.translate_closure_type_ref(span, args)?;
210 TyKind::Adt(tref)
211 }
212
213 hax::TyKind::Dynamic(self_ty, preds, region) => {
214 self.check_no_monomorphize(span)?;
215 let pred = self.translate_existential_predicates(span, self_ty, preds, region)?;
216 if let hax::ClauseKind::Trait(trait_predicate) =
217 preds.predicates[0].0.kind.hax_skip_binder_ref()
218 {
219 if self.trait_is_dyn_compatible(&trait_predicate.trait_ref.def_id)? {
223 let _: TypeDeclId = self.register_item(
226 span,
227 &trait_predicate.trait_ref,
228 TransItemSourceKind::VTable,
229 );
230 }
231 }
232 TyKind::DynTrait(pred)
233 }
234
235 hax::TyKind::Infer(_) => {
236 raise_error!(self, span, "Unsupported type: infer type")
237 }
238 hax::TyKind::Coroutine(..) => {
239 raise_error!(self, span, "Coroutine types are not supported yet")
240 }
241 hax::TyKind::Bound(_, _) => {
242 raise_error!(self, span, "Unexpected type kind: bound")
243 }
244 hax::TyKind::Placeholder(_) => {
245 raise_error!(self, span, "Unsupported type: placeholder")
246 }
247
248 hax::TyKind::Error => {
249 raise_error!(self, span, "Type checking error")
250 }
251 hax::TyKind::Todo(s) => {
252 raise_error!(self, span, "Unsupported type: {:?}", s)
253 }
254 };
255 Ok(kind.into_ty())
256 }
257
258 pub fn translate_fun_sig(
259 &mut self,
260 span: Span,
261 sig: &hax::Binder<hax::TyFnSig>,
262 ) -> Result<RegionBinder<(Vec<Ty>, Ty)>, Error> {
263 self.translate_region_binder(span, sig, |ctx, sig| {
264 let inputs = sig
265 .inputs
266 .iter()
267 .map(|x| ctx.translate_ty(span, x))
268 .try_collect()?;
269 let output = ctx.translate_ty(span, &sig.output)?;
270 Ok((inputs, output))
271 })
272 }
273
274 pub fn translate_generic_args(
276 &mut self,
277 span: Span,
278 substs: &[hax::GenericArg],
279 trait_refs: &[hax::ImplExpr],
280 ) -> Result<GenericArgs, Error> {
281 use hax::GenericArg::*;
282 trace!("{:?}", substs);
283
284 let mut regions = Vector::new();
285 let mut types = Vector::new();
286 let mut const_generics = Vector::new();
287 for param in substs {
288 match param {
289 Type(param_ty) => {
290 types.push(self.translate_ty(span, param_ty)?);
291 }
292 Lifetime(region) => {
293 regions.push(self.translate_region(span, region)?);
294 }
295 Const(c) => {
296 const_generics.push(self.translate_constant_expr_to_const_generic(span, c)?);
297 }
298 }
299 }
300 let trait_refs = self.translate_trait_impl_exprs(span, trait_refs)?;
301
302 Ok(GenericArgs {
303 regions,
304 types,
305 const_generics,
306 trait_refs,
307 })
308 }
309
310 pub fn append_late_bound_to_generics(
312 &mut self,
313 span: Span,
314 generics: GenericArgs,
315 late_bound: Option<hax::Binder<()>>,
316 ) -> Result<RegionBinder<GenericArgs>, Error> {
317 let late_bound = late_bound.unwrap_or(hax::Binder {
318 value: (),
319 bound_vars: vec![],
320 });
321 self.translate_region_binder(span, &late_bound, |ctx, _| {
322 Ok(generics
323 .move_under_binder()
324 .concat(&ctx.innermost_binder().params.identity_args()))
325 })
326 }
327
328 pub(crate) fn recognize_builtin_type(
330 &mut self,
331 item: &hax::ItemRef,
332 ) -> Result<Option<BuiltinTy>, Error> {
333 let def = self.hax_def(item)?;
334 let ty = if def.lang_item.as_deref() == Some("owned_box") && !self.t_ctx.options.raw_boxes {
335 Some(BuiltinTy::Box)
336 } else {
337 None
338 };
339 Ok(ty)
340 }
341
342 pub fn translate_ptr_metadata(
346 &mut self,
347 span: Span,
348 item: &hax::ItemRef,
349 ) -> Result<PtrMetadata, Error> {
350 use rustc_middle::ty;
352 let tcx = self.t_ctx.tcx;
353 let rdefid = item.def_id.as_rust_def_id().unwrap();
354 let hax_state = &self.hax_state_with_id;
355 let ty_env = hax_state.typing_env();
356 let ty = tcx
357 .type_of(rdefid)
358 .instantiate(tcx, item.rustc_args(hax_state));
359
360 let tail_ty = tcx.struct_tail_raw(
362 ty,
363 &rustc_middle::traits::ObligationCause::dummy(),
364 |ty| tcx.try_normalize_erasing_regions(ty_env, ty).unwrap_or(ty),
365 || {},
366 );
367 let hax_ty: hax::Ty = self.t_ctx.catch_sinto(hax_state, span, &tail_ty)?;
368
369 let everything_is_sized = self.t_ctx.options.hide_marker_traits;
371 let ret = match tail_ty.kind() {
372 _ if everything_is_sized || tail_ty.is_sized(tcx, ty_env) => PtrMetadata::None,
373 ty::Str | ty::Slice(..) => PtrMetadata::Length,
374 ty::Dynamic(..) => match hax_ty.kind() {
375 hax::TyKind::Dynamic(_, preds, _) => {
376 let vtable = self
377 .translate_region_binder(
378 span,
379 &preds.predicates[0].0.kind,
380 |ctx, kind: &hax::ClauseKind| {
381 let hax::ClauseKind::Trait(trait_predicate) = kind else {
382 unreachable!()
383 };
384 Ok(ctx
385 .translate_vtable_struct_ref(span, &trait_predicate.trait_ref)?
386 .unwrap())
387 },
388 )?
389 .erase();
390 PtrMetadata::VTable(vtable)
391 }
392 _ => unreachable!("Unexpected hax type {hax_ty:?} for dynamic type: {ty:?}"),
393 },
394 ty::Param(..) => PtrMetadata::InheritFrom(self.translate_ty(span, &hax_ty)?),
395 ty::Placeholder(..) | ty::Infer(..) | ty::Bound(..) => {
396 panic!(
397 "We should never encounter a placeholder, infer, or bound type from ptr_metadata translation. Got: {tail_ty:?}"
398 )
399 }
400 _ => PtrMetadata::None,
401 };
402
403 Ok(ret)
404 }
405
406 #[tracing::instrument(skip(self))]
411 pub fn translate_layout(&self, item: &hax::ItemRef) -> Option<Layout> {
412 use rustc_abi as r_abi;
413
414 fn translate_variant_layout(
415 variant_layout: &r_abi::LayoutData<r_abi::FieldIdx, r_abi::VariantIdx>,
416 tag: Option<ScalarValue>,
417 ) -> VariantLayout {
418 let field_offsets = match &variant_layout.fields {
419 r_abi::FieldsShape::Arbitrary { offsets, .. } => {
420 offsets.iter().map(|o| o.bytes()).collect()
421 }
422 r_abi::FieldsShape::Primitive | r_abi::FieldsShape::Union(_) => Vector::default(),
423 r_abi::FieldsShape::Array { .. } => panic!("Unexpected layout shape"),
424 };
425 VariantLayout {
426 field_offsets,
427 uninhabited: variant_layout.is_uninhabited(),
428 tag,
429 }
430 }
431
432 fn translate_primitive_int(int_ty: r_abi::Integer, signed: bool) -> IntegerTy {
433 if signed {
434 IntegerTy::Signed(match int_ty {
435 r_abi::Integer::I8 => IntTy::I8,
436 r_abi::Integer::I16 => IntTy::I16,
437 r_abi::Integer::I32 => IntTy::I32,
438 r_abi::Integer::I64 => IntTy::I64,
439 r_abi::Integer::I128 => IntTy::I128,
440 })
441 } else {
442 IntegerTy::Unsigned(match int_ty {
443 r_abi::Integer::I8 => UIntTy::U8,
444 r_abi::Integer::I16 => UIntTy::U16,
445 r_abi::Integer::I32 => UIntTy::U32,
446 r_abi::Integer::I64 => UIntTy::U64,
447 r_abi::Integer::I128 => UIntTy::U128,
448 })
449 }
450 }
451
452 let tcx = self.t_ctx.tcx;
453 let rdefid = item.def_id.as_rust_def_id().unwrap();
454 let hax_state = self.hax_state_with_id();
455 assert_eq!(hax_state.owner_id(), rdefid);
456 let ty_env = hax_state.typing_env();
457 let ty = tcx
458 .type_of(rdefid)
459 .instantiate(tcx, item.rustc_args(hax_state));
460 let pseudo_input = ty_env.as_query_input(ty);
461
462 let layout = tcx.layout_of(pseudo_input).ok()?.layout;
464 let (size, align) = if layout.is_sized() {
465 (
466 Some(layout.size().bytes()),
467 Some(layout.align().abi.bytes()),
468 )
469 } else {
470 (None, None)
471 };
472
473 let discriminant_layout = match layout.variants() {
475 r_abi::Variants::Multiple {
476 tag,
477 tag_encoding,
478 tag_field,
479 ..
480 } => {
481 let r_abi::FieldsShape::Arbitrary { offsets, .. } = layout.fields() else {
483 unreachable!()
484 };
485
486 let tag_ty = match tag.primitive() {
487 r_abi::Primitive::Int(int_ty, signed) => {
488 translate_primitive_int(int_ty, signed)
489 }
490 r_abi::Primitive::Pointer(_) => IntegerTy::Signed(IntTy::Isize),
492 r_abi::Primitive::Float(_) => {
493 unreachable!()
494 }
495 };
496
497 let encoding = match tag_encoding {
498 r_abi::TagEncoding::Direct => TagEncoding::Direct,
499 r_abi::TagEncoding::Niche {
500 untagged_variant, ..
501 } => TagEncoding::Niche {
502 untagged_variant: VariantId::from_usize(r_abi::VariantIdx::as_usize(
503 *untagged_variant,
504 )),
505 },
506 };
507 offsets.get(*tag_field).map(|s| DiscriminantLayout {
508 offset: r_abi::Size::bytes(*s),
509 tag_ty,
510 encoding,
511 })
512 }
513 r_abi::Variants::Single { .. } | r_abi::Variants::Empty => None,
514 };
515
516 let mut variant_layouts: Vector<VariantId, VariantLayout> = Vector::new();
517
518 match layout.variants() {
519 r_abi::Variants::Multiple { variants, .. } => {
520 let tag_ty = discriminant_layout
521 .as_ref()
522 .expect("No discriminant layout for enum?")
523 .tag_ty;
524 let ptr_size = self.t_ctx.translated.target_information.target_pointer_size;
525 let tag_size = r_abi::Size::from_bytes(tag_ty.target_size(ptr_size));
526
527 for (id, variant_layout) in variants.iter_enumerated() {
528 let tag = if variant_layout.is_uninhabited() {
529 None
530 } else {
531 tcx.tag_for_variant(ty_env.as_query_input((ty, id)))
532 .map(|s| match tag_ty {
533 IntegerTy::Signed(int_ty) => {
534 ScalarValue::from_int(ptr_size, int_ty, s.to_int(tag_size))
535 .unwrap()
536 }
537 IntegerTy::Unsigned(uint_ty) => {
538 ScalarValue::from_uint(ptr_size, uint_ty, s.to_uint(tag_size))
539 .unwrap()
540 }
541 })
542 };
543 variant_layouts.push(translate_variant_layout(variant_layout, tag));
544 }
545 }
546 r_abi::Variants::Single { index } => {
547 if let r_abi::FieldsShape::Arbitrary { .. } = layout.fields() {
548 let n_variants = match ty.kind() {
549 _ if let Some(range) = ty.variant_range(tcx) => range.end.index(),
550 _ => 1,
551 };
552 variant_layouts = (0..n_variants)
554 .map(|_| VariantLayout {
555 field_offsets: Vector::default(),
556 uninhabited: true,
557 tag: None,
558 })
559 .collect();
560 variant_layouts[index.index()] = translate_variant_layout(&layout, None);
561 }
562 }
563 r_abi::Variants::Empty => {}
564 }
565
566 Some(Layout {
567 size,
568 align,
569 discriminant_layout,
570 uninhabited: layout.is_uninhabited(),
571 variant_layouts,
572 })
573 }
574
575 pub fn generate_naive_layout(&self, span: Span, ty: &TypeDeclKind) -> Result<Layout, Error> {
577 match ty {
578 TypeDeclKind::Struct(fields) => {
579 let mut size = 0;
580 let mut align = 0;
581 let ptr_size = self.t_ctx.translated.target_information.target_pointer_size;
582 let field_offsets = fields.map_ref(|field| {
583 let offset = size;
584 let size_of_ty = match field.ty.kind() {
585 TyKind::Literal(literal_ty) => literal_ty.target_size(ptr_size) as u64,
586 TyKind::Ref(..) | TyKind::RawPtr(..) | TyKind::FnPtr(..) => ptr_size,
588 _ => panic!("Unsupported type for `generate_naive_layout`: {ty:?}"),
589 };
590 size += size_of_ty;
591 align = std::cmp::max(align, size);
593 offset
594 });
595
596 Ok(Layout {
597 size: Some(size),
598 align: Some(align),
599 discriminant_layout: None,
600 uninhabited: false,
601 variant_layouts: [VariantLayout {
602 field_offsets,
603 tag: None,
604 uninhabited: false,
605 }]
606 .into(),
607 })
608 }
609 _ => raise_error!(
610 self,
611 span,
612 "`generate_naive_layout` only supports structs at the moment"
613 ),
614 }
615 }
616
617 pub(crate) fn translate_adt_def(
623 &mut self,
624 trans_id: TypeDeclId,
625 def_span: Span,
626 item_meta: &ItemMeta,
627 def: &hax::FullDef,
628 ) -> Result<TypeDeclKind, Error> {
629 use hax::AdtKind;
630 let hax::FullDefKind::Adt {
631 adt_kind, variants, ..
632 } = def.kind()
633 else {
634 unreachable!()
635 };
636
637 if item_meta.opacity.is_opaque() {
638 return Ok(TypeDeclKind::Opaque);
639 }
640
641 trace!("{}", trans_id);
642
643 let contents_are_public = match adt_kind {
648 AdtKind::Enum => true,
649 AdtKind::Struct | AdtKind::Union => {
650 error_assert!(self, def_span, variants.len() == 1);
652 variants[0]
653 .fields
654 .iter()
655 .all(|f| matches!(f.vis, Visibility::Public))
656 }
657 _ => unreachable!(),
659 };
660
661 if item_meta
662 .opacity
663 .with_content_visibility(contents_are_public)
664 .is_opaque()
665 {
666 return Ok(TypeDeclKind::Opaque);
667 }
668
669 let mut translated_variants: Vector<VariantId, Variant> = Default::default();
671 for (i, var_def) in variants.iter().enumerate() {
672 trace!("variant {i}: {var_def:?}");
673
674 let mut fields: Vector<FieldId, Field> = Default::default();
675 let mut have_names: Option<bool> = None;
678 for (j, field_def) in var_def.fields.iter().enumerate() {
679 trace!("variant {i}: field {j}: {field_def:?}");
680 let field_span = self.t_ctx.translate_span_from_hax(&field_def.span);
681 let ty = self.translate_ty(field_span, &field_def.ty)?;
683 let field_full_def =
684 self.hax_def(&def.this().with_def_id(self.hax_state(), &field_def.did))?;
685 let field_attrs = self.t_ctx.translate_attr_info(&field_full_def);
686
687 let field_name = field_def.name.clone();
689 match &have_names {
691 None => {
692 have_names = match &field_name {
693 None => Some(false),
694 Some(_) => Some(true),
695 }
696 }
697 Some(b) => {
698 error_assert!(self, field_span, *b == field_name.is_some());
699 }
700 };
701
702 let field = Field {
704 span: field_span,
705 attr_info: field_attrs,
706 name: field_name.clone(),
707 ty,
708 };
709 fields.push(field);
710 }
711
712 let discriminant = self.translate_discriminant(def_span, &var_def.discr_val)?;
713 let variant_span = self.t_ctx.translate_span_from_hax(&var_def.span);
714 let variant_name = var_def.name.clone();
715 let variant_full_def =
716 self.hax_def(&def.this().with_def_id(self.hax_state(), &var_def.def_id))?;
717 let variant_attrs = self.t_ctx.translate_attr_info(&variant_full_def);
718
719 let mut variant = Variant {
720 span: variant_span,
721 attr_info: variant_attrs,
722 name: variant_name,
723 fields,
724 discriminant,
725 };
726 if variant.attr_info.rename.is_none() {
728 let prefix = item_meta
729 .attr_info
730 .attributes
731 .iter()
732 .filter_map(|a| a.as_variants_prefix())
733 .next()
734 .map(|attr| attr.as_str());
735 let suffix = item_meta
736 .attr_info
737 .attributes
738 .iter()
739 .filter_map(|a| a.as_variants_suffix())
740 .next()
741 .map(|attr| attr.as_str());
742 if prefix.is_some() || suffix.is_some() {
743 let prefix = prefix.unwrap_or_default();
744 let suffix = suffix.unwrap_or_default();
745 let name = &variant.name;
746 variant.attr_info.rename = Some(format!("{prefix}{name}{suffix}"));
747 }
748 }
749 translated_variants.push(variant);
750 }
751
752 let type_def_kind: TypeDeclKind = match adt_kind {
754 AdtKind::Struct => TypeDeclKind::Struct(translated_variants[0].fields.clone()),
755 AdtKind::Enum => TypeDeclKind::Enum(translated_variants),
756 AdtKind::Union => TypeDeclKind::Union(translated_variants[0].fields.clone()),
757 _ => unreachable!(),
759 };
760
761 Ok(type_def_kind)
762 }
763
764 fn translate_discriminant(
765 &mut self,
766 def_span: Span,
767 discr: &hax::DiscriminantValue,
768 ) -> Result<Literal, Error> {
769 let ty = self.translate_ty(def_span, &discr.ty)?;
770 let lit_ty = ty.kind().as_literal().unwrap();
771 match Literal::from_bits(lit_ty, discr.val) {
772 Some(lit) => Ok(lit),
773 None => raise_error!(self, def_span, "unexpected discriminant type: {ty:?}",),
774 }
775 }
776
777 pub fn translate_repr_options(&mut self, hax_repr_options: &hax::ReprOptions) -> ReprOptions {
778 let repr_algo = if hax_repr_options.flags.is_c {
779 ReprAlgorithm::C
780 } else {
781 ReprAlgorithm::Rust
782 };
783
784 let align_mod = if let Some(align) = &hax_repr_options.align {
785 Some(AlignmentModifier::Align(align.bytes))
786 } else if let Some(pack) = &hax_repr_options.pack {
787 Some(AlignmentModifier::Pack(pack.bytes))
788 } else {
789 None
790 };
791
792 ReprOptions {
793 transparent: hax_repr_options.flags.is_transparent,
794 explicit_discr_type: hax_repr_options.int_specified,
795 repr_algo,
796 align_modif: align_mod,
797 }
798 }
799}