1use super::translate_crate::*;
2use super::translate_ctx::*;
3use crate::hax;
4use crate::hax::SInto;
5use charon_lib::ast::ullbc_ast_utils::BodyBuilder;
6use charon_lib::ast::*;
7use charon_lib::formatter::IntoFormatter;
8use charon_lib::pretty::FmtWithCtx;
9use derive_generic_visitor::Visitor;
10use itertools::Itertools;
11use rustc_span::sym;
12use std::mem;
13use std::ops::ControlFlow;
14
15impl<'tcx> TranslateCtx<'tcx> {
16 pub(crate) fn translate_item(&mut self, item_src: &TransItemSource) {
17 let trans_id = self.register_no_enqueue(&None, item_src);
18 let def_id = item_src.def_id();
19 if let Some(trans_id) = trans_id {
20 if self.translate_stack.contains(&trans_id) {
21 register_error!(
22 self,
23 Span::dummy(),
24 "Cycle detected while translating {def_id:?}! Stack: {:?}",
25 &self.translate_stack
26 );
27 return;
28 } else {
29 self.translate_stack.push(trans_id);
30 }
31 }
32 self.with_def_id(def_id, trans_id, |mut ctx| {
33 let span = ctx.def_span(def_id);
34 let res = {
36 let mut ctx = std::panic::AssertUnwindSafe(&mut ctx);
38 std::panic::catch_unwind(move || ctx.translate_item_aux(item_src, trans_id))
39 };
40 match res {
41 Ok(Ok(())) => return,
42 Ok(Err(_)) => {
44 register_error!(ctx, span, "Item `{def_id:?}` caused errors; ignoring.")
45 }
46 Err(_) => register_error!(
48 ctx,
49 span,
50 "Thread panicked when extracting item `{def_id:?}`."
51 ),
52 };
53 });
54 self.translate_stack.pop();
56 }
57
58 pub(crate) fn translate_item_aux(
59 &mut self,
60 item_src: &TransItemSource,
61 trans_id: Option<ItemId>,
62 ) -> Result<(), Error> {
63 let name = self.translate_name(item_src)?;
65 if let Some(trans_id) = trans_id {
66 self.translated.item_names.insert(trans_id, name.clone());
67 }
68 let opacity = self.opacity_for_name(&name);
69 if opacity.is_invisible() {
70 return Ok(());
72 }
73 let def = self.hax_def_for_item(&item_src.item)?;
74 let item_meta = self.translate_item_meta(&def, item_src, name, opacity);
75 if item_meta.opacity.is_invisible() {
76 return Ok(());
77 }
78
79 if !item_meta.opacity.is_opaque()
82 && let Some(def_id) = def.def_id().as_rust_def_id()
83 && let Some(ldid) = def_id.as_local()
84 && let node = self.tcx.hir_node_by_def_id(ldid)
85 && let Some(body_id) = node.body_id()
86 {
87 use rustc_hir::intravisit;
88 #[allow(non_local_definitions)]
89 impl<'tcx> intravisit::Visitor<'tcx> for TranslateCtx<'tcx> {
90 fn visit_nested_item(&mut self, id: rustc_hir::ItemId) {
91 let def_id = id.owner_id.def_id.to_def_id();
92 let def_id = def_id.sinto(&self.hax_state);
93 self.enqueue_module_item(&def_id);
94 }
95 }
96 let body = self.tcx.hir_body(body_id);
97 intravisit::walk_body(self, body);
98 }
99
100 let mut bt_ctx = ItemTransCtx::new(item_src.clone(), trans_id, self);
102 trace!(
103 "About to translate item `{:?}` as a {:?}; \
104 target_id={trans_id:?}, mono={}",
105 def.def_id(),
106 item_src.kind,
107 bt_ctx.monomorphize(),
108 );
109 if !matches!(
110 &item_src.kind,
111 TransItemSourceKind::InherentImpl | TransItemSourceKind::Module,
112 ) {
113 bt_ctx.translate_item_generics(item_meta.span, &def, &item_src.kind)?;
114 }
115 match &item_src.kind {
116 TransItemSourceKind::InherentImpl | TransItemSourceKind::Module => {
117 bt_ctx.register_module(item_meta, &def);
118 }
119 TransItemSourceKind::Type => {
120 let Some(ItemId::Type(id)) = trans_id else {
121 unreachable!()
122 };
123 let ty = bt_ctx.translate_type_decl(id, item_meta, &def)?;
124 self.translated.type_decls.set_slot(id, ty);
125 }
126 TransItemSourceKind::Fun => {
127 let Some(ItemId::Fun(id)) = trans_id else {
128 unreachable!()
129 };
130 let fun_decl = bt_ctx.translate_fun_decl(id, item_meta, &def)?;
131 self.translated.fun_decls.set_slot(id, fun_decl);
132 }
133 TransItemSourceKind::Global => {
134 let Some(ItemId::Global(id)) = trans_id else {
135 unreachable!()
136 };
137 let global_decl = bt_ctx.translate_global(id, item_meta, &def)?;
138 self.translated.global_decls.set_slot(id, global_decl);
139 }
140 TransItemSourceKind::TraitDecl => {
141 let Some(ItemId::TraitDecl(id)) = trans_id else {
142 unreachable!()
143 };
144 let trait_decl = bt_ctx.translate_trait_decl(id, item_meta, &def)?;
145 self.translated.trait_decls.set_slot(id, trait_decl);
146 }
147 TransItemSourceKind::TraitImpl(kind) => {
148 let Some(ItemId::TraitImpl(id)) = trans_id else {
149 unreachable!()
150 };
151 let trait_impl = match kind {
153 TraitImplSource::Normal => bt_ctx.translate_trait_impl(id, item_meta, &def)?,
154 TraitImplSource::TraitAlias => {
155 bt_ctx.translate_trait_alias_blanket_impl(id, item_meta, &def)?
156 }
157 &TraitImplSource::Closure(kind) => {
158 bt_ctx.translate_closure_trait_impl(id, item_meta, &def, kind)?
159 }
160 TraitImplSource::ImplicitDestruct => {
161 bt_ctx.translate_implicit_destruct_impl(id, item_meta, &def)?
162 }
163 };
164 self.translated.trait_impls.set_slot(id, trait_impl);
165 }
166 &TransItemSourceKind::DefaultedMethod(impl_kind, name) => {
167 let Some(ItemId::Fun(id)) = trans_id else {
168 unreachable!()
169 };
170 let fun_decl =
171 bt_ctx.translate_defaulted_method(id, item_meta, &def, impl_kind, name)?;
172 self.translated.fun_decls.set_slot(id, fun_decl);
173 }
174 &TransItemSourceKind::ClosureMethod(kind) => {
175 let Some(ItemId::Fun(id)) = trans_id else {
176 unreachable!()
177 };
178 let fun_decl = bt_ctx.translate_closure_method(id, item_meta, &def, kind)?;
179 self.translated.fun_decls.set_slot(id, fun_decl);
180 }
181 TransItemSourceKind::ClosureAsFnCast => {
182 let Some(ItemId::Fun(id)) = trans_id else {
183 unreachable!()
184 };
185 let fun_decl = bt_ctx.translate_stateless_closure_as_fn(id, item_meta, &def)?;
186 self.translated.fun_decls.set_slot(id, fun_decl);
187 }
188 &TransItemSourceKind::DropInPlaceMethod(impl_kind) => {
189 let Some(ItemId::Fun(id)) = trans_id else {
190 unreachable!()
191 };
192 let fun_decl =
193 bt_ctx.translate_drop_in_place_method(id, item_meta, &def, impl_kind)?;
194 self.translated.fun_decls.set_slot(id, fun_decl);
195 }
196 TransItemSourceKind::VTable => {
197 let Some(ItemId::Type(id)) = trans_id else {
198 unreachable!()
199 };
200 let ty_decl = bt_ctx.translate_vtable_struct(id, item_meta, &def)?;
201 self.translated.type_decls.set_slot(id, ty_decl);
202 }
203 TransItemSourceKind::VTableInstance(impl_kind) => {
204 let Some(ItemId::Global(id)) = trans_id else {
205 unreachable!()
206 };
207 let global_decl =
208 bt_ctx.translate_vtable_instance(id, item_meta, &def, impl_kind)?;
209 self.translated.global_decls.set_slot(id, global_decl);
210 }
211 TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
212 let Some(ItemId::Fun(id)) = trans_id else {
213 unreachable!()
214 };
215 let fun_decl =
216 bt_ctx.translate_vtable_instance_init(id, item_meta, &def, impl_kind)?;
217 self.translated.fun_decls.set_slot(id, fun_decl);
218 }
219 TransItemSourceKind::VTableMethod => {
220 let Some(ItemId::Fun(id)) = trans_id else {
221 unreachable!()
222 };
223 let fun_decl = bt_ctx.translate_vtable_shim(id, item_meta, &def)?;
224 self.translated.fun_decls.set_slot(id, fun_decl);
225 }
226 TransItemSourceKind::VTableDropShim => {
227 let Some(ItemId::Fun(id)) = trans_id else {
228 unreachable!()
229 };
230 let fun_decl = bt_ctx.translate_vtable_drop_shim(id, item_meta, &def)?;
231 self.translated.fun_decls.set_slot(id, fun_decl);
232 }
233 TransItemSourceKind::VTableDropPreShim => {
234 let Some(ItemId::Fun(id)) = trans_id else {
235 unreachable!()
236 };
237 let fun_decl = bt_ctx.translate_vtable_drop_preshim(id, item_meta, &def)?;
238 self.translated.fun_decls.set_slot(id, fun_decl);
239 }
240 TransItemSourceKind::VTableMethodPreShim(trait_id, name) => {
241 let Some(ItemId::Fun(id)) = trans_id else {
242 unreachable!()
243 };
244 let fun_decl =
245 bt_ctx.translate_vtable_method_preshim(id, item_meta, &def, name, trait_id)?;
246 self.translated.fun_decls.set_slot(id, fun_decl);
247 }
248 }
249 Ok(())
250 }
251
252 pub(crate) fn get_or_translate(&mut self, id: ItemId) -> Result<krate::ItemRef<'_>, Error> {
255 if self.translated.get_item(id).is_none() {
258 let item_source = self.reverse_id_map.get(&id).unwrap().clone();
259 self.translate_item(&item_source);
260 if self.translated.get_item(id).is_none() {
261 let span = self.def_span(item_source.def_id());
262 let name = self
263 .translated
264 .item_name(id)
265 .map(|n| n.to_string_with_ctx(&self.into_fmt()))
266 .unwrap_or_else(|| id.to_string());
267 return Err(Error {
269 span,
270 msg: format!("Failed to translate item {name}."),
271 });
272 }
274 self.processed.insert(item_source.clone());
276 }
277 let item = self.translated.get_item(id);
278 Ok(item.unwrap())
279 }
280
281 pub fn translate_unit_metadata_const(&mut self) {
283 use charon_lib::ullbc_ast::*;
284 let name = Name::from_path(&["UNIT_METADATA"]);
285 let item_meta = ItemMeta {
286 name: name.clone(),
287 span: Span::dummy(),
288 source_text: None,
289 attr_info: AttrInfo::default(),
290 is_local: false,
291 opacity: ItemOpacity::Foreign,
292 lang_item: None,
293 };
294
295 let body = {
296 let mut builder = BodyBuilder::new(Span::dummy(), 0);
297 let _ = builder.new_var(None, Ty::mk_unit());
298 builder.build()
299 };
300
301 let global_id = self.translated.global_decls.reserve_slot();
302 let initializer = self.translated.fun_decls.push_with(|def_id| FunDecl {
303 def_id,
304 item_meta: item_meta.clone(),
305 src: ItemSource::TopLevel,
306 is_global_initializer: Some(global_id),
307 generics: Default::default(),
308 signature: FunSig {
309 is_unsafe: false,
310 inputs: vec![],
311 output: Ty::mk_unit(),
312 },
313 body: Body::Unstructured(body),
314 });
315 self.translated
316 .item_names
317 .insert(ItemId::Fun(initializer), name.clone());
318 self.translated.global_decls.set_slot(
319 global_id,
320 GlobalDecl {
321 def_id: global_id,
322 item_meta,
323 generics: Default::default(),
324 ty: Ty::mk_unit(),
325 src: ItemSource::TopLevel,
326 global_kind: GlobalKind::NamedConst,
327 init: initializer,
328 },
329 );
330 self.translated
331 .item_names
332 .insert(ItemId::Global(global_id), name);
333 self.translated.unit_metadata = Some(GlobalDeclRef {
334 id: global_id,
335 generics: Box::new(GenericArgs::empty()),
336 });
337 }
338
339 pub fn remove_unused_methods(&mut self) {
341 let method_is_used = |trait_id, name| {
342 self.method_status.get(trait_id).is_some_and(|map| {
343 map.get(&name)
344 .is_some_and(|status| matches!(status, MethodStatus::Used))
345 })
346 };
347 for tdecl in self.translated.trait_decls.iter_mut() {
348 tdecl
349 .methods
350 .retain(|m| method_is_used(tdecl.def_id, m.name()));
351 }
352 for timpl in self.translated.trait_impls.iter_mut() {
353 let trait_id = timpl.impl_trait.id;
354 timpl
355 .methods
356 .retain(|(name, _)| method_is_used(trait_id, *name));
357 }
358 }
359}
360
361impl ItemTransCtx<'_, '_> {
362 #[tracing::instrument(skip(self, item_meta, def))]
366 pub(crate) fn register_module(&mut self, item_meta: ItemMeta, def: &hax::FullDef) {
367 if !item_meta.opacity.is_transparent() {
368 return;
369 }
370 match def.kind() {
371 hax::FullDefKind::InherentImpl { items, .. } => {
372 for assoc in items {
373 self.t_ctx.enqueue_module_item(&assoc.def_id);
374 }
375 }
376 hax::FullDefKind::Mod { items, .. } => {
377 for (_, def_id) in items {
378 self.t_ctx.enqueue_module_item(def_id);
379 }
380 }
381 hax::FullDefKind::ForeignMod { items, .. } => {
382 for def_id in items {
383 self.t_ctx.enqueue_module_item(def_id);
384 }
385 }
386 _ => panic!("Item should be a module but isn't: {def:?}"),
387 }
388 }
389
390 pub(crate) fn get_item_source(
391 &mut self,
392 span: Span,
393 def: &hax::FullDef,
394 ) -> Result<ItemSource, Error> {
395 let assoc = match def.kind() {
396 hax::FullDefKind::AssocTy {
397 associated_item, ..
398 }
399 | hax::FullDefKind::AssocConst {
400 associated_item, ..
401 }
402 | hax::FullDefKind::AssocFn {
403 associated_item, ..
404 } => associated_item,
405 hax::FullDefKind::Closure { args, .. } => {
406 let info = self.translate_closure_info(span, args)?;
407 return Ok(ItemSource::Closure { info });
408 }
409 _ => return Ok(ItemSource::TopLevel),
410 };
411 Ok(match &assoc.container {
412 hax::AssocItemContainer::InherentImplContainer { .. } => ItemSource::TopLevel,
419 hax::AssocItemContainer::TraitImplContainer {
426 impl_,
427 implemented_trait_ref,
428 overrides_default,
429 ..
430 } => {
431 let impl_ref =
432 self.translate_trait_impl_ref(span, impl_, TraitImplSource::Normal)?;
433 let trait_ref = self.translate_trait_ref(span, implemented_trait_ref)?;
434 let item_name = self.t_ctx.translate_trait_item_name(def.def_id())?;
435 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
436 self.mark_method_as_used(trait_ref.id, item_name);
439 }
440 ItemSource::TraitImpl {
441 impl_ref,
442 trait_ref,
443 item_name,
444 reuses_default: !overrides_default,
445 }
446 }
447 hax::AssocItemContainer::TraitContainer { trait_ref, .. } => {
455 let trait_ref = self.translate_trait_ref(span, trait_ref)?;
458 let item_name = self.t_ctx.translate_trait_item_name(def.def_id())?;
459 ItemSource::TraitDecl {
460 trait_ref,
461 item_name,
462 has_default: assoc.has_value,
463 }
464 }
465 })
466 }
467
468 #[tracing::instrument(skip(self, item_meta, def))]
474 pub fn translate_type_decl(
475 mut self,
476 trans_id: TypeDeclId,
477 item_meta: ItemMeta,
478 def: &hax::FullDef,
479 ) -> Result<TypeDecl, Error> {
480 let span = item_meta.span;
481
482 let src = self.get_item_source(span, def)?;
484
485 let mut repr: Option<ReprOptions> = None;
486
487 let kind = match &def.kind {
489 _ if item_meta.opacity.is_opaque() => Ok(TypeDeclKind::Opaque),
490 hax::FullDefKind::OpaqueTy | hax::FullDefKind::ForeignTy => Ok(TypeDeclKind::Opaque),
491 hax::FullDefKind::TyAlias { ty, .. } => {
492 self.error_on_impl_expr_error = false;
494 self.translate_ty(span, ty).map(TypeDeclKind::Alias)
495 }
496 hax::FullDefKind::Adt { repr: hax_repr, .. } => {
497 repr = Some(self.translate_repr_options(hax_repr));
498 self.translate_adt_def(trans_id, span, &item_meta, def)
499 }
500 hax::FullDefKind::Closure { args, .. } => self.translate_closure_adt(span, args),
501 _ => panic!("Unexpected item when translating types: {def:?}"),
502 };
503
504 let kind = match kind {
505 Ok(kind) => kind,
506 Err(err) => TypeDeclKind::Error(err.msg),
507 };
508 let layout = self
509 .translate_layout(def.this())
510 .into_iter()
511 .map(|l| (self.get_target_triple(), l))
512 .collect();
513 let ptr_metadata = self.translate_ptr_metadata(span, def.this())?;
514 let type_def = TypeDecl {
515 def_id: trans_id,
516 item_meta,
517 generics: self.into_generics(),
518 kind,
519 src,
520 layout,
521 ptr_metadata,
522 repr,
523 };
524
525 Ok(type_def)
526 }
527
528 #[tracing::instrument(skip(self, item_meta, def))]
530 pub fn translate_fun_decl(
531 mut self,
532 def_id: FunDeclId,
533 item_meta: ItemMeta,
534 def: &hax::FullDef,
535 ) -> Result<FunDecl, Error> {
536 let span = item_meta.span;
537
538 let src = self.get_item_source(span, def)?;
539
540 if let hax::FullDefKind::Ctor {
541 fields, output_ty, ..
542 } = def.kind()
543 {
544 let signature = FunSig {
545 inputs: fields
546 .iter()
547 .map(|field| self.translate_ty(span, &field.ty))
548 .try_collect()?,
549 output: self.translate_ty(span, output_ty)?,
550 is_unsafe: false,
551 };
552
553 let body = if item_meta.opacity.with_private_contents().is_opaque() {
554 Body::Opaque
555 } else {
556 self.build_ctor_body(span, def)?
557 };
558 return Ok(FunDecl {
559 def_id,
560 item_meta,
561 generics: self.into_generics(),
562 signature,
563 src,
564 is_global_initializer: None,
565 body,
566 });
567 }
568
569 trace!("Translating function signature");
571 let signature = match &def.kind {
572 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
573 self.translate_fun_sig(span, &sig.value)?
574 }
575 hax::FullDefKind::Const { ty, .. }
576 | hax::FullDefKind::AssocConst { ty, .. }
577 | hax::FullDefKind::Static { ty, .. } => FunSig {
578 inputs: vec![],
579 output: self.translate_ty(span, ty)?,
580 is_unsafe: false,
581 },
582 _ => panic!("Unexpected definition for function: {def:?}"),
583 };
584
585 let is_trait_method_decl_without_default = match &src {
588 ItemSource::TraitDecl { has_default, .. } => !has_default,
589 _ => false,
590 };
591
592 let intrinsic_name = def
593 .def_id()
594 .as_rust_def_id()
595 .and_then(|id| self.tcx.intrinsic(id))
596 .map(|i| i.name.to_ident_string());
597
598 let is_global_initializer = matches!(
599 def.kind(),
600 hax::FullDefKind::Const { .. }
601 | hax::FullDefKind::AssocConst { .. }
602 | hax::FullDefKind::Static { .. }
603 );
604 let is_global_initializer = is_global_initializer
605 .then(|| self.register_item(span, def.this(), TransItemSourceKind::Global));
606
607 let body = if let Some(name) = intrinsic_name {
608 let arg_names = self.translate_argument_names(span, def, signature.inputs.len());
609 Body::Intrinsic { name, arg_names }
610 } else if let Some(name) = self.t_ctx.extern_item_symbol_name(def) {
611 Body::Extern(name)
612 } else if item_meta.opacity.with_private_contents().is_opaque() {
613 Body::Opaque
614 } else if is_trait_method_decl_without_default {
615 Body::TraitMethodWithoutDefault
616 } else {
617 self.translate_def_body(item_meta.span, def)
619 };
620 Ok(FunDecl {
621 def_id,
622 item_meta,
623 generics: self.into_generics(),
624 signature,
625 src,
626 is_global_initializer,
627 body,
628 })
629 }
630
631 #[tracing::instrument(skip(self, item_meta, def))]
633 pub fn translate_global(
634 mut self,
635 def_id: GlobalDeclId,
636 item_meta: ItemMeta,
637 def: &hax::FullDef,
638 ) -> Result<GlobalDecl, Error> {
639 let span = item_meta.span;
640
641 let item_source = self.get_item_source(span, def)?;
643
644 trace!("Translating global type");
645 let ty = match &def.kind {
646 hax::FullDefKind::Const { ty, .. }
647 | hax::FullDefKind::AssocConst { ty, .. }
648 | hax::FullDefKind::Static { ty, .. } => ty,
649 _ => panic!("Unexpected def for constant: {def:?}"),
650 };
651 let ty = self.translate_ty(span, ty)?;
652
653 let global_kind = match &def.kind {
654 hax::FullDefKind::Static { .. } => GlobalKind::Static,
655 hax::FullDefKind::Const {
656 kind: hax::ConstKind::TopLevel,
657 ..
658 }
659 | hax::FullDefKind::AssocConst { .. } => GlobalKind::NamedConst,
660 hax::FullDefKind::Const { .. } => GlobalKind::AnonConst,
661 _ => panic!("Unexpected def for constant: {def:?}"),
662 };
663
664 let initializer = self.register_item(span, def.this(), TransItemSourceKind::Fun);
665
666 Ok(GlobalDecl {
667 def_id,
668 item_meta,
669 generics: self.into_generics(),
670 ty,
671 src: item_source,
672 global_kind,
673 init: initializer,
674 })
675 }
676
677 #[tracing::instrument(skip(self, item_meta, def))]
679 pub fn translate_trait_decl(
680 mut self,
681 def_id: TraitDeclId,
682 item_meta: ItemMeta,
683 def: &hax::FullDef,
684 ) -> Result<TraitDecl, Error> {
685 let span = item_meta.span;
686
687 let (hax::FullDefKind::Trait {
688 implied_predicates, ..
689 }
690 | hax::FullDefKind::TraitAlias {
691 implied_predicates, ..
692 }) = def.kind()
693 else {
694 raise_error!(self, span, "Unexpected definition: {def:?}");
695 };
696
697 let mut implied_clauses = Default::default();
700 self.translate_predicates(
701 implied_predicates,
702 PredicateOrigin::WhereClauseOnTrait,
703 Some(&mut implied_clauses),
704 )?;
705
706 let vtable = self.translate_vtable_struct_ref_no_enqueue(span, def.this())?;
707
708 if let hax::FullDefKind::TraitAlias { .. } = def.kind() {
709 return Ok(TraitDecl {
711 def_id,
712 item_meta,
713 implied_clauses,
714 generics: self.into_generics(),
715 consts: Default::default(),
716 types: Default::default(),
717 methods: Default::default(),
718 vtable,
719 });
720 }
721
722 let hax::FullDefKind::Trait {
723 items,
724 self_predicate,
725 ..
726 } = &def.kind
727 else {
728 unreachable!()
729 };
730 let self_trait_ref = TraitRef::new(
731 TraitRefKind::SelfId,
732 RegionBinder::empty(self.translate_trait_predicate(span, self_predicate)?),
733 );
734 let items: Vec<(TraitItemName, &hax::AssocItem)> = items
735 .iter()
736 .map(|item| -> Result<_, Error> {
737 let name = self.t_ctx.translate_trait_item_name(&item.def_id)?;
738 Ok((name, item))
739 })
740 .try_collect()?;
741
742 let mut consts = Vec::new();
744 let mut types = Vec::new();
745 let mut methods = Vec::new();
746
747 if self.monomorphize() {
751 return Ok(TraitDecl {
752 def_id,
753 item_meta,
754 implied_clauses,
755 generics: self.into_generics(),
756 consts,
757 types,
758 methods,
759 vtable,
760 });
761 }
762
763 for &(item_name, hax_item) in &items {
764 let item_def_id = &hax_item.def_id;
765 let item_span = self.def_span(item_def_id);
766
767 let trans_kind = match hax_item.kind {
770 hax::AssocKind::Fn { .. } => TransItemSourceKind::Fun,
771 hax::AssocKind::Const { .. } => TransItemSourceKind::Global,
772 hax::AssocKind::Type { .. } => TransItemSourceKind::Type,
773 };
774
775 let item_def = self.poly_hax_def(item_def_id)?;
776 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
777 let attr_info = self.translate_attr_info(&item_def);
778
779 match item_def.kind() {
780 hax::FullDefKind::AssocFn { .. } => {
781 let method_id = self.register_no_enqueue(item_span, &item_src);
782 self.register_method_impl(def_id, item_name, method_id);
784 if self.options.translate_all_methods
787 || item_meta.opacity.is_transparent()
788 || !hax_item.has_value
789 {
790 self.mark_method_as_used(def_id, item_name);
791 }
792
793 let binder_kind = BinderKind::TraitMethod(def_id, item_name);
794 let mut method = self.translate_binder_for_def(
795 item_span,
796 binder_kind,
797 &item_def,
798 |bt_ctx| {
799 assert_eq!(bt_ctx.binding_levels.len(), 2);
800 let fun_generics = bt_ctx
801 .outermost_binder()
802 .params
803 .identity_args_at_depth(DeBruijnId::one())
804 .concat(
805 &bt_ctx
806 .innermost_binder()
807 .params
808 .identity_args_at_depth(DeBruijnId::zero()),
809 );
810 let fn_ref = FunDeclRef {
811 id: method_id,
812 generics: Box::new(fun_generics),
813 };
814 Ok(TraitMethod {
815 name: item_name,
816 attr_info,
817 item: fn_ref,
818 })
819 },
820 )?;
821 struct ReplaceSelfVisitor;
826 impl VarsVisitor for ReplaceSelfVisitor {
827 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
828 if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
829 Some(if let Some(new_id) = clause_id.index().checked_sub(1) {
831 TraitRefKind::Clause(DeBruijnVar::Bound(
832 DeBruijnId::ZERO,
833 TraitClauseId::new(new_id),
834 ))
835 } else {
836 TraitRefKind::SelfId
837 })
838 } else {
839 None
840 }
841 }
842 }
843 method.params.visit_vars(&mut ReplaceSelfVisitor);
844 method.skip_binder.visit_vars(&mut ReplaceSelfVisitor);
845 method
846 .params
847 .trait_clauses
848 .remove_and_shift_ids(TraitClauseId::ZERO);
849 method.params.trait_clauses.iter_mut().for_each(|clause| {
850 clause.clause_id -= 1;
851 });
852
853 methods.push(method);
856 }
857 hax::FullDefKind::AssocConst { ty, .. } => {
858 let bound_assoc_const = self.translate_binder_for_def(
861 item_span,
862 BinderKind::Other,
863 &item_def,
864 |ctx| {
865 let default = hax_item.has_value.then(|| {
867 let id = ctx.register_and_enqueue(item_span, item_src);
870 let generics = ctx
871 .outermost_binder()
872 .params
873 .identity_args_at_depth(DeBruijnId::one())
874 .concat(
875 &ctx.innermost_binder()
876 .params
877 .identity_args_at_depth(DeBruijnId::zero()),
878 );
879 GlobalDeclRef {
880 id,
881 generics: Box::new(generics),
882 }
883 });
884 let ty = ctx.translate_ty(item_span, ty)?;
885 Ok(TraitAssocConst {
886 name: item_name,
887 attr_info,
888 ty,
889 default,
890 })
891 },
892 )?;
893 let assoc_const = bound_assoc_const.apply(&{
894 let mut generics = GenericArgs::empty();
895 generics.trait_refs.push(self_trait_ref.clone());
897 generics
898 });
899 consts.push(assoc_const);
900 }
901 hax::FullDefKind::AssocTy {
902 implied_predicates,
903 value: default,
904 ..
905 } => {
906 let binder_kind = BinderKind::TraitType(def_id, item_name);
907 let assoc_ty =
908 self.translate_binder_for_def(item_span, binder_kind, &item_def, |ctx| {
909 let mut implied_clauses = Default::default();
911 ctx.translate_predicates(
912 implied_predicates,
913 PredicateOrigin::TraitItem(item_name),
914 Some(&mut implied_clauses),
915 )?;
916
917 let default = default
918 .as_ref()
919 .map(|(ty, impl_exprs)| -> Result<_, Error> {
920 let ty = ctx.translate_ty(item_span, ty)?;
921 let trefs = ctx.translate_trait_impl_exprs(span, impl_exprs)?;
922 Ok(TraitAssocTyImpl {
923 value: ty,
924 implied_trait_refs: trefs,
925 })
926 })
927 .transpose()?;
928 Ok(TraitAssocTy {
929 name: item_name,
930 attr_info,
931 default,
932 implied_clauses,
933 })
934 })?;
935 types.push(assoc_ty);
936 }
937 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
938 }
939 }
940
941 if def.lang_item == Some(sym::destruct) {
942 let (method_name, method_binder) =
944 self.prepare_drop_in_place_method(def, span, def_id, None);
945 self.mark_method_as_used(def_id, method_name);
946 methods.push(method_binder.map(|fn_ref| TraitMethod {
947 name: method_name,
948 attr_info: AttrInfo::dummy_public(),
949 item: fn_ref,
950 }));
951 }
952
953 Ok(TraitDecl {
957 def_id,
958 item_meta,
959 implied_clauses,
960 generics: self.into_generics(),
961 consts,
962 types,
963 methods,
964 vtable,
965 })
966 }
967
968 #[tracing::instrument(skip(self, item_meta, def))]
969 pub fn translate_trait_impl(
970 mut self,
971 def_id: TraitImplId,
972 item_meta: ItemMeta,
973 def: &hax::FullDef,
974 ) -> Result<TraitImpl, Error> {
975 let span = item_meta.span;
976
977 let hax::FullDefKind::TraitImpl {
978 trait_pred,
979 implied_impl_exprs,
980 items: impl_items,
981 ..
982 } = &def.kind
983 else {
984 unreachable!()
985 };
986
987 let implemented_trait = self.translate_trait_ref(span, &trait_pred.trait_ref)?;
989 let trait_id = implemented_trait.id;
990 let self_predicate = TraitRef::new(
992 TraitRefKind::TraitImpl(TraitImplRef {
993 id: def_id,
994 generics: Box::new(self.the_only_binder().params.identity_args()),
995 }),
996 RegionBinder::empty(implemented_trait.clone()),
997 );
998
999 let vtable =
1000 self.translate_vtable_instance_ref_no_enqueue(span, &trait_pred.trait_ref, def.this())?;
1001
1002 let implied_trait_refs = self.translate_trait_impl_exprs(span, implied_impl_exprs)?;
1004
1005 {
1006 let ctx = self.into_fmt();
1008 let refs = implied_trait_refs
1009 .iter()
1010 .map(|c| c.with_ctx(&ctx))
1011 .format("\n");
1012 trace!(
1013 "Trait impl: {:?}\n- implied_trait_refs:\n{}",
1014 def.def_id(),
1015 refs
1016 );
1017 }
1018
1019 let implemented_trait_def = self.poly_hax_def(&trait_pred.trait_ref.def_id)?;
1020 if implemented_trait_def.lang_item == Some(sym::destruct) {
1021 raise_error!(
1022 self,
1023 span,
1024 "found an explicit impl of `core::marker::Destruct`, this should not happen"
1025 );
1026 }
1027
1028 let mut consts = Vec::new();
1030 let mut types = Vec::new();
1031 let mut methods = Vec::new();
1032
1033 if self.monomorphize() {
1035 return Ok(TraitImpl {
1036 def_id,
1037 item_meta,
1038 impl_trait: implemented_trait,
1039 generics: self.into_generics(),
1040 implied_trait_refs,
1041 consts,
1042 types,
1043 methods,
1044 vtable,
1045 });
1046 }
1047
1048 for impl_item in impl_items {
1049 use crate::hax::ImplAssocItemValue::*;
1050 let name = self
1051 .t_ctx
1052 .translate_trait_item_name(&impl_item.decl_def_id)?;
1053 let item_def_id = impl_item.def_id();
1054 let item_span = self.def_span(item_def_id);
1055 let item_def = self.poly_hax_def(item_def_id)?;
1058 let trans_kind = match item_def.kind() {
1059 hax::FullDefKind::AssocFn { .. } => TransItemSourceKind::Fun,
1060 hax::FullDefKind::AssocConst { .. } => TransItemSourceKind::Global,
1061 hax::FullDefKind::AssocTy { .. } => TransItemSourceKind::Type,
1062 _ => unreachable!(),
1063 };
1064 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
1065
1066 match item_def.kind() {
1067 hax::FullDefKind::AssocFn { .. } => {
1068 let method_id: FunDeclId = {
1069 let method_src = match &impl_item.value {
1070 Provided { .. } => item_src,
1071 DefaultedFn { .. } => TransItemSource::from_item(
1074 def.this(),
1075 TransItemSourceKind::DefaultedMethod(TraitImplSource::Normal, name),
1076 self.monomorphize(),
1077 ),
1078 _ => unreachable!(),
1079 };
1080 self.register_no_enqueue(item_span, &method_src)
1081 };
1082
1083 self.register_method_impl(trait_id, name, method_id);
1085 if matches!(impl_item.value, Provided { .. })
1088 && item_meta.opacity.is_transparent()
1089 {
1090 self.mark_method_as_used(trait_id, name);
1091 }
1092
1093 let binder_kind = BinderKind::TraitMethod(trait_id, name);
1094 let bound_fn_ref = match &impl_item.value {
1095 Provided { .. } => self.translate_binder_for_def(
1096 item_span,
1097 binder_kind,
1098 &item_def,
1099 |ctx| {
1100 let generics = ctx
1101 .outermost_generics()
1102 .identity_args_at_depth(DeBruijnId::one())
1103 .concat(
1104 &ctx.innermost_generics()
1105 .identity_args_at_depth(DeBruijnId::zero()),
1106 );
1107 Ok(FunDeclRef {
1108 id: method_id,
1109 generics: Box::new(generics),
1110 })
1111 },
1112 )?,
1113 DefaultedFn { .. } => {
1114 let decl_methods =
1116 match self.get_or_translate(implemented_trait.id.into()) {
1117 Ok(ItemRef::TraitDecl(tdecl)) => tdecl.methods.as_slice(),
1118 _ => &[],
1119 };
1120 let Some(bound_method) = decl_methods.iter().find(|m| m.name() == name)
1121 else {
1122 continue;
1123 };
1124 let method_params = bound_method
1125 .clone()
1126 .substitute_with_tref(&self_predicate)
1127 .params;
1128
1129 let generics = self
1130 .outermost_generics()
1131 .identity_args_at_depth(DeBruijnId::one())
1132 .concat(&method_params.identity_args_at_depth(DeBruijnId::zero()));
1133 let fn_ref = FunDeclRef {
1134 id: method_id,
1135 generics: Box::new(generics),
1136 };
1137 Binder::new(binder_kind, method_params, fn_ref)
1138 }
1139 _ => unreachable!(),
1140 };
1141
1142 methods.push((name, bound_fn_ref));
1145 }
1146 hax::FullDefKind::AssocConst { .. } => {
1147 let id = self.register_and_enqueue(item_span, item_src);
1148 let generics = match &impl_item.value {
1151 Provided { .. } => self.the_only_binder().params.identity_args(),
1152 _ => {
1153 let mut generics = implemented_trait.generics.as_ref().clone();
1154 generics.trait_refs.push(self_predicate.clone());
1156 generics
1157 }
1158 };
1159 let gref = GlobalDeclRef {
1160 id,
1161 generics: Box::new(generics),
1162 };
1163 consts.push((name, gref));
1164 }
1165 hax::FullDefKind::AssocTy { value, .. } => {
1166 let binder_kind = BinderKind::TraitType(trait_id, name);
1167 let assoc_ty = match &impl_item.value {
1168 Provided { .. } => self.translate_binder_for_def(
1169 item_span,
1170 binder_kind,
1171 &item_def,
1172 |ctx| {
1173 let (ty, _impl_exprs) = value.as_ref().unwrap();
1174 let ty = ctx.translate_ty(item_span, ty)?;
1175 let implied_trait_refs = ctx.translate_trait_impl_exprs(
1176 item_span,
1177 &impl_item.required_impl_exprs,
1178 )?;
1179 Ok(TraitAssocTyImpl {
1180 value: ty,
1181 implied_trait_refs,
1182 })
1183 },
1184 )?,
1185 DefaultedTy { .. } => {
1186 let decl_types =
1188 match self.get_or_translate(implemented_trait.id.into()) {
1189 Ok(ItemRef::TraitDecl(tdecl)) => tdecl.types.as_slice(),
1190 _ => &[],
1191 };
1192 let Some(bound_ty) =
1193 decl_types.iter().find(|m| *m.name() == name).cloned()
1194 else {
1195 register_error!(
1196 self,
1197 item_span,
1198 "couldn't translate defaulted associated type; \
1199 either the corresponding trait decl caused errors \
1200 or it was declared opaque."
1201 );
1202 continue;
1203 };
1204 bound_ty
1205 .substitute_with_tref(&self_predicate)
1206 .map(|ty_decl: TraitAssocTy| ty_decl.default.unwrap())
1207 }
1208 _ => unreachable!(),
1209 };
1210
1211 types.push((name, assoc_ty));
1212 }
1213 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
1214 }
1215 }
1216
1217 Ok(TraitImpl {
1218 def_id,
1219 item_meta,
1220 impl_trait: implemented_trait,
1221 generics: self.into_generics(),
1222 implied_trait_refs,
1223 consts,
1224 types,
1225 methods,
1226 vtable,
1227 })
1228 }
1229
1230 #[tracing::instrument(skip(self, item_meta, def))]
1240 pub fn translate_trait_alias_blanket_impl(
1241 mut self,
1242 def_id: TraitImplId,
1243 item_meta: ItemMeta,
1244 def: &hax::FullDef,
1245 ) -> Result<TraitImpl, Error> {
1246 let span = item_meta.span;
1247
1248 let hax::FullDefKind::TraitAlias {
1249 implied_predicates, ..
1250 } = &def.kind
1251 else {
1252 raise_error!(self, span, "Unexpected definition: {def:?}");
1253 };
1254
1255 let trait_id = self.register_item(span, def.this(), TransItemSourceKind::TraitDecl);
1256
1257 assert!(self.innermost_generics_mut().trait_clauses.is_empty());
1259 self.register_predicates(implied_predicates, PredicateOrigin::WhereClauseOnTrait)?;
1260
1261 let mut generics = self.the_only_binder().params.identity_args();
1262 let implied_trait_refs = mem::take(&mut generics.trait_refs);
1264 let implemented_trait = TraitDeclRef {
1265 id: trait_id,
1266 generics: Box::new(generics),
1267 };
1268
1269 let mut timpl = TraitImpl {
1270 def_id,
1271 item_meta,
1272 impl_trait: implemented_trait,
1273 generics: self.the_only_binder().params.clone(),
1274 implied_trait_refs,
1275 consts: Default::default(),
1276 types: Default::default(),
1277 methods: Default::default(),
1278 vtable: None,
1280 };
1281 {
1284 struct FixSelfVisitor {
1285 binder_depth: DeBruijnId,
1286 }
1287 struct UnhandledSelf;
1288 impl Visitor for FixSelfVisitor {
1289 type Break = UnhandledSelf;
1290 }
1291 impl VisitorWithBinderDepth for FixSelfVisitor {
1292 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1293 &mut self.binder_depth
1294 }
1295 }
1296 impl VisitAstMut for FixSelfVisitor {
1297 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
1298 VisitWithBinderDepth::new(self).visit(x)
1299 }
1300 fn visit_trait_ref_kind(
1301 &mut self,
1302 kind: &mut TraitRefKind,
1303 ) -> ControlFlow<Self::Break> {
1304 match kind {
1305 TraitRefKind::SelfId => return ControlFlow::Break(UnhandledSelf),
1306 TraitRefKind::ParentClause(sub, clause_id)
1307 if matches!(sub.kind, TraitRefKind::SelfId) =>
1308 {
1309 *kind = TraitRefKind::Clause(DeBruijnVar::bound(
1310 self.binder_depth,
1311 *clause_id,
1312 ))
1313 }
1314 _ => (),
1315 }
1316 self.visit_inner(kind)
1317 }
1318 }
1319 match timpl.drive_mut(&mut FixSelfVisitor {
1320 binder_depth: DeBruijnId::zero(),
1321 }) {
1322 ControlFlow::Continue(()) => {}
1323 ControlFlow::Break(UnhandledSelf) => {
1324 register_error!(
1325 self,
1326 span,
1327 "Found `Self` clause we can't handle \
1328 in a trait alias blanket impl."
1329 );
1330 }
1331 }
1332 };
1333
1334 Ok(timpl)
1335 }
1336
1337 #[tracing::instrument(skip(self, item_meta))]
1340 pub fn translate_virtual_trait_impl(
1341 &mut self,
1342 def_id: TraitImplId,
1343 item_meta: ItemMeta,
1344 vimpl: &hax::VirtualTraitImpl,
1345 ) -> Result<TraitImpl, Error> {
1346 let span = item_meta.span;
1347 let trait_def = self.hax_def(&vimpl.trait_pred.trait_ref)?;
1348 let hax::FullDefKind::Trait {
1349 items: trait_items, ..
1350 } = trait_def.kind()
1351 else {
1352 panic!()
1353 };
1354
1355 let implemented_trait = self.translate_trait_predicate(span, &vimpl.trait_pred)?;
1356 let implied_trait_refs =
1357 self.translate_trait_impl_exprs(span, &vimpl.implied_impl_exprs)?;
1358
1359 let mut types = vec![];
1360 if !self.monomorphize() {
1362 let type_items = trait_items
1363 .iter()
1364 .filter(|assoc| matches!(assoc.kind, hax::AssocKind::Type { .. }));
1365 for ((ty, impl_exprs), assoc) in vimpl.types.iter().zip(type_items) {
1366 let name = self.t_ctx.translate_trait_item_name(&assoc.def_id)?;
1367 let assoc_ty = TraitAssocTyImpl {
1368 value: self.translate_ty(span, ty)?,
1369 implied_trait_refs: self.translate_trait_impl_exprs(span, impl_exprs)?,
1370 };
1371 let binder_kind = BinderKind::TraitType(implemented_trait.id, name);
1372 types.push((name, Binder::empty(binder_kind, assoc_ty)));
1373 }
1374 }
1375
1376 let generics = self.the_only_binder().params.clone();
1377 Ok(TraitImpl {
1378 def_id,
1379 item_meta,
1380 impl_trait: implemented_trait,
1381 generics,
1382 implied_trait_refs,
1383 consts: vec![],
1384 types,
1385 methods: vec![],
1386 vtable: None,
1388 })
1389 }
1390
1391 pub fn register_method_impl(
1395 &mut self,
1396 trait_id: TraitDeclId,
1397 method_name: TraitItemName,
1398 method_id: FunDeclId,
1399 ) {
1400 match self
1401 .method_status
1402 .get_or_extend_and_insert_default(trait_id)
1403 .entry(method_name)
1404 .or_default()
1405 {
1406 MethodStatus::Unused { implementors } => {
1407 implementors.insert(method_id);
1408 }
1409 MethodStatus::Used => {
1410 self.enqueue_id(method_id);
1411 }
1412 }
1413 }
1414
1415 pub fn mark_method_as_used(&mut self, trait_id: TraitDeclId, method_name: TraitItemName) {
1418 let method_status = self
1419 .method_status
1420 .get_or_extend_and_insert_default(trait_id)
1421 .entry(method_name)
1422 .or_default();
1423 match method_status {
1424 MethodStatus::Unused { implementors } => {
1425 let implementors = mem::take(implementors);
1426 *method_status = MethodStatus::Used;
1427 for fun_id in implementors {
1428 self.enqueue_id(fun_id);
1429 }
1430 }
1431 MethodStatus::Used => {}
1432 }
1433 }
1434
1435 #[tracing::instrument(skip(self, item_meta, def))]
1438 pub fn translate_defaulted_method(
1439 &mut self,
1440 def_id: FunDeclId,
1441 item_meta: ItemMeta,
1442 def: &hax::FullDef,
1443 impl_kind: TraitImplSource,
1444 method_name: TraitItemName,
1445 ) -> Result<FunDecl, Error> {
1446 let span = item_meta.span;
1447
1448 let hax::FullDefKind::TraitImpl { trait_pred, .. } = &def.kind else {
1449 unreachable!()
1450 };
1451
1452 let implemented_trait = self.translate_trait_ref(span, &trait_pred.trait_ref)?;
1454 let self_impl_ref = self.translate_trait_impl_ref(span, def.this(), impl_kind)?;
1456 let self_predicate_kind = TraitRefKind::TraitImpl(self_impl_ref.clone());
1457
1458 let ItemRef::TraitDecl(tdecl) = self.get_or_translate(implemented_trait.id.into())? else {
1460 panic!()
1461 };
1462 let Some(bound_method) = tdecl.methods.iter().find(|m| m.name() == method_name) else {
1463 raise_error!(
1464 self,
1465 span,
1466 "Could not find a method with name \
1467 `{method_name}` in trait `{:?}`",
1468 trait_pred.trait_ref.def_id,
1469 )
1470 };
1471 let bound_fn_ref: Binder<FunDeclRef> = bound_method
1472 .clone()
1473 .substitute_with_self(&implemented_trait.generics, &self_predicate_kind)
1474 .map(|m| m.item);
1475
1476 let bound_fn_ref: Binder<Binder<FunDeclRef>> = Binder {
1480 params: self.outermost_generics().clone(),
1481 skip_binder: bound_fn_ref,
1482 kind: BinderKind::Other,
1483 };
1484 let bound_fn_ref: Binder<FunDeclRef> = bound_fn_ref.flatten();
1485
1486 let original_method_id = bound_fn_ref.skip_binder.id;
1488 let ItemRef::Fun(fun_decl) = self.get_or_translate(original_method_id.into())? else {
1489 panic!()
1490 };
1491 let mut fun_decl = fun_decl
1492 .clone()
1493 .substitute_params(bound_fn_ref.map(|x| *x.generics));
1494
1495 fun_decl.def_id = def_id;
1497 fun_decl.item_meta = ItemMeta {
1500 name: item_meta.name,
1501 opacity: item_meta.opacity,
1502 is_local: item_meta.is_local,
1503 span: item_meta.span,
1504 source_text: fun_decl.item_meta.source_text,
1505 attr_info: fun_decl.item_meta.attr_info,
1506 lang_item: fun_decl.item_meta.lang_item,
1507 };
1508 fun_decl.src = if let ItemSource::TraitDecl {
1509 trait_ref,
1510 item_name,
1511 ..
1512 } = fun_decl.src
1513 {
1514 ItemSource::TraitImpl {
1515 impl_ref: self_impl_ref.clone(),
1516 trait_ref,
1517 item_name,
1518 reuses_default: true,
1519 }
1520 } else {
1521 unreachable!()
1522 };
1523 if !item_meta.opacity.is_transparent() {
1524 fun_decl.body = Body::Opaque;
1525 }
1526
1527 Ok(fun_decl)
1528 }
1529}