1use super::translate_crate::*;
2use super::translate_ctx::*;
3use crate::hax;
4use crate::hax::SInto;
5use charon_lib::ast::*;
6use charon_lib::formatter::IntoFormatter;
7use charon_lib::options::ConstHandling;
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_real_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 TransImplSource::Normal => bt_ctx.translate_trait_impl(id, item_meta, &def)?,
154 TransImplSource::TraitAlias => {
155 bt_ctx.translate_trait_alias_blanket_impl(id, item_meta, &def)?
156 }
157 &TransImplSource::Callable(kind) => {
158 bt_ctx.translate_closure_trait_impl(id, item_meta, &def, kind)?
159 }
160 TransImplSource::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::CallableMethod(kind) => {
167 let Some(ItemId::Fun(id)) = trans_id else {
168 unreachable!()
169 };
170 let fun_decl = bt_ctx.translate_closure_method(id, item_meta, &def, kind)?;
171 self.translated.fun_decls.set_slot(id, fun_decl);
172 }
173 TransItemSourceKind::ClosureAsFnCast => {
174 let Some(ItemId::Fun(id)) = trans_id else {
175 unreachable!()
176 };
177 let fun_decl = bt_ctx.translate_stateless_closure_as_fn(id, item_meta, &def)?;
178 self.translated.fun_decls.set_slot(id, fun_decl);
179 }
180 &TransItemSourceKind::DropGlueMethod(impl_kind) => {
181 let Some(ItemId::Fun(id)) = trans_id else {
182 unreachable!()
183 };
184 let fun_decl = bt_ctx.translate_drop_glue_method(id, item_meta, &def, impl_kind)?;
185 self.translated.fun_decls.set_slot(id, fun_decl);
186 }
187 TransItemSourceKind::VTable => {
188 let Some(ItemId::Type(id)) = trans_id else {
189 unreachable!()
190 };
191 let ty_decl = bt_ctx.translate_vtable_struct(id, item_meta, &def)?;
192 self.translated.type_decls.set_slot(id, ty_decl);
193 }
194 TransItemSourceKind::VTableInstance(impl_kind) => {
195 let Some(ItemId::Global(id)) = trans_id else {
196 unreachable!()
197 };
198 let global_decl =
199 bt_ctx.translate_vtable_instance(id, item_meta, &def, impl_kind)?;
200 self.translated.global_decls.set_slot(id, global_decl);
201 }
202 TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
203 let Some(ItemId::Fun(id)) = trans_id else {
204 unreachable!()
205 };
206 let fun_decl =
207 bt_ctx.translate_vtable_instance_init(id, item_meta, &def, impl_kind)?;
208 self.translated.fun_decls.set_slot(id, fun_decl);
209 }
210 TransItemSourceKind::VTableMethod => {
211 let Some(ItemId::Fun(id)) = trans_id else {
212 unreachable!()
213 };
214 let fun_decl = bt_ctx.translate_vtable_shim(id, item_meta, &def)?;
215 self.translated.fun_decls.set_slot(id, fun_decl);
216 }
217 TransItemSourceKind::VTableDropShim => {
218 let Some(ItemId::Fun(id)) = trans_id else {
219 unreachable!()
220 };
221 let fun_decl = bt_ctx.translate_vtable_drop_shim(id, item_meta, &def)?;
222 self.translated.fun_decls.set_slot(id, fun_decl);
223 }
224 }
225 Ok(())
226 }
227
228 pub(crate) fn get_or_translate(&mut self, id: ItemId) -> Result<ItemRef<'_>, Error> {
231 if self.translated.get_item(id).is_none() {
234 let item_source = self.reverse_id_map.get(&id).unwrap().clone();
235 self.translate_item(&item_source);
236 if self.translated.get_item(id).is_none() {
237 let span = self.def_span(item_source.def_id());
238 let name = id.to_string_with_ctx(&self.into_fmt());
239 return Err(Error {
241 span,
242 msg: format!("Failed to translate item {name}."),
243 });
244 }
246 self.processed.insert(item_source.clone());
248 }
249 let item = self.translated.get_item(id);
250 Ok(item.unwrap())
251 }
252
253 pub fn register_method_impl(
257 &mut self,
258 trait_id: TraitDeclId,
259 method_id: TraitMethodId,
260 fun_id: FunDeclId,
261 ) {
262 match &mut self.method_status[trait_id][method_id] {
263 MethodStatus::Unused { implementors } => {
264 implementors.insert(fun_id);
265 }
266 MethodStatus::Used => {
267 self.enqueue_id(fun_id);
268 }
269 }
270 }
271
272 pub fn mark_method_as_used(&mut self, trait_id: TraitDeclId, method_id: TraitMethodId) {
275 let old_status = mem::replace(
276 &mut self.method_status[trait_id][method_id],
277 MethodStatus::Used,
278 );
279 match old_status {
280 MethodStatus::Unused { implementors } => {
281 for fun_id in implementors {
282 self.enqueue_id(fun_id);
283 }
284 }
285 MethodStatus::Used => {}
286 }
287 }
288
289 pub fn remove_unused_methods(&mut self) {
291 let method_is_used = |trait_id: TraitDeclId, method_id: TraitMethodId| {
292 matches!(self.method_status[trait_id][method_id], MethodStatus::Used)
293 };
294 for tdecl in self.translated.trait_decls.iter_mut() {
295 tdecl
296 .methods
297 .retain(|i, _m| method_is_used(tdecl.def_id, i));
298 }
299 for timpl in self.translated.trait_impls.iter_mut() {
300 let trait_id = timpl.impl_trait.id;
301 timpl.methods.retain(|i, _m| method_is_used(trait_id, i));
302 }
303 }
304}
305
306enum TraitItemSource {
307 Default {
308 trait_ref: TraitDeclRef,
309 item_id: AssocItemId,
310 },
311 Impl {
312 impl_ref: TraitImplRef,
313 trait_ref: TraitDeclRef,
314 item_id: AssocItemId,
315 reuses_default: bool,
316 },
317}
318
319impl<'tcx> ItemTransCtx<'tcx, '_> {
320 #[tracing::instrument(skip(self, item_meta, def))]
324 pub(crate) fn register_module(&mut self, item_meta: ItemMeta, def: &hax::FullDef<'tcx>) {
325 if !item_meta.opacity.is_transparent() {
326 return;
327 }
328 match def.kind() {
329 hax::FullDefKind::InherentImpl { items, .. } => {
330 for assoc in items {
331 self.t_ctx.enqueue_module_item(&assoc.def_id);
332 }
333 }
334 hax::FullDefKind::Mod { items, .. } => {
335 for (_, def_id) in items {
336 self.t_ctx.enqueue_module_item(def_id);
337 }
338 }
339 hax::FullDefKind::ForeignMod { items, .. } => {
340 for def_id in items {
341 self.t_ctx.enqueue_module_item(def_id);
342 }
343 }
344 _ => panic!("Item should be a module but isn't: {def:?}"),
345 }
346 }
347
348 fn get_trait_item_source(
349 &mut self,
350 span: Span,
351 def: &hax::FullDef<'tcx>,
352 ) -> Result<Option<TraitItemSource>, Error> {
353 let assoc = match def.kind() {
354 hax::FullDefKind::AssocConst {
355 associated_item, ..
356 }
357 | hax::FullDefKind::AssocFn {
358 associated_item, ..
359 } => associated_item,
360 _ => return Ok(None),
361 };
362 Ok(Some(match &assoc.container {
363 hax::AssocItemContainer::InherentImplContainer { .. } => return Ok(None),
370 hax::AssocItemContainer::TraitImplContainer {
377 impl_,
378 implemented_trait_ref,
379 overrides_default,
380 ..
381 } => {
382 let impl_ref =
383 self.translate_trait_impl_ref(span, impl_, TransImplSource::Normal)?;
384 let trait_ref = self.translate_trait_ref(span, implemented_trait_ref)?;
385 let item_id = self.translate_assoc_item_id(trait_ref.id, def.def_id())?;
386 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
387 let method_id = *item_id.as_method().unwrap();
390 self.mark_method_as_used(trait_ref.id, method_id);
391 }
392 TraitItemSource::Impl {
393 impl_ref,
394 trait_ref,
395 item_id,
396 reuses_default: !overrides_default,
397 }
398 }
399 hax::AssocItemContainer::TraitContainer { trait_ref, .. } => {
407 let trait_ref = self.translate_trait_ref(span, trait_ref)?;
410 let item_id = self.translate_assoc_item_id(trait_ref.id, def.def_id())?;
411 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
412 let method_id = *item_id.as_method().unwrap();
415 self.mark_method_as_used(trait_ref.id, method_id);
416 }
417 debug_assert!(assoc.has_value);
418 TraitItemSource::Default { trait_ref, item_id }
419 }
420 }))
421 }
422
423 #[tracing::instrument(skip(self, item_meta, def))]
429 pub fn translate_type_decl(
430 mut self,
431 trans_id: TypeDeclId,
432 item_meta: ItemMeta,
433 def: &hax::FullDef<'tcx>,
434 ) -> Result<TypeDecl, Error> {
435 let span = item_meta.span;
436
437 let src = match def.kind() {
439 hax::FullDefKind::Closure { args, .. } => {
440 let info = self.translate_closure_info(span, args)?;
441 TypeSource::Closure { info }
442 }
443 _ => TypeSource::Normal,
444 };
445
446 let kind = match &def.kind {
448 _ if item_meta.opacity.is_opaque() => Ok(TypeDeclKind::Opaque),
449 hax::FullDefKind::OpaqueTy | hax::FullDefKind::ForeignTy => Ok(TypeDeclKind::Opaque),
450 hax::FullDefKind::TyAlias { ty, .. } => {
451 self.error_on_trait_proof_error = false;
453 self.translate_ty(span, ty).map(TypeDeclKind::Alias)
454 }
455 hax::FullDefKind::Adt { .. } => self.translate_adt_def(trans_id, span, &item_meta, def),
456 hax::FullDefKind::Closure { args, .. } => self.translate_closure_adt(span, args),
457 _ => panic!("Unexpected item when translating types: {def:?}"),
458 };
459
460 let kind = match kind {
461 Ok(kind) => kind,
462 Err(err) => TypeDeclKind::Error(err.msg),
463 };
464 let layout = self
465 .translate_layout(def)
466 .into_iter()
467 .map(|l| (self.get_target_triple(), l))
468 .collect();
469 let ptr_metadata = self.translate_ptr_metadata(span, def.this())?;
470 let type_def = TypeDecl {
471 def_id: trans_id,
472 item_meta,
473 generics: self.into_generics(),
474 kind,
475 src,
476 layout,
477 ptr_metadata,
478 };
479
480 Ok(type_def)
481 }
482
483 #[tracing::instrument(skip(self, item_meta, def))]
485 pub fn translate_fun_decl(
486 mut self,
487 def_id: FunDeclId,
488 item_meta: ItemMeta,
489 def: &hax::FullDef<'tcx>,
490 ) -> Result<FunDecl, Error> {
491 let span = item_meta.span;
492
493 let src = if matches!(
494 def.kind(),
495 hax::FullDefKind::Const { .. }
496 | hax::FullDefKind::AssocConst { .. }
497 | hax::FullDefKind::Static { .. }
498 ) {
499 let global_id = self.register_item(span, def.this(), TransItemSourceKind::Global);
500 FunSource::GlobalInitializer(GlobalDeclRef {
501 id: global_id,
502 generics: Box::new(self.outermost_generics().identity_args()),
503 })
504 } else {
505 match self.get_trait_item_source(span, def)? {
506 None => FunSource::Normal,
507 Some(TraitItemSource::Default { trait_ref, item_id }) => FunSource::TraitDefault {
508 trait_ref,
509 item_id: *item_id.as_method().unwrap(),
510 },
511 Some(TraitItemSource::Impl {
512 impl_ref,
513 trait_ref,
514 item_id,
515 reuses_default,
516 }) => FunSource::TraitImpl {
517 impl_ref,
518 trait_ref,
519 item_id: *item_id.as_method().unwrap(),
520 reuses_default,
521 },
522 }
523 };
524
525 if let hax::FullDefKind::Ctor {
526 fields, output_ty, ..
527 } = def.kind()
528 {
529 let signature = FunSig {
530 inputs: fields
531 .iter()
532 .map(|field| self.translate_ty(span, &field.ty))
533 .try_collect()?,
534 output: self.translate_ty(span, output_ty)?,
535 is_unsafe: false,
536 abi: Abi::rust(),
537 is_variadic: false,
538 };
539
540 let body = if item_meta.opacity.with_private_contents().is_opaque() {
541 Body::Opaque
542 } else {
543 self.build_ctor_body(span, def)?
544 };
545 return Ok(FunDecl {
546 def_id,
547 item_meta,
548 generics: self.into_generics(),
549 signature: Box::new(signature),
550 src,
551 body,
552 });
553 }
554
555 trace!("Translating function signature");
557 let signature = match &def.kind {
558 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
559 self.translate_fun_sig(span, &sig.value)?
560 }
561 hax::FullDefKind::Const { ty, .. }
562 | hax::FullDefKind::AssocConst { ty, .. }
563 | hax::FullDefKind::Static { ty, .. } => FunSig {
564 inputs: vec![],
565 output: self.translate_ty(span, ty)?,
566 is_unsafe: false,
567 abi: Abi::rust(),
568 is_variadic: false,
569 },
570 _ => panic!("Unexpected definition for function: {def:?}"),
571 };
572
573 let intrinsic_name = def
574 .def_id()
575 .as_real_def_id()
576 .and_then(|id| self.tcx.intrinsic(id))
577 .map(|i| i.name.to_ident_string());
578
579 let body = if intrinsic_name.as_deref() == Some("type_id") {
580 self.build_type_id_body(span, def, &signature)?
581 } else if let Some(name) = intrinsic_name {
582 let arg_names = self.translate_argument_names(span, def, signature.inputs.len());
583 Body::Intrinsic { name, arg_names }
584 } else if let Some(name) = self.t_ctx.extern_item_symbol_name(def) {
585 Body::Extern(name)
586 } else if item_meta.diagnostic_item.as_deref()
587 == Some(names::BOX_ASSUME_INIT_INTO_VEC_UNSAFE)
588 && self.options.treat_box_as_builtin
589 {
590 self.build_box_assume_init_into_vec_unsafe(span, def)?
593 } else if item_meta.lang_item.as_ref() == Some(&from_rustc::LangItem::DropGlue) {
594 self.build_drop_glue_body(span, def, &signature)?
595 } else if item_meta.opacity.with_private_contents().is_opaque() {
596 Body::Opaque
597 } else {
598 self.translate_def_body(item_meta.span, def)
600 };
601 Ok(FunDecl {
602 def_id,
603 item_meta,
604 generics: self.into_generics(),
605 signature: Box::new(signature),
606 src,
607 body,
608 })
609 }
610
611 #[tracing::instrument(skip(self, item_meta, def))]
613 pub fn translate_global(
614 mut self,
615 def_id: GlobalDeclId,
616 item_meta: ItemMeta,
617 def: &hax::FullDef<'tcx>,
618 ) -> Result<GlobalDecl, Error> {
619 let span = item_meta.span;
620
621 let item_source = match self.get_trait_item_source(span, def)? {
623 None => GlobalSource::Normal,
624 Some(TraitItemSource::Default { trait_ref, item_id }) => GlobalSource::TraitDefault {
625 trait_ref,
626 item_id: *item_id.as_const().unwrap(),
627 },
628 Some(TraitItemSource::Impl {
629 impl_ref,
630 trait_ref,
631 item_id,
632 reuses_default,
633 }) => GlobalSource::TraitImpl {
634 impl_ref,
635 trait_ref,
636 item_id: *item_id.as_const().unwrap(),
637 reuses_default,
638 },
639 };
640
641 trace!("Translating global type");
642 let ty = match &def.kind {
643 hax::FullDefKind::Const { ty, .. }
644 | hax::FullDefKind::AssocConst { ty, .. }
645 | hax::FullDefKind::Static { ty, .. } => ty,
646 _ => panic!("Unexpected def for constant: {def:?}"),
647 };
648 let ty = self.translate_ty(span, ty)?;
649
650 let global_kind = match &def.kind {
651 hax::FullDefKind::Static {
652 thread_local: true, ..
653 } => GlobalKind::ThreadLocal,
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 value = if matches!(self.options.consts, ConstHandling::Values)
668 && let Some(evaluated) = self.evaluate_const_def(def)
669 {
670 self.translate_constant_expr(span, &evaluated)?
671 } else {
672 let initializer = self.register_item(span, def.this(), TransItemSourceKind::Fun);
675 ConstantExpr {
676 kind: ConstantExprKind::Call(
677 FnPtr::new(
678 FnPtrKind::Fun(FunId::Regular(initializer)),
679 self.outermost_generics().identity_args(),
680 ),
681 vec![],
682 ),
683 ty: ty.clone(),
684 }
685 };
686
687 Ok(GlobalDecl {
688 def_id,
689 item_meta,
690 generics: self.into_generics(),
691 ty,
692 src: item_source,
693 global_kind,
694 value,
695 })
696 }
697
698 #[tracing::instrument(skip(self, item_meta, def))]
700 pub fn translate_trait_decl(
701 mut self,
702 trait_decl_id: TraitDeclId,
703 item_meta: ItemMeta,
704 def: &hax::FullDef<'tcx>,
705 ) -> Result<TraitDecl, Error> {
706 let span = item_meta.span;
707
708 let (hax::FullDefKind::Trait {
709 implied_predicates, ..
710 }
711 | hax::FullDefKind::TraitAlias {
712 implied_predicates, ..
713 }) = def.kind()
714 else {
715 raise_error!(self, span, "Unexpected definition: {def:?}");
716 };
717 let src = match def.kind() {
718 hax::FullDefKind::Trait { .. } => TraitDeclSource::Normal,
719 hax::FullDefKind::TraitAlias { .. } => TraitDeclSource::TraitAlias,
720 _ => unreachable!(),
721 };
722
723 let mut implied_clauses = Default::default();
726 self.translate_predicates(
727 implied_predicates,
728 PredicateOrigin::WhereClauseOnTrait,
729 Some(&mut implied_clauses),
730 )?;
731
732 let vtable = self.translate_vtable_struct_ref_no_enqueue(span, def.this())?;
733
734 if let hax::FullDefKind::TraitAlias { .. } = def.kind() {
735 return Ok(TraitDecl {
737 def_id: trait_decl_id,
738 item_meta,
739 src,
740 implied_clauses,
741 generics: self.into_generics(),
742 consts: Default::default(),
743 types: Default::default(),
744 methods: Default::default(),
745 vtable,
746 });
747 }
748
749 let hax::FullDefKind::Trait {
750 items,
751 self_predicate,
752 ..
753 } = &def.kind
754 else {
755 unreachable!()
756 };
757 let self_trait_ref = TraitRef::new(
758 TraitRefKind::SelfId,
759 RegionBinder::empty(self.translate_trait_predicate(span, self_predicate)?),
760 );
761
762 self.register_assoc_items(def.def_id(), trait_decl_id)?;
764 let mut consts: IndexMap<AssocConstId, _> = IndexMap::new();
765 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
766 let mut methods: IndexMap<TraitMethodId, _> = IndexMap::new();
767
768 if def.lang_item == Some(sym::destruct) {
769 let destruct_trait_def_id = def.def_id();
771 let method_id =
772 self.translate_drop_glue_method_id(destruct_trait_def_id, trait_decl_id)?;
773 self.mark_method_as_used(trait_decl_id, method_id);
774 let method = {
775 let method_name = self.translated.assoc_item_name(trait_decl_id, method_id);
776 let mut method_item_meta = ItemMeta::dummy_public(
777 span,
778 item_meta.name.clone(),
779 item_meta.is_local,
780 item_meta.opacity,
781 );
782 method_item_meta.name.name.push(PathElem::Ident(
783 method_name.to_string(),
784 Disambiguator::ZERO,
785 ));
786 let self_ty = if self.monomorphize() {
787 Ty::mk_unit()
789 } else {
790 TyKind::TypeVar(DeBruijnVar::bound(DeBruijnId::one(), TypeVarId::ZERO))
791 .into_ty()
792 };
793 let signature = self.drop_glue_method_sig(
794 self_ty,
795 Region::Var(DeBruijnVar::new_at_zero(RegionId::ZERO)),
796 );
797 let method_params = Self::drop_glue_params();
798 Binder::new(
799 BinderKind::TraitMethod(trait_decl_id, method_id),
800 method_params,
801 TraitMethod {
802 name: method_name,
803 default: None,
804 item_meta: method_item_meta,
805 signature,
806 },
807 )
808 };
809 methods.set_slot_extend(method_id, method);
810 }
811
812 if self.monomorphize() {
816 return Ok(TraitDecl {
817 def_id: trait_decl_id,
818 item_meta,
819 src,
820 implied_clauses,
821 generics: self.into_generics(),
822 consts,
823 types,
824 methods,
825 vtable,
826 });
827 }
828
829 for hax_item in items {
830 let item_def_id = &hax_item.def_id;
831 let item_span = self.def_span(item_def_id);
832 let assoc_item_id = self.translate_assoc_item_id(trait_decl_id, item_def_id)?;
833 let item_name = self
834 .translated
835 .assoc_item_name(trait_decl_id, assoc_item_id);
836
837 let trans_kind = match hax_item.kind {
840 hax::AssocKind::Fn { .. } => TransItemSourceKind::Fun,
841 hax::AssocKind::Const { .. } => TransItemSourceKind::Global,
842 hax::AssocKind::Type { .. } => TransItemSourceKind::Type,
843 };
844
845 let item_def = self.poly_hax_def(item_def_id)?;
846 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
847 let attr_info = self.translate_attr_info(&item_def);
848
849 match item_def.kind() {
850 hax::FullDefKind::AssocFn {
851 sig,
852 associated_item,
853 ..
854 } => {
855 let trait_method_id = *assoc_item_id.as_method().unwrap();
856 let method_name = self.translate_name(&item_src)?;
857 let method_opacity = self.opacity_for_name(&method_name);
858 let method_item_meta =
859 self.translate_item_meta(&item_def, &item_src, method_name, method_opacity);
860 if self.options.translate_all_methods
863 || item_meta.opacity.is_transparent()
864 || !hax_item.has_value
865 {
866 self.mark_method_as_used(trait_decl_id, trait_method_id);
867 }
868 let default_fun_id = associated_item.has_value.then(|| {
869 let fun_id = self.register_no_enqueue(item_span, &item_src);
870 self.register_method_impl(trait_decl_id, trait_method_id, fun_id);
872 fun_id
873 });
874
875 let binder_kind = BinderKind::TraitMethod(trait_decl_id, trait_method_id);
876 let mut method = self.translate_binder_for_def(
877 item_span,
878 binder_kind,
879 &item_def,
880 |bt_ctx| {
881 assert_eq!(bt_ctx.binding_levels.len(), 2);
882 let default = default_fun_id.map(|id| {
883 let fun_generics = bt_ctx
884 .outermost_binder()
885 .params
886 .identity_args_at_depth(DeBruijnId::one())
887 .concat(
888 &bt_ctx
889 .innermost_binder()
890 .params
891 .identity_args_at_depth(DeBruijnId::zero()),
892 );
893 FunDeclRef {
894 id,
895 generics: Box::new(fun_generics),
896 }
897 });
898 let signature =
901 bt_ctx.translate_fun_sig(span, sig.hax_skip_binder_ref())?;
902 Ok(TraitMethod {
903 name: item_name,
904 item_meta: method_item_meta,
905 signature,
906 default,
907 })
908 },
909 )?;
910 struct ReplaceSelfVisitor;
915 impl VarsVisitor for ReplaceSelfVisitor {
916 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
917 if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
918 Some(if let Some(new_id) = clause_id.index().checked_sub(1) {
920 TraitRefKind::Clause(DeBruijnVar::Bound(
921 DeBruijnId::ZERO,
922 TraitClauseId::new(new_id),
923 ))
924 } else {
925 TraitRefKind::SelfId
926 })
927 } else {
928 None
929 }
930 }
931 }
932 method.params.visit_vars(&mut ReplaceSelfVisitor);
933 method.skip_binder.visit_vars(&mut ReplaceSelfVisitor);
934 method
935 .params
936 .trait_clauses
937 .remove_and_shift_ids(TraitClauseId::ZERO);
938 method.params.trait_clauses.iter_mut().for_each(|clause| {
939 clause.clause_id -= 1;
940 });
941
942 methods.set_slot_extend(trait_method_id, method);
945 }
946 hax::FullDefKind::AssocConst { ty, .. } => {
947 let assoc_const_id = *assoc_item_id.as_const().unwrap();
948 let bound_assoc_const = self.translate_binder_for_def(
951 item_span,
952 BinderKind::Other,
953 &item_def,
954 |ctx| {
955 let default = hax_item.has_value.then(|| {
957 let id = ctx.register_and_enqueue(item_span, item_src);
960 let generics = ctx
961 .outermost_binder()
962 .params
963 .identity_args_at_depth(DeBruijnId::one())
964 .concat(
965 &ctx.innermost_binder()
966 .params
967 .identity_args_at_depth(DeBruijnId::zero()),
968 );
969 GlobalDeclRef {
970 id,
971 generics: Box::new(generics),
972 }
973 });
974 let ty = ctx.translate_ty(item_span, ty)?;
975 Ok(TraitAssocConst {
976 name: item_name,
977 attr_info,
978 ty,
979 default,
980 })
981 },
982 )?;
983 let assoc_const = bound_assoc_const.apply(&{
984 let mut generics = GenericArgs::empty();
985 generics.trait_refs.push(self_trait_ref.clone());
987 generics
988 });
989 consts.set_slot_extend(assoc_const_id, assoc_const);
990 }
991 hax::FullDefKind::AssocTy {
992 implied_predicates,
993 value: default,
994 ..
995 } => {
996 let assoc_type_id = *assoc_item_id.as_type().unwrap();
997 let binder_kind = BinderKind::TraitType(trait_decl_id, assoc_type_id);
998 let assoc_ty =
999 self.translate_binder_for_def(item_span, binder_kind, &item_def, |ctx| {
1000 let mut implied_clauses = Default::default();
1002 ctx.translate_predicates(
1003 implied_predicates,
1004 PredicateOrigin::TraitItem(assoc_type_id),
1005 Some(&mut implied_clauses),
1006 )?;
1007
1008 let default = default
1009 .as_ref()
1010 .map(|(ty, trait_proofs)| -> Result<_, Error> {
1011 let ty = ctx.translate_ty(item_span, ty)?;
1012 let trefs = ctx.translate_trait_proofs(span, trait_proofs)?;
1013 Ok(TraitAssocTyImpl {
1014 value: ty,
1015 implied_trait_refs: trefs,
1016 })
1017 })
1018 .transpose()?;
1019 Ok(TraitAssocTy {
1020 name: item_name,
1021 attr_info,
1022 default,
1023 implied_clauses,
1024 })
1025 })?;
1026 types.set_slot_extend(assoc_type_id, assoc_ty);
1027 }
1028 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
1029 }
1030 }
1031
1032 Ok(TraitDecl {
1036 def_id: trait_decl_id,
1037 item_meta,
1038 src,
1039 implied_clauses,
1040 generics: self.into_generics(),
1041 consts,
1042 types,
1043 methods,
1044 vtable,
1045 })
1046 }
1047
1048 #[tracing::instrument(skip(self, item_meta, def))]
1049 pub fn translate_trait_impl(
1050 mut self,
1051 def_id: TraitImplId,
1052 item_meta: ItemMeta,
1053 def: &hax::FullDef<'tcx>,
1054 ) -> Result<TraitImpl, Error> {
1055 let span = item_meta.span;
1056
1057 let hax::FullDefKind::TraitImpl {
1058 trait_pred,
1059 implied_trait_proofs,
1060 items: impl_items,
1061 ..
1062 } = &def.kind
1063 else {
1064 unreachable!()
1065 };
1066
1067 let implemented_trait = self.translate_trait_ref(span, &trait_pred.trait_ref)?;
1069 let trait_id = implemented_trait.id;
1070 let self_predicate = TraitRef::new(
1072 TraitRefKind::TraitImpl(TraitImplRef {
1073 id: def_id,
1074 generics: Box::new(self.the_only_binder().params.identity_args()),
1075 }),
1076 RegionBinder::empty(implemented_trait.clone()),
1077 );
1078
1079 let vtable =
1080 self.translate_vtable_instance_ref_no_enqueue(span, &trait_pred.trait_ref, def.this())?;
1081
1082 let implied_trait_refs = self.translate_trait_proofs(span, implied_trait_proofs)?;
1084
1085 {
1086 let ctx = self.into_fmt();
1088 let refs = implied_trait_refs
1089 .iter()
1090 .map(|c| c.with_ctx(&ctx))
1091 .format("\n");
1092 trace!(
1093 "Trait impl: {:?}\n- implied_trait_refs:\n{}",
1094 def.def_id(),
1095 refs
1096 );
1097 }
1098
1099 let implemented_trait_def = self.poly_hax_def(&trait_pred.trait_ref.def_id)?;
1100 if implemented_trait_def.lang_item == Some(sym::destruct) {
1101 raise_error!(
1102 self,
1103 span,
1104 "found an explicit impl of `core::marker::Destruct`, this should not happen"
1105 );
1106 }
1107
1108 let mut consts: IndexMap<AssocConstId, _> = IndexMap::new();
1110 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
1111 let mut methods: IndexMap<TraitMethodId, _> = IndexMap::new();
1112
1113 if self.monomorphize() {
1115 return Ok(TraitImpl {
1116 def_id,
1117 item_meta,
1118 src: TraitImplSource::Normal,
1119 impl_trait: implemented_trait,
1120 generics: self.into_generics(),
1121 implied_trait_refs,
1122 consts,
1123 types,
1124 methods,
1125 vtable,
1126 });
1127 }
1128
1129 for impl_item in impl_items {
1130 let item_def_id = impl_item.def_id().unwrap_or(impl_item.decl_def_id());
1131 let item_span = self.def_span(item_def_id);
1132 let assoc_item_id = self.translate_assoc_item_id(trait_id, item_def_id)?;
1133
1134 let item_def = self.poly_hax_def(item_def_id)?;
1136 let trans_kind = match item_def.kind() {
1137 hax::FullDefKind::AssocFn { .. } => TransItemSourceKind::Fun,
1138 hax::FullDefKind::AssocConst { .. } => TransItemSourceKind::Global,
1139 hax::FullDefKind::AssocTy { .. } => TransItemSourceKind::Type,
1140 _ => unreachable!(),
1141 };
1142 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
1143
1144 match item_def.kind() {
1145 hax::FullDefKind::AssocFn { .. } => {
1146 let trait_method_id = *assoc_item_id.as_method().unwrap();
1147 let binder_kind = BinderKind::TraitMethod(trait_id, trait_method_id);
1148 let bound_fn_ref = match &impl_item.value {
1149 Some(value) => {
1150 if item_meta.opacity.is_transparent() {
1153 self.mark_method_as_used(trait_id, trait_method_id);
1154 }
1155 self.translate_item_binder(
1156 item_span,
1157 binder_kind,
1158 value,
1159 PredicateOrigin::WhereClauseOnFn,
1160 |ctx, value| {
1161 let bound_fn_ptr = ctx.translate_bound_fn_ptr_no_enqueue(
1162 item_span,
1163 &value.item,
1164 TransItemSourceKind::Fun,
1165 )?;
1166 let late_bound_regions = ctx
1168 .innermost_binder()
1169 .bound_region_vars
1170 .iter()
1171 .map(|rid| Region::Var(DeBruijnVar::new_at_zero(*rid)))
1172 .collect();
1173 let fn_ptr = bound_fn_ptr.apply(late_bound_regions);
1174 Ok(FunDeclRef {
1175 id: *fn_ptr.kind.as_fun().unwrap().as_regular().unwrap(),
1176 generics: fn_ptr.generics,
1177 })
1178 },
1179 )?
1180 }
1181 None => {
1182 let bound_method = match self.get_or_translate(trait_id.into()) {
1184 Ok(ItemRef::TraitDecl(tdecl)) => {
1185 tdecl.methods.get(trait_method_id).cloned()
1186 }
1187 _ => None,
1188 };
1189 let Some(bound_method) = bound_method else {
1190 continue;
1191 };
1192 bound_method
1193 .substitute_with_tref(&self_predicate)
1194 .map(|method| {
1195 method
1196 .default
1197 .expect("default method should have a default")
1198 })
1199 }
1200 };
1201
1202 self.register_method_impl(
1204 trait_id,
1205 trait_method_id,
1206 bound_fn_ref.skip_binder.id,
1207 );
1208
1209 methods.set_slot_extend(trait_method_id, bound_fn_ref);
1212 }
1213 hax::FullDefKind::AssocConst { .. } => {
1214 let assoc_const_id = *assoc_item_id.as_const().unwrap();
1215 let id = self.register_and_enqueue(item_span, item_src);
1216 let generics = match &impl_item.value {
1219 Some(_) => self.the_only_binder().params.identity_args(),
1220 None => {
1221 let mut generics = implemented_trait.generics.as_ref().clone();
1222 generics.trait_refs.push(self_predicate.clone());
1224 generics
1225 }
1226 };
1227 let gref = GlobalDeclRef {
1228 id,
1229 generics: Box::new(generics),
1230 };
1231 consts.set_slot_extend(assoc_const_id, gref);
1232 }
1233 hax::FullDefKind::AssocTy { .. } => {
1234 let assoc_type_id = *assoc_item_id.as_type().unwrap();
1235 let binder_kind = BinderKind::TraitType(trait_id, assoc_type_id);
1236 let assoc_ty = match &impl_item.value {
1237 Some(impl_value) => self.translate_item_binder(
1238 item_span,
1239 binder_kind,
1240 impl_value,
1241 PredicateOrigin::WhereClauseOnType,
1242 |ctx, impl_value| {
1243 let ty = ctx.translate_ty(
1244 item_span,
1245 impl_value.assoc_ty_value.as_ref().unwrap(),
1246 )?;
1247 let implied_trait_refs = ctx.translate_trait_proofs(
1248 item_span,
1249 &impl_value.implied_trait_proofs,
1250 )?;
1251 Ok(TraitAssocTyImpl {
1252 value: ty,
1253 implied_trait_refs,
1254 })
1255 },
1256 )?,
1257 None => {
1258 let trait_id = implemented_trait.id;
1260 let bound_ty = match self.get_or_translate(trait_id.into()) {
1261 Ok(ItemRef::TraitDecl(tdecl)) => tdecl.types.get(assoc_type_id),
1262 _ => None,
1263 };
1264 let Some(bound_ty) = bound_ty else {
1265 register_error!(
1266 self,
1267 item_span,
1268 "couldn't translate defaulted associated type; \
1269 either the corresponding trait decl caused errors \
1270 or it was declared opaque."
1271 );
1272 continue;
1273 };
1274 bound_ty
1275 .clone()
1276 .substitute_with_tref(&self_predicate)
1277 .map(|ty_decl: TraitAssocTy| ty_decl.default.unwrap())
1278 }
1279 };
1280
1281 types.set_slot_extend(assoc_type_id, assoc_ty);
1282 }
1283 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
1284 }
1285 }
1286
1287 Ok(TraitImpl {
1288 def_id,
1289 item_meta,
1290 src: TraitImplSource::Normal,
1291 impl_trait: implemented_trait,
1292 generics: self.into_generics(),
1293 implied_trait_refs,
1294 consts,
1295 types,
1296 methods,
1297 vtable,
1298 })
1299 }
1300
1301 #[tracing::instrument(skip(self, item_meta, def))]
1311 pub fn translate_trait_alias_blanket_impl(
1312 mut self,
1313 def_id: TraitImplId,
1314 item_meta: ItemMeta,
1315 def: &hax::FullDef<'tcx>,
1316 ) -> Result<TraitImpl, Error> {
1317 let span = item_meta.span;
1318
1319 let hax::FullDefKind::TraitAlias {
1320 implied_predicates,
1321 self_predicate,
1322 ..
1323 } = &def.kind
1324 else {
1325 raise_error!(self, span, "Unexpected definition: {def:?}");
1326 };
1327
1328 let implemented_trait = self.translate_trait_ref(span, &self_predicate.trait_ref)?;
1330
1331 assert!(self.innermost_generics_mut().trait_clauses.is_empty());
1333 self.register_predicates(implied_predicates, PredicateOrigin::WhereClauseOnTrait)?;
1334
1335 let mut generics = self.the_only_binder().params.identity_args();
1336 let implied_trait_refs = mem::take(&mut generics.trait_refs);
1338
1339 let mut timpl = TraitImpl {
1340 def_id,
1341 item_meta,
1342 src: TraitImplSource::TraitAlias,
1343 impl_trait: implemented_trait,
1344 generics: self.the_only_binder().params.clone(),
1345 implied_trait_refs,
1346 consts: Default::default(),
1347 types: Default::default(),
1348 methods: Default::default(),
1349 vtable: None,
1351 };
1352 {
1355 struct FixSelfVisitor {
1356 binder_depth: DeBruijnId,
1357 }
1358 struct UnhandledSelf;
1359 impl Visitor for FixSelfVisitor {
1360 type Break = UnhandledSelf;
1361 }
1362 impl VisitorWithBinderDepth for FixSelfVisitor {
1363 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1364 &mut self.binder_depth
1365 }
1366 }
1367 impl VisitAstMut for FixSelfVisitor {
1368 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
1369 VisitWithBinderDepth::new(self).visit(x)
1370 }
1371 fn visit_trait_ref_kind(
1372 &mut self,
1373 kind: &mut TraitRefKind,
1374 ) -> ControlFlow<Self::Break> {
1375 match kind {
1376 TraitRefKind::SelfId => return ControlFlow::Break(UnhandledSelf),
1377 TraitRefKind::ParentClause(sub, clause_id)
1378 if matches!(sub.kind, TraitRefKind::SelfId) =>
1379 {
1380 *kind = TraitRefKind::Clause(DeBruijnVar::bound(
1381 self.binder_depth,
1382 *clause_id,
1383 ))
1384 }
1385 _ => (),
1386 }
1387 self.visit_inner(kind)
1388 }
1389 }
1390 match timpl.drive_mut(&mut FixSelfVisitor {
1391 binder_depth: DeBruijnId::zero(),
1392 }) {
1393 ControlFlow::Continue(()) => {}
1394 ControlFlow::Break(UnhandledSelf) => {
1395 register_error!(
1396 self,
1397 span,
1398 "Found `Self` clause we can't handle \
1399 in a trait alias blanket impl."
1400 );
1401 }
1402 }
1403 };
1404
1405 Ok(timpl)
1406 }
1407
1408 #[tracing::instrument(skip(self, item_meta))]
1411 pub fn translate_virtual_trait_impl(
1412 &mut self,
1413 def_id: TraitImplId,
1414 item_meta: ItemMeta,
1415 src: TraitImplSource,
1416 vimpl: &hax::VirtualTraitImpl,
1417 ) -> Result<TraitImpl, Error> {
1418 let span = item_meta.span;
1419 let trait_def = self.hax_def(&vimpl.trait_pred.trait_ref)?;
1420 let hax::FullDefKind::Trait {
1421 items: trait_items, ..
1422 } = trait_def.kind()
1423 else {
1424 panic!()
1425 };
1426
1427 let implemented_trait = self.translate_trait_predicate(span, &vimpl.trait_pred)?;
1428 let implied_trait_refs = self.translate_trait_proofs(span, &vimpl.implied_trait_proofs)?;
1429
1430 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
1431 if !self.monomorphize() {
1433 let type_items = trait_items
1434 .iter()
1435 .filter(|assoc| matches!(assoc.kind, hax::AssocKind::Type { .. }));
1436 for ((ty, trait_proofs), assoc) in vimpl.types.iter().zip(type_items) {
1437 let assoc_type_id =
1438 self.translate_assoc_type_id(implemented_trait.id, &assoc.def_id)?;
1439 let assoc_ty = TraitAssocTyImpl {
1440 value: self.translate_ty(span, ty)?,
1441 implied_trait_refs: self.translate_trait_proofs(span, trait_proofs)?,
1442 };
1443 let binder_kind = BinderKind::TraitType(implemented_trait.id, assoc_type_id);
1444 types.set_slot_extend(assoc_type_id, Binder::empty(binder_kind, assoc_ty));
1445 }
1446 }
1447
1448 let generics = self.the_only_binder().params.clone();
1449 Ok(TraitImpl {
1450 def_id,
1451 item_meta,
1452 src,
1453 impl_trait: implemented_trait,
1454 generics,
1455 implied_trait_refs,
1456 consts: IndexMap::new(),
1457 types,
1458 methods: IndexMap::new(),
1459 vtable: None,
1461 })
1462 }
1463}