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