1use super::translate_bodies::BodyTransCtx;
2use super::translate_crate::*;
3use super::translate_ctx::*;
4use charon_lib::ast::*;
5use charon_lib::formatter::IntoFormatter;
6use charon_lib::pretty::FmtWithCtx;
7use derive_generic_visitor::Visitor;
8use itertools::Itertools;
9use std::mem;
10use std::ops::ControlFlow;
11
12impl<'tcx, 'ctx> TranslateCtx<'tcx> {
13 pub(crate) fn translate_item(&mut self, item_src: &TransItemSource) {
14 let trans_id = self.register_no_enqueue(&None, item_src);
15 let def_id = item_src.def_id();
16 if let Some(trans_id) = trans_id {
17 if self.translate_stack.contains(&trans_id) {
18 register_error!(
19 self,
20 Span::dummy(),
21 "Cycle detected while translating {def_id:?}! Stack: {:?}",
22 &self.translate_stack
23 );
24 return;
25 } else {
26 self.translate_stack.push(trans_id);
27 }
28 }
29 self.with_def_id(def_id, trans_id, |mut ctx| {
30 let span = ctx.def_span(def_id);
31 let res = {
33 let mut ctx = std::panic::AssertUnwindSafe(&mut ctx);
35 std::panic::catch_unwind(move || ctx.translate_item_aux(item_src, trans_id))
36 };
37 match res {
38 Ok(Ok(())) => return,
39 Ok(Err(_)) => {
41 register_error!(ctx, span, "Item `{def_id:?}` caused errors; ignoring.")
42 }
43 Err(_) => register_error!(
45 ctx,
46 span,
47 "Thread panicked when extracting item `{def_id:?}`."
48 ),
49 };
50 });
51 self.translate_stack.pop();
53 }
54
55 pub(crate) fn translate_item_aux(
56 &mut self,
57 item_src: &TransItemSource,
58 trans_id: Option<AnyTransId>,
59 ) -> Result<(), Error> {
60 let name = self.translate_name(item_src)?;
62 if let Some(trans_id) = trans_id {
63 self.translated.item_names.insert(trans_id, name.clone());
64 }
65 let opacity = self.opacity_for_name(&name);
66 if opacity.is_invisible() {
67 return Ok(());
69 }
70 let def = self.hax_def_for_item(&item_src.item)?;
71 let item_meta = self.translate_item_meta(&def, item_src, name, opacity);
72
73 let mut bt_ctx = ItemTransCtx::new(item_src.clone(), trans_id, self);
75 match &item_src.kind {
76 TransItemSourceKind::InherentImpl | TransItemSourceKind::Module => {
77 bt_ctx.register_module(item_meta, &def);
78 }
79 TransItemSourceKind::Type => {
80 let Some(AnyTransId::Type(id)) = trans_id else {
81 unreachable!()
82 };
83 let ty = bt_ctx.translate_type_decl(id, item_meta, &def)?;
84 self.translated.type_decls.set_slot(id, ty);
85 }
86 TransItemSourceKind::Fun => {
87 let Some(AnyTransId::Fun(id)) = trans_id else {
88 unreachable!()
89 };
90 let fun_decl = bt_ctx.translate_function(id, item_meta, &def)?;
91 self.translated.fun_decls.set_slot(id, fun_decl);
92 }
93 TransItemSourceKind::Global => {
94 let Some(AnyTransId::Global(id)) = trans_id else {
95 unreachable!()
96 };
97 let global_decl = bt_ctx.translate_global(id, item_meta, &def)?;
98 self.translated.global_decls.set_slot(id, global_decl);
99 }
100 TransItemSourceKind::TraitDecl => {
101 let Some(AnyTransId::TraitDecl(id)) = trans_id else {
102 unreachable!()
103 };
104 let trait_decl = bt_ctx.translate_trait_decl(id, item_meta, &def)?;
105 self.translated.trait_decls.set_slot(id, trait_decl);
106 }
107 TransItemSourceKind::TraitImpl(kind) => {
108 let Some(AnyTransId::TraitImpl(id)) = trans_id else {
109 unreachable!()
110 };
111 let trait_impl = match kind {
112 TraitImplSource::Normal => bt_ctx.translate_trait_impl(id, item_meta, &def)?,
113 TraitImplSource::TraitAlias => {
114 bt_ctx.translate_trait_alias_blanket_impl(id, item_meta, &def)?
115 }
116 &TraitImplSource::Closure(kind) => {
117 bt_ctx.translate_closure_trait_impl(id, item_meta, &def, kind)?
118 }
119 TraitImplSource::DropGlue => bt_ctx.translate_drop_impl(id, item_meta, &def)?,
120 };
121 self.translated.trait_impls.set_slot(id, trait_impl);
122 }
123 &TransItemSourceKind::ClosureMethod(kind) => {
124 let Some(AnyTransId::Fun(id)) = trans_id else {
125 unreachable!()
126 };
127 let fun_decl = bt_ctx.translate_closure_method(id, item_meta, &def, kind)?;
128 self.translated.fun_decls.set_slot(id, fun_decl);
129 }
130 TransItemSourceKind::ClosureAsFnCast => {
131 let Some(AnyTransId::Fun(id)) = trans_id else {
132 unreachable!()
133 };
134 let fun_decl = bt_ctx.translate_stateless_closure_as_fn(id, item_meta, &def)?;
135 self.translated.fun_decls.set_slot(id, fun_decl);
136 }
137 TransItemSourceKind::DropGlueMethod => {
138 let Some(AnyTransId::Fun(id)) = trans_id else {
139 unreachable!()
140 };
141 let fun_decl = bt_ctx.translate_drop_method(id, item_meta, &def)?;
142 self.translated.fun_decls.set_slot(id, fun_decl);
143 }
144 TransItemSourceKind::VTable => {
145 let Some(AnyTransId::Type(id)) = trans_id else {
146 unreachable!()
147 };
148 let ty_decl = bt_ctx.translate_vtable_struct(id, item_meta, &def)?;
149 self.translated.type_decls.set_slot(id, ty_decl);
150 }
151 TransItemSourceKind::VTableInstance(impl_kind) => {
152 let Some(AnyTransId::Global(id)) = trans_id else {
153 unreachable!()
154 };
155 let global_decl =
156 bt_ctx.translate_vtable_instance(id, item_meta, &def, impl_kind)?;
157 self.translated.global_decls.set_slot(id, global_decl);
158 }
159 TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
160 let Some(AnyTransId::Fun(id)) = trans_id else {
161 unreachable!()
162 };
163 let fun_decl =
164 bt_ctx.translate_vtable_instance_init(id, item_meta, &def, impl_kind)?;
165 self.translated.fun_decls.set_slot(id, fun_decl);
166 }
167 TransItemSourceKind::VTableMethod => {
168 }
174 }
175 Ok(())
176 }
177
178 pub(crate) fn get_or_translate(&mut self, id: AnyTransId) -> Result<AnyTransItem<'_>, Error> {
181 if self.translated.get_item(id).is_none() {
184 let item_source = self.reverse_id_map.get(&id).unwrap().clone();
185 self.translate_item(&item_source);
186 if self.translated.get_item(id).is_none() {
187 let span = self.def_span(item_source.def_id());
188 raise_error!(self, span, "Failed to translate item {id:?}.")
189 }
190 }
191 let item = self.translated.get_item(id);
192 Ok(item.unwrap())
193 }
194}
195
196impl ItemTransCtx<'_, '_> {
197 #[tracing::instrument(skip(self, item_meta))]
201 pub(crate) fn register_module(&mut self, item_meta: ItemMeta, def: &hax::FullDef) {
202 if !item_meta.opacity.is_transparent() {
203 return;
204 }
205 match def.kind() {
206 hax::FullDefKind::InherentImpl { items, .. } => {
207 for assoc in items {
208 self.t_ctx.enqueue_module_item(&assoc.def_id);
209 }
210 }
211 hax::FullDefKind::Mod { items, .. } => {
212 for (_, def_id) in items {
213 self.t_ctx.enqueue_module_item(def_id);
214 }
215 }
216 hax::FullDefKind::ForeignMod { items, .. } => {
217 for def_id in items {
218 self.t_ctx.enqueue_module_item(def_id);
219 }
220 }
221 _ => panic!("Item should be a module but isn't: {def:?}"),
222 }
223 }
224
225 pub(crate) fn get_item_kind(
226 &mut self,
227 span: Span,
228 def: &hax::FullDef,
229 ) -> Result<ItemKind, Error> {
230 let assoc = match def.kind() {
231 hax::FullDefKind::AssocTy {
232 associated_item, ..
233 }
234 | hax::FullDefKind::AssocConst {
235 associated_item, ..
236 }
237 | hax::FullDefKind::AssocFn {
238 associated_item, ..
239 } => associated_item,
240 hax::FullDefKind::Closure { args, .. } => {
241 let info = self.translate_closure_info(span, args)?;
242 return Ok(ItemKind::Closure { info });
243 }
244 _ => return Ok(ItemKind::TopLevel),
245 };
246 Ok(match &assoc.container {
247 hax::AssocItemContainer::InherentImplContainer { .. } => ItemKind::TopLevel,
254 hax::AssocItemContainer::TraitImplContainer {
261 impl_,
262 implemented_trait_ref,
263 implemented_trait_item,
264 overrides_default,
265 ..
266 } => {
267 let impl_ref =
268 self.translate_trait_impl_ref(span, impl_, TraitImplSource::Normal)?;
269 let trait_ref = self.translate_trait_ref(span, implemented_trait_ref)?;
270 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
271 let _: FunDeclId =
275 self.register_item(span, implemented_trait_item, TransItemSourceKind::Fun);
276 }
277 let item_name = self.t_ctx.translate_trait_item_name(def.def_id())?;
278 ItemKind::TraitImpl {
279 impl_ref,
280 trait_ref,
281 item_name,
282 reuses_default: !overrides_default,
283 }
284 }
285 hax::AssocItemContainer::TraitContainer { trait_ref, .. } => {
293 let trait_ref = self.translate_trait_ref(span, trait_ref)?;
296 let item_name = self.t_ctx.translate_trait_item_name(def.def_id())?;
297 ItemKind::TraitDecl {
298 trait_ref,
299 item_name,
300 has_default: assoc.has_value,
301 }
302 }
303 })
304 }
305
306 #[tracing::instrument(skip(self, item_meta))]
312 pub fn translate_type_decl(
313 mut self,
314 trans_id: TypeDeclId,
315 item_meta: ItemMeta,
316 def: &hax::FullDef,
317 ) -> Result<TypeDecl, Error> {
318 let span = item_meta.span;
319
320 self.translate_def_generics(span, def)?;
322
323 let src = self.get_item_kind(span, def)?;
325
326 let kind = match &def.kind {
328 _ if item_meta.opacity.is_opaque() => Ok(TypeDeclKind::Opaque),
329 hax::FullDefKind::OpaqueTy | hax::FullDefKind::ForeignTy => Ok(TypeDeclKind::Opaque),
330 hax::FullDefKind::TyAlias { ty, .. } => {
331 self.error_on_impl_expr_error = false;
333 self.translate_ty(span, ty).map(TypeDeclKind::Alias)
334 }
335 hax::FullDefKind::Adt { .. } => self.translate_adt_def(trans_id, span, &item_meta, def),
336 hax::FullDefKind::Closure { args, .. } => {
337 self.translate_closure_adt(trans_id, span, &args)
338 }
339 _ => panic!("Unexpected item when translating types: {def:?}"),
340 };
341
342 let kind = match kind {
343 Ok(kind) => kind,
344 Err(err) => TypeDeclKind::Error(err.msg),
345 };
346 let layout = self.translate_layout(def.this());
347 let ptr_metadata = self.translate_ptr_metadata(def.this());
348 let type_def = TypeDecl {
349 def_id: trans_id,
350 item_meta,
351 generics: self.into_generics(),
352 kind,
353 src,
354 layout,
355 ptr_metadata,
356 };
357
358 Ok(type_def)
359 }
360
361 #[tracing::instrument(skip(self, item_meta))]
363 pub fn translate_function(
364 mut self,
365 def_id: FunDeclId,
366 item_meta: ItemMeta,
367 def: &hax::FullDef,
368 ) -> Result<FunDecl, Error> {
369 trace!("About to translate function:\n{:?}", def.def_id());
370 let span = item_meta.span;
371
372 trace!("Translating function signature");
374 let signature = self.translate_function_signature(def, &item_meta)?;
375
376 let kind = self.get_item_kind(span, def)?;
379 let is_trait_method_decl_without_default = match &kind {
380 ItemKind::TraitDecl { has_default, .. } => !has_default,
381 _ => false,
382 };
383
384 let is_global_initializer = matches!(
385 def.kind(),
386 hax::FullDefKind::Const { .. }
387 | hax::FullDefKind::AssocConst { .. }
388 | hax::FullDefKind::Static { .. }
389 );
390 let is_global_initializer = is_global_initializer
391 .then(|| self.register_item(span, def.this(), TransItemSourceKind::Global));
392
393 let body = if item_meta.opacity.with_private_contents().is_opaque()
394 || is_trait_method_decl_without_default
395 {
396 Err(Opaque)
397 } else if let hax::FullDefKind::Ctor {
398 adt_def_id,
399 ctor_of,
400 variant_id,
401 fields,
402 output_ty,
403 ..
404 } = def.kind()
405 {
406 let body = self.build_ctor_body(
407 span,
408 def,
409 adt_def_id,
410 ctor_of,
411 *variant_id,
412 fields,
413 output_ty,
414 )?;
415 Ok(body)
416 } else {
417 let mut bt_ctx = BodyTransCtx::new(&mut self);
420 match bt_ctx.translate_def_body(item_meta.span, def) {
421 Ok(Ok(body)) => Ok(body),
422 Ok(Err(Opaque)) => Err(Opaque),
424 Err(_) => Err(Opaque),
427 }
428 };
429 Ok(FunDecl {
430 def_id,
431 item_meta,
432 signature,
433 kind,
434 is_global_initializer,
435 body,
436 })
437 }
438
439 #[tracing::instrument(skip(self, item_meta))]
441 pub fn translate_global(
442 mut self,
443 def_id: GlobalDeclId,
444 item_meta: ItemMeta,
445 def: &hax::FullDef,
446 ) -> Result<GlobalDecl, Error> {
447 trace!("About to translate global:\n{:?}", def.def_id());
448 let span = item_meta.span;
449
450 self.translate_def_generics(span, def)?;
458
459 let item_kind = self.get_item_kind(span, def)?;
461
462 trace!("Translating global type");
463 let ty = match &def.kind {
464 hax::FullDefKind::Const { ty, .. }
465 | hax::FullDefKind::AssocConst { ty, .. }
466 | hax::FullDefKind::Static { ty, .. } => ty,
467 _ => panic!("Unexpected def for constant: {def:?}"),
468 };
469 let ty = self.translate_ty(span, ty)?;
470
471 let global_kind = match &def.kind {
472 hax::FullDefKind::Static { .. } => GlobalKind::Static,
473 hax::FullDefKind::Const {
474 kind: hax::ConstKind::TopLevel,
475 ..
476 }
477 | hax::FullDefKind::AssocConst { .. } => GlobalKind::NamedConst,
478 hax::FullDefKind::Const { .. } => GlobalKind::AnonConst,
479 _ => panic!("Unexpected def for constant: {def:?}"),
480 };
481
482 let initializer = self.register_item(span, def.this(), TransItemSourceKind::Fun);
483
484 Ok(GlobalDecl {
485 def_id,
486 item_meta,
487 generics: self.into_generics(),
488 ty,
489 kind: item_kind,
490 global_kind,
491 init: initializer,
492 })
493 }
494
495 #[tracing::instrument(skip(self, item_meta))]
496 pub fn translate_trait_decl(
497 mut self,
498 def_id: TraitDeclId,
499 item_meta: ItemMeta,
500 def: &hax::FullDef,
501 ) -> Result<TraitDecl, Error> {
502 trace!("About to translate trait decl:\n{:?}", def.def_id());
503 trace!("Trait decl id:\n{:?}", def_id);
504
505 let span = item_meta.span;
506
507 self.translate_def_generics(span, def)?;
512
513 let (hax::FullDefKind::Trait {
514 implied_predicates, ..
515 }
516 | hax::FullDefKind::TraitAlias {
517 implied_predicates, ..
518 }) = def.kind()
519 else {
520 raise_error!(self, span, "Unexpected definition: {def:?}");
521 };
522
523 let mut preds =
525 self.translate_predicates(implied_predicates, PredicateOrigin::WhereClauseOnTrait)?;
526 let parent_clauses = mem::take(&mut preds.trait_clauses);
527 self.innermost_generics_mut().take_predicates_from(preds);
530
531 let vtable = self.translate_vtable_struct_ref(span, def.this())?;
532
533 if let hax::FullDefKind::TraitAlias { .. } = def.kind() {
534 return Ok(TraitDecl {
536 def_id,
537 item_meta,
538 parent_clauses,
539 generics: self.into_generics(),
540 consts: Default::default(),
541 types: Default::default(),
542 methods: Default::default(),
543 vtable,
544 });
545 }
546
547 let hax::FullDefKind::Trait {
548 items,
549 self_predicate,
550 ..
551 } = &def.kind
552 else {
553 unreachable!()
554 };
555 let self_trait_ref = TraitRef {
556 kind: TraitRefKind::SelfId,
557 trait_decl_ref: RegionBinder::empty(
558 self.translate_trait_predicate(span, self_predicate)?,
559 ),
560 };
561 let items: Vec<(TraitItemName, &hax::AssocItem)> = items
562 .iter()
563 .map(|item| -> Result<_, Error> {
564 let name = self.t_ctx.translate_trait_item_name(&item.def_id)?;
565 Ok((name, item))
566 })
567 .try_collect()?;
568
569 let mut consts = Vec::new();
572 let mut types = Vec::new();
573 let mut methods = Vec::new();
574 for (item_name, hax_item) in &items {
575 let item_def_id = &hax_item.def_id;
576 let item_span = self.def_span(item_def_id);
577
578 let trans_kind = match hax_item.kind {
581 hax::AssocKind::Fn { .. } => TransItemSourceKind::Fun,
582 hax::AssocKind::Const { .. } => TransItemSourceKind::Global,
583 hax::AssocKind::Type { .. } => TransItemSourceKind::Type,
584 };
585 let poly_item_def = self.poly_hax_def(item_def_id)?;
586 let (item_src, item_def) = if self.monomorphize() {
587 if poly_item_def.has_own_generics() {
588 continue;
593 } else {
594 let item = def.this().with_def_id(self.hax_state(), item_def_id);
595 let item_def = self.hax_def(&item)?;
596 let item_src = TransItemSource::monomorphic(&item, trans_kind);
597 (item_src, item_def)
598 }
599 } else {
600 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
601 (item_src, poly_item_def)
602 };
603
604 match item_def.kind() {
605 hax::FullDefKind::AssocFn { .. } => {
606 let binder_kind = BinderKind::TraitMethod(def_id, item_name.clone());
607 let mut method = self.translate_binder_for_def(
608 item_span,
609 binder_kind,
610 &item_def,
611 |bt_ctx| {
612 let fun_id = if bt_ctx.t_ctx.options.translate_all_methods
620 || item_meta.opacity.is_transparent()
621 || !hax_item.has_value
622 {
623 bt_ctx.register_and_enqueue(item_span, item_src)
624 } else {
625 bt_ctx.register_no_enqueue(item_span, &item_src)
626 };
627
628 assert_eq!(bt_ctx.binding_levels.len(), 2);
629 let fun_generics = bt_ctx
630 .outermost_binder()
631 .params
632 .identity_args_at_depth(DeBruijnId::one())
633 .concat(
634 &bt_ctx
635 .innermost_binder()
636 .params
637 .identity_args_at_depth(DeBruijnId::zero()),
638 );
639 let fn_ref = FunDeclRef {
640 id: fun_id,
641 generics: Box::new(fun_generics),
642 };
643 Ok(TraitMethod {
644 name: item_name.clone(),
645 item: fn_ref,
646 })
647 },
648 )?;
649 if !self.monomorphize() {
654 struct ReplaceSelfVisitor;
655 impl VarsVisitor for ReplaceSelfVisitor {
656 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
657 if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
658 Some(if let Some(new_id) = clause_id.index().checked_sub(1) {
660 TraitRefKind::Clause(DeBruijnVar::Bound(
661 DeBruijnId::ZERO,
662 TraitClauseId::new(new_id),
663 ))
664 } else {
665 TraitRefKind::SelfId
666 })
667 } else {
668 None
669 }
670 }
671 }
672 method.params.visit_vars(&mut ReplaceSelfVisitor);
673 method.skip_binder.visit_vars(&mut ReplaceSelfVisitor);
674 method
675 .params
676 .trait_clauses
677 .remove_and_shift_ids(TraitClauseId::ZERO);
678 method.params.trait_clauses.iter_mut().for_each(|clause| {
679 clause.clause_id -= 1;
680 });
681 }
682 methods.push(method);
683 }
684 hax::FullDefKind::AssocConst { ty, .. } => {
685 let default = hax_item.has_value.then(|| {
687 let id = self.register_and_enqueue(item_span, item_src);
690 let mut generics = self.the_only_binder().params.identity_args();
691 generics.trait_refs.push(self_trait_ref.clone());
692 GlobalDeclRef {
693 id,
694 generics: Box::new(generics),
695 }
696 });
697 let ty = self.translate_ty(item_span, ty)?;
698 consts.push(TraitAssocConst {
699 name: item_name.clone(),
700 ty,
701 default,
702 });
703 }
704 hax::FullDefKind::AssocTy { .. } if self.monomorphize() => continue,
706 hax::FullDefKind::AssocTy {
707 value,
708 implied_predicates,
709 ..
710 } => {
711 let binder_kind = BinderKind::TraitType(def_id, item_name.clone());
712 let assoc_ty =
713 self.translate_binder_for_def(item_span, binder_kind, &item_def, |ctx| {
714 let mut preds = ctx.translate_predicates(
716 &implied_predicates,
717 PredicateOrigin::TraitItem(item_name.clone()),
718 )?;
719 let implied_clauses = mem::take(&mut preds.trait_clauses);
720 ctx.innermost_generics_mut().take_predicates_from(preds);
723
724 let default = value
725 .as_ref()
726 .map(|ty| ctx.translate_ty(item_span, ty))
727 .transpose()?;
728 Ok(TraitAssocTy {
729 name: item_name.clone(),
730 default,
731 implied_clauses,
732 })
733 })?;
734 types.push(assoc_ty);
735 }
736 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
737 }
738 }
739
740 Ok(TraitDecl {
744 def_id,
745 item_meta,
746 parent_clauses,
747 generics: self.into_generics(),
748 consts,
749 types,
750 methods,
751 vtable,
752 })
753 }
754
755 #[tracing::instrument(skip(self, item_meta))]
756 pub fn translate_trait_impl(
757 mut self,
758 def_id: TraitImplId,
759 item_meta: ItemMeta,
760 def: &hax::FullDef,
761 ) -> Result<TraitImpl, Error> {
762 trace!("About to translate trait impl:\n{:?}", def.def_id());
763 trace!("Trait impl id:\n{:?}", def_id);
764
765 let span = item_meta.span;
766
767 self.translate_def_generics(span, def)?;
768
769 let hax::FullDefKind::TraitImpl {
770 trait_pred,
771 implied_impl_exprs,
772 items: impl_items,
773 ..
774 } = &def.kind
775 else {
776 unreachable!()
777 };
778
779 let implemented_trait = self.translate_trait_ref(span, &trait_pred.trait_ref)?;
781 let trait_id = implemented_trait.id;
782 let self_predicate = TraitRef {
784 kind: TraitRefKind::TraitImpl(TraitImplRef {
785 id: def_id,
786 generics: Box::new(self.the_only_binder().params.identity_args()),
787 }),
788 trait_decl_ref: RegionBinder::empty(implemented_trait.clone()),
789 };
790
791 let vtable = self.translate_vtable_instance_ref(span, &trait_pred.trait_ref, def.this())?;
792
793 let parent_trait_refs = self.translate_trait_impl_exprs(span, &implied_impl_exprs)?;
795
796 {
797 let ctx = self.into_fmt();
799 let refs = parent_trait_refs
800 .iter()
801 .map(|c| c.with_ctx(&ctx))
802 .format("\n");
803 trace!(
804 "Trait impl: {:?}\n- parent_trait_refs:\n{}",
805 def.def_id(),
806 refs
807 );
808 }
809
810 let mut consts = Vec::new();
812 let mut types = Vec::new();
813 let mut methods = Vec::new();
814
815 for impl_item in impl_items {
816 use hax::ImplAssocItemValue::*;
817 let name = self
818 .t_ctx
819 .translate_trait_item_name(&impl_item.decl_def_id)?;
820 let item_def_id = impl_item.def_id();
821 let item_span = self.def_span(item_def_id);
822 let poly_item_def = self.poly_hax_def(item_def_id)?;
826 let trans_kind = match poly_item_def.kind() {
827 hax::FullDefKind::AssocFn { .. } => TransItemSourceKind::Fun,
828 hax::FullDefKind::AssocConst { .. } => TransItemSourceKind::Global,
829 hax::FullDefKind::AssocTy { .. } => TransItemSourceKind::Type,
830 _ => unreachable!(),
831 };
832 let (item_src, item_def) = if self.monomorphize() {
833 if poly_item_def.has_own_generics() {
834 continue;
835 } else {
836 let item = match &impl_item.value {
837 Provided { def_id, .. } => def.this().with_def_id(self.hax_state(), def_id),
839 _ => trait_pred
841 .trait_ref
842 .with_def_id(self.hax_state(), &impl_item.decl_def_id),
843 };
844 let item_def = self.hax_def(&item)?;
845 let item_src = TransItemSource::monomorphic(&item, trans_kind);
846 (item_src, item_def)
847 }
848 } else {
849 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
850 (item_src, poly_item_def)
851 };
852
853 match item_def.kind() {
854 hax::FullDefKind::AssocFn { .. } => {
855 match &impl_item.value {
856 Provided { is_override, .. } => {
857 let binder_kind = BinderKind::TraitMethod(trait_id, name.clone());
858 let fn_ref = self.translate_binder_for_def(
859 item_span,
860 binder_kind,
861 &item_def,
862 |bt_ctx| {
863 let fun_id = if bt_ctx.t_ctx.options.translate_all_methods
870 || item_meta.opacity.is_transparent()
871 || !*is_override
872 {
873 bt_ctx.register_and_enqueue(item_span, item_src)
874 } else {
875 bt_ctx.register_no_enqueue(item_span, &item_src)
876 };
877
878 assert_eq!(bt_ctx.binding_levels.len(), 2);
880 let fun_generics = bt_ctx
881 .outermost_binder()
882 .params
883 .identity_args_at_depth(DeBruijnId::one())
884 .concat(
885 &bt_ctx
886 .innermost_binder()
887 .params
888 .identity_args_at_depth(DeBruijnId::zero()),
889 );
890 Ok(FunDeclRef {
891 id: fun_id,
892 generics: Box::new(fun_generics),
893 })
894 },
895 )?;
896 methods.push((name, fn_ref));
897 }
898 DefaultedFn { .. } => {
899 }
901 _ => unreachable!(),
902 }
903 }
904 hax::FullDefKind::AssocConst { .. } => {
905 let id = self.register_and_enqueue(item_span, item_src);
906 let generics = match &impl_item.value {
909 Provided { .. } => self.the_only_binder().params.identity_args(),
910 _ => {
911 let mut generics = implemented_trait.generics.as_ref().clone();
912 generics.trait_refs.push(self_predicate.clone());
913 generics
914 }
915 };
916 let gref = GlobalDeclRef {
917 id,
918 generics: Box::new(generics),
919 };
920 consts.push((name, gref));
921 }
922 hax::FullDefKind::AssocTy { .. } if self.monomorphize() => continue,
924 hax::FullDefKind::AssocTy { value, .. } => {
925 let binder_kind = BinderKind::TraitType(trait_id, name.clone());
926 let assoc_ty =
927 self.translate_binder_for_def(item_span, binder_kind, &item_def, |ctx| {
928 let ty = match &impl_item.value {
929 Provided { .. } => value.as_ref().unwrap(),
930 DefaultedTy { ty, .. } => ty,
931 _ => unreachable!(),
932 };
933 let ty = ctx.translate_ty(item_span, &ty)?;
934 let implied_trait_refs = ctx.translate_trait_impl_exprs(
935 item_span,
936 &impl_item.required_impl_exprs,
937 )?;
938 Ok(TraitAssocTyImpl {
939 value: ty,
940 implied_trait_refs,
941 })
942 })?;
943 types.push((name.clone(), assoc_ty));
944 }
945 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
946 }
947 }
948
949 Ok(TraitImpl {
950 def_id,
951 item_meta,
952 impl_trait: implemented_trait,
953 generics: self.into_generics(),
954 parent_trait_refs,
955 consts,
956 types,
957 methods,
958 vtable,
959 })
960 }
961
962 #[tracing::instrument(skip(self, item_meta))]
972 pub fn translate_trait_alias_blanket_impl(
973 mut self,
974 def_id: TraitImplId,
975 item_meta: ItemMeta,
976 def: &hax::FullDef,
977 ) -> Result<TraitImpl, Error> {
978 let span = item_meta.span;
979
980 self.translate_def_generics(span, def)?;
981
982 let hax::FullDefKind::TraitAlias {
983 implied_predicates, ..
984 } = &def.kind
985 else {
986 raise_error!(self, span, "Unexpected definition: {def:?}");
987 };
988
989 let trait_id = self.register_item(span, def.this(), TransItemSourceKind::TraitDecl);
990
991 assert!(self.innermost_generics_mut().trait_clauses.is_empty());
993 self.register_predicates(implied_predicates, PredicateOrigin::WhereClauseOnTrait)?;
994
995 let mut generics = self.the_only_binder().params.identity_args();
996 let parent_trait_refs = mem::take(&mut generics.trait_refs);
998 let implemented_trait = TraitDeclRef {
999 id: trait_id,
1000 generics: Box::new(generics),
1001 };
1002
1003 let mut timpl = TraitImpl {
1004 def_id,
1005 item_meta,
1006 impl_trait: implemented_trait,
1007 generics: self.the_only_binder().params.clone(),
1008 parent_trait_refs,
1009 consts: Default::default(),
1010 types: Default::default(),
1011 methods: Default::default(),
1012 vtable: None,
1014 };
1015 {
1018 struct FixSelfVisitor {
1019 binder_depth: DeBruijnId,
1020 }
1021 struct UnhandledSelf;
1022 impl Visitor for FixSelfVisitor {
1023 type Break = UnhandledSelf;
1024 }
1025 impl VisitorWithBinderDepth for FixSelfVisitor {
1026 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1027 &mut self.binder_depth
1028 }
1029 }
1030 impl VisitAstMut for FixSelfVisitor {
1031 fn visit<'a, T: AstVisitable>(&'a mut self, x: &mut T) -> ControlFlow<Self::Break> {
1032 VisitWithBinderDepth::new(self).visit(x)
1033 }
1034 fn visit_trait_ref_kind(
1035 &mut self,
1036 kind: &mut TraitRefKind,
1037 ) -> ControlFlow<Self::Break> {
1038 match kind {
1039 TraitRefKind::SelfId => return ControlFlow::Break(UnhandledSelf),
1040 TraitRefKind::ParentClause(sub, clause_id)
1041 if matches!(sub.kind, TraitRefKind::SelfId) =>
1042 {
1043 *kind = TraitRefKind::Clause(DeBruijnVar::bound(
1044 self.binder_depth,
1045 *clause_id,
1046 ))
1047 }
1048 _ => (),
1049 }
1050 self.visit_inner(kind)
1051 }
1052 }
1053 match timpl.drive_mut(&mut FixSelfVisitor {
1054 binder_depth: DeBruijnId::zero(),
1055 }) {
1056 ControlFlow::Continue(()) => {}
1057 ControlFlow::Break(UnhandledSelf) => {
1058 register_error!(
1059 self,
1060 span,
1061 "Found `Self` clause we can't handle \
1062 in a trait alias blanket impl."
1063 );
1064 }
1065 }
1066 };
1067
1068 Ok(timpl)
1069 }
1070
1071 #[tracing::instrument(skip(self, item_meta))]
1074 pub fn translate_virtual_trait_impl(
1075 &mut self,
1076 def_id: TraitImplId,
1077 item_meta: ItemMeta,
1078 vimpl: &hax::VirtualTraitImpl,
1079 ) -> Result<TraitImpl, Error> {
1080 let span = item_meta.span;
1081 let trait_def = self.hax_def(&vimpl.trait_pred.trait_ref)?;
1082 let hax::FullDefKind::Trait {
1083 items: trait_items, ..
1084 } = trait_def.kind()
1085 else {
1086 panic!()
1087 };
1088
1089 let implemented_trait = self.translate_trait_predicate(span, &vimpl.trait_pred)?;
1090 let parent_trait_refs = self.translate_trait_impl_exprs(span, &vimpl.implied_impl_exprs)?;
1091
1092 let mut types = vec![];
1093 if !self.monomorphize() {
1095 let type_items = trait_items.iter().filter(|assoc| match assoc.kind {
1096 hax::AssocKind::Type { .. } => true,
1097 _ => false,
1098 });
1099 for ((ty, impl_exprs), assoc) in vimpl.types.iter().zip(type_items) {
1100 let name = self.t_ctx.translate_trait_item_name(&assoc.def_id)?;
1101 let assoc_ty = TraitAssocTyImpl {
1102 value: self.translate_ty(span, ty)?,
1103 implied_trait_refs: self.translate_trait_impl_exprs(span, impl_exprs)?,
1104 };
1105 let binder_kind = BinderKind::TraitType(implemented_trait.id, name.clone());
1106 types.push((name, Binder::empty(binder_kind, assoc_ty)));
1107 }
1108 }
1109
1110 let generics = self.the_only_binder().params.clone();
1111 Ok(TraitImpl {
1112 def_id,
1113 item_meta,
1114 impl_trait: implemented_trait,
1115 generics,
1116 parent_trait_refs,
1117 consts: vec![],
1118 types,
1119 methods: vec![],
1120 vtable: None,
1122 })
1123 }
1124}