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 _guard = charon_lib::timing::scope_lazy("translate-item", || {
18 let kind = format!("{:?}", item_src.kind);
19 kind.split('(').next().unwrap().to_owned()
20 });
21 let trans_id = self.register_no_enqueue(&None, item_src);
22 let def_id = item_src.def_id();
23 if let Some(trans_id) = trans_id {
24 if self.translate_stack.contains(&trans_id) {
25 register_error!(
26 self,
27 Span::dummy(),
28 "Cycle detected while translating {def_id:?}! Stack: {:?}",
29 &self.translate_stack
30 );
31 return;
32 } else {
33 self.translate_stack.push(trans_id);
34 }
35 }
36 self.with_def_id(def_id, trans_id, |mut ctx| {
37 let span = ctx.def_span(def_id);
38 let res = {
40 let mut ctx = std::panic::AssertUnwindSafe(&mut ctx);
42 std::panic::catch_unwind(move || ctx.translate_item_aux(item_src, trans_id))
43 };
44 match res {
45 Ok(Ok(())) => return,
46 Ok(Err(_)) => {
48 register_error!(ctx, span, "Item `{def_id:?}` caused errors; ignoring.")
49 }
50 Err(_) => register_error!(
52 ctx,
53 span,
54 "Thread panicked when extracting item `{def_id:?}`."
55 ),
56 };
57 });
58 self.translate_stack.pop();
60 }
61
62 pub(crate) fn translate_item_aux(
63 &mut self,
64 item_src: &TransItemSource,
65 trans_id: Option<ItemId>,
66 ) -> Result<(), Error> {
67 let name = self.translate_name(item_src)?;
69 if let Some(trans_id) = trans_id {
70 self.translated.item_names.insert(trans_id, name.clone());
71 }
72 let opacity = self.opacity_for_name(&name);
73 if opacity.is_invisible() {
74 return Ok(());
76 }
77 let def = self.hax_def_for_item(&item_src.item)?;
78 let item_meta = self.translate_item_meta(&def, item_src, name, opacity);
79 if item_meta.opacity.is_invisible() {
80 return Ok(());
81 }
82
83 if !item_meta.opacity.is_opaque()
86 && let Some(def_id) = def.def_id().as_real_def_id()
87 && let Some(ldid) = def_id.as_local()
88 && let node = self.tcx.hir_node_by_def_id(ldid)
89 && let Some(body_id) = node.body_id()
90 {
91 use rustc_hir::intravisit;
92 #[allow(non_local_definitions)]
93 impl<'tcx> intravisit::Visitor<'tcx> for TranslateCtx<'tcx> {
94 fn visit_nested_item(&mut self, id: rustc_hir::ItemId) {
95 let def_id = id.owner_id.def_id.to_def_id();
96 let def_id = def_id.sinto(&self.hax_state);
97 self.enqueue_module_item(&def_id);
98 }
99 }
100 let body = self.tcx.hir_body(body_id);
101 intravisit::walk_body(self, body);
102 }
103
104 let mut bt_ctx = ItemTransCtx::new(item_src.clone(), trans_id, self);
106 trace!(
107 "About to translate item `{:?}` as a {:?}; \
108 target_id={trans_id:?}, mono={}",
109 def.def_id(),
110 item_src.kind,
111 bt_ctx.monomorphize(),
112 );
113 if !matches!(
114 &item_src.kind,
115 TransItemSourceKind::InherentImpl | TransItemSourceKind::Module,
116 ) {
117 bt_ctx.translate_item_generics(item_meta.span, &def, &item_src.kind)?;
118 }
119 match &item_src.kind {
120 TransItemSourceKind::InherentImpl | TransItemSourceKind::Module => {
121 bt_ctx.register_module(item_meta, &def);
122 }
123 TransItemSourceKind::Type => {
124 let Some(ItemId::Type(id)) = trans_id else {
125 unreachable!()
126 };
127 let ty = bt_ctx.translate_type_decl(id, item_meta, &def)?;
128 self.translated.type_decls.set_slot(id, ty);
129 }
130 TransItemSourceKind::Fun => {
131 let Some(ItemId::Fun(id)) = trans_id else {
132 unreachable!()
133 };
134 let fun_decl = bt_ctx.translate_fun_decl(id, item_meta, &def)?;
135 self.translated.fun_decls.set_slot(id, fun_decl);
136 }
137 TransItemSourceKind::Global => {
138 let Some(ItemId::Global(id)) = trans_id else {
139 unreachable!()
140 };
141 let global_decl = bt_ctx.translate_global(id, item_meta, &def)?;
142 self.translated.global_decls.set_slot(id, global_decl);
143 }
144 TransItemSourceKind::TraitDecl => {
145 let Some(ItemId::TraitDecl(id)) = trans_id else {
146 unreachable!()
147 };
148 let trait_decl = bt_ctx.translate_trait_decl(id, item_meta, &def)?;
149 self.translated.trait_decls.set_slot(id, trait_decl);
150 }
151 TransItemSourceKind::TraitImpl(kind) => {
152 let Some(ItemId::TraitImpl(id)) = trans_id else {
153 unreachable!()
154 };
155 let trait_impl = match kind {
157 TransImplSource::Normal => bt_ctx.translate_trait_impl(id, item_meta, &def)?,
158 TransImplSource::TraitAlias => {
159 bt_ctx.translate_trait_alias_blanket_impl(id, item_meta, &def)?
160 }
161 &TransImplSource::Callable(kind) => {
162 bt_ctx.translate_closure_trait_impl(id, item_meta, &def, kind)?
163 }
164 TransImplSource::ImplicitDestruct => {
165 bt_ctx.translate_implicit_destruct_impl(id, item_meta, &def)?
166 }
167 TransImplSource::Marker => {
168 unreachable!("marker impls are only used as vtable item sources")
169 }
170 };
171 self.translated.trait_impls.set_slot(id, trait_impl);
172 }
173 &TransItemSourceKind::CallableMethod(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::DropGlueMethod(impl_kind) => {
188 let Some(ItemId::Fun(id)) = trans_id else {
189 unreachable!()
190 };
191 let fun_decl = bt_ctx.translate_drop_glue_method(id, item_meta, &def, impl_kind)?;
192 self.translated.fun_decls.set_slot(id, fun_decl);
193 }
194 TransItemSourceKind::VTable => {
195 let Some(ItemId::Type(id)) = trans_id else {
196 unreachable!()
197 };
198 let ty_decl = bt_ctx.translate_vtable_struct(id, item_meta, &def)?;
199 self.translated.type_decls.set_slot(id, ty_decl);
200 }
201 &TransItemSourceKind::VTableInstance(impl_kind) => {
202 let Some(ItemId::Global(id)) = trans_id else {
203 unreachable!()
204 };
205 let global_decl =
206 bt_ctx.translate_vtable_instance(id, item_meta, &def, impl_kind)?;
207 self.translated.global_decls.set_slot(id, global_decl);
208 }
209 &TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
210 let Some(ItemId::Fun(id)) = trans_id else {
211 unreachable!()
212 };
213 let fun_decl =
214 bt_ctx.translate_vtable_instance_init(id, item_meta, &def, impl_kind)?;
215 self.translated.fun_decls.set_slot(id, fun_decl);
216 }
217 &TransItemSourceKind::VTableMethod(impl_kind) => {
218 let Some(ItemId::Fun(id)) = trans_id else {
219 unreachable!()
220 };
221 let fun_decl = bt_ctx.translate_vtable_shim(id, item_meta, &def, impl_kind)?;
222 self.translated.fun_decls.set_slot(id, fun_decl);
223 }
224 &TransItemSourceKind::VTableDropShim(impl_kind) => {
225 let Some(ItemId::Fun(id)) = trans_id else {
226 unreachable!()
227 };
228 let fun_decl = bt_ctx.translate_vtable_drop_shim(id, item_meta, &def, impl_kind)?;
229 self.translated.fun_decls.set_slot(id, fun_decl);
230 }
231 }
232 Ok(())
233 }
234
235 pub(crate) fn get_or_translate(&mut self, id: ItemId) -> Result<ItemRef<'_>, Error> {
238 if self.translated.get_item(id).is_none() {
241 let item_source = self.reverse_id_map.get(&id).unwrap().clone();
242 self.translate_item(&item_source);
243 if self.translated.get_item(id).is_none() {
244 let span = self.def_span(item_source.def_id());
245 let name = id.to_string_with_ctx(&self.into_fmt());
246 return Err(Error {
248 span,
249 msg: format!("Failed to translate item {name}."),
250 });
251 }
253 self.processed.insert(item_source.clone());
255 }
256 let item = self.translated.get_item(id);
257 Ok(item.unwrap())
258 }
259
260 pub fn register_method_impl(
264 &mut self,
265 trait_id: TraitDeclId,
266 method_id: TraitMethodId,
267 fun_id: FunDeclId,
268 ) {
269 match &mut self.method_status[trait_id][method_id] {
270 MethodStatus::Unused { implementors } => {
271 implementors.insert(fun_id);
272 }
273 MethodStatus::Used => {
274 self.enqueue_id(fun_id);
275 }
276 }
277 }
278
279 pub fn mark_method_as_used(&mut self, trait_id: TraitDeclId, method_id: TraitMethodId) {
282 let old_status = mem::replace(
283 &mut self.method_status[trait_id][method_id],
284 MethodStatus::Used,
285 );
286 match old_status {
287 MethodStatus::Unused { implementors } => {
288 for fun_id in implementors {
289 self.enqueue_id(fun_id);
290 }
291 }
292 MethodStatus::Used => {}
293 }
294 }
295
296 pub fn remove_unused_methods(&mut self) {
298 let method_is_used = |trait_id: TraitDeclId, method_id: TraitMethodId| {
299 matches!(self.method_status[trait_id][method_id], MethodStatus::Used)
300 };
301 for tdecl in self.translated.trait_decls.iter_mut() {
302 tdecl
303 .methods
304 .retain(|i, _m| method_is_used(tdecl.def_id, i));
305 }
306 for timpl in self.translated.trait_impls.iter_mut() {
307 let trait_id = timpl.impl_trait.id;
308 timpl.methods.retain(|i, _m| method_is_used(trait_id, i));
309 }
310 }
311}
312
313enum TraitItemSource {
314 Default {
315 trait_ref: TraitDeclRef,
316 item_id: AssocItemId,
317 },
318 Impl {
319 impl_ref: TraitImplRef,
320 trait_ref: TraitDeclRef,
321 item_id: AssocItemId,
322 reuses_default: bool,
323 },
324}
325
326impl<'tcx> ItemTransCtx<'tcx, '_> {
327 #[tracing::instrument(skip(self, item_meta, def))]
331 pub(crate) fn register_module(&mut self, item_meta: ItemMeta, def: &hax::FullDef<'tcx>) {
332 if !item_meta.opacity.is_transparent() {
333 return;
334 }
335 match def.kind() {
336 hax::FullDefKind::InherentImpl { items, .. } => {
337 for assoc in items {
338 self.t_ctx.enqueue_module_item(&assoc.def_id);
339 }
340 }
341 hax::FullDefKind::Mod { items, .. } => {
342 for (_, def_id) in items {
343 self.t_ctx.enqueue_module_item(def_id);
344 }
345 }
346 hax::FullDefKind::ForeignMod { items, .. } => {
347 for def_id in items {
348 self.t_ctx.enqueue_module_item(def_id);
349 }
350 }
351 _ => panic!("Item should be a module but isn't: {def:?}"),
352 }
353 }
354
355 fn get_trait_item_source(
356 &mut self,
357 span: Span,
358 def: &hax::FullDef<'tcx>,
359 ) -> Result<Option<TraitItemSource>, Error> {
360 let assoc = match def.kind() {
361 hax::FullDefKind::AssocConst {
362 associated_item, ..
363 }
364 | hax::FullDefKind::AssocFn {
365 associated_item, ..
366 } => associated_item,
367 _ => return Ok(None),
368 };
369 Ok(Some(match &assoc.container {
370 hax::AssocItemContainer::InherentImplContainer { .. } => return Ok(None),
377 hax::AssocItemContainer::TraitImplContainer {
384 impl_,
385 implemented_trait_ref,
386 overrides_default,
387 ..
388 } => {
389 let impl_ref =
390 self.translate_trait_impl_ref(span, impl_, TransImplSource::Normal)?;
391 let trait_ref = self.translate_trait_ref(span, implemented_trait_ref)?;
392 let item_id = self.translate_assoc_item_id(trait_ref.id, def.def_id())?;
393 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
394 let method_id = *item_id.as_method().unwrap();
397 self.mark_method_as_used(trait_ref.id, method_id);
398 }
399 TraitItemSource::Impl {
400 impl_ref,
401 trait_ref,
402 item_id,
403 reuses_default: !overrides_default,
404 }
405 }
406 hax::AssocItemContainer::TraitContainer { trait_ref, .. } => {
414 let trait_ref = self.translate_trait_ref(span, trait_ref)?;
417 let item_id = self.translate_assoc_item_id(trait_ref.id, def.def_id())?;
418 if matches!(def.kind(), hax::FullDefKind::AssocFn { .. }) {
419 let method_id = *item_id.as_method().unwrap();
422 self.mark_method_as_used(trait_ref.id, method_id);
423 }
424 debug_assert!(assoc.has_value);
425 TraitItemSource::Default { trait_ref, item_id }
426 }
427 }))
428 }
429
430 #[tracing::instrument(skip(self, item_meta, def))]
436 pub fn translate_type_decl(
437 mut self,
438 trans_id: TypeDeclId,
439 item_meta: ItemMeta,
440 def: &hax::FullDef<'tcx>,
441 ) -> Result<TypeDecl, Error> {
442 let span = item_meta.span;
443
444 let src = if let hax::FullDefKind::Closure { args, .. } = def.kind() {
446 let info = self.translate_closure_info(span, args)?;
447 TypeSource::Closure { info }
448 } else if let Some(builtin) = self.recognize_builtin_adt(def.this()) {
449 TypeSource::Builtin(builtin)
450 } else {
451 TypeSource::Normal
452 };
453
454 let kind = match &def.kind {
456 _ if item_meta.opacity.is_opaque() => Ok(TypeDeclKind::Opaque),
457 hax::FullDefKind::OpaqueTy | hax::FullDefKind::ForeignTy => Ok(TypeDeclKind::Opaque),
458 hax::FullDefKind::TyAlias { ty, .. } => {
459 self.error_on_trait_proof_error = false;
461 self.translate_ty(span, ty).map(TypeDeclKind::Alias)
462 }
463 hax::FullDefKind::Adt { .. } => self.translate_adt_def(trans_id, span, &item_meta, def),
464 hax::FullDefKind::Closure { args, .. } => self.translate_closure_adt(span, args),
465 _ => panic!("Unexpected item when translating types: {def:?}"),
466 };
467
468 let kind = match kind {
469 Ok(kind) => kind,
470 Err(err) => TypeDeclKind::Error(err.msg),
471 };
472 let layout = self
473 .translate_layout(span, def, &kind)
474 .into_iter()
475 .map(|l| (self.get_target_triple(), l))
476 .collect();
477 let ptr_metadata = self.translate_ptr_metadata(span, def.this())?;
478 Ok(TypeDecl {
479 def_id: trans_id,
480 item_meta,
481 generics: self.into_generics(),
482 kind,
483 src,
484 layout,
485 ptr_metadata,
486 })
487 }
488
489 #[tracing::instrument(skip(self, item_meta, def))]
491 pub fn translate_fun_decl(
492 mut self,
493 def_id: FunDeclId,
494 item_meta: ItemMeta,
495 def: &hax::FullDef<'tcx>,
496 ) -> Result<FunDecl, Error> {
497 let span = item_meta.span;
498
499 let src = if matches!(
500 def.kind(),
501 hax::FullDefKind::Const { .. }
502 | hax::FullDefKind::AssocConst { .. }
503 | hax::FullDefKind::Static { .. }
504 ) {
505 let global_id = self.register_item(span, def.this(), TransItemSourceKind::Global);
506 FunSource::GlobalInitializer(GlobalDeclRef {
507 id: global_id,
508 generics: Box::new(self.outermost_generics().identity_args()),
509 })
510 } else if matches!(def.kind(), hax::FullDefKind::Ctor { .. }) {
511 FunSource::AdtConstructor
512 } else {
513 match self.get_trait_item_source(span, def)? {
514 None => FunSource::Normal,
515 Some(TraitItemSource::Default { trait_ref, item_id }) => FunSource::TraitDefault {
516 trait_ref,
517 item_id: *item_id.as_method().unwrap(),
518 },
519 Some(TraitItemSource::Impl {
520 impl_ref,
521 trait_ref,
522 item_id,
523 reuses_default,
524 }) => FunSource::TraitImpl {
525 impl_ref,
526 trait_ref,
527 item_id: *item_id.as_method().unwrap(),
528 reuses_default,
529 },
530 }
531 };
532
533 if let hax::FullDefKind::Ctor {
534 fields, output_ty, ..
535 } = def.kind()
536 {
537 let signature = FunSig {
538 inputs: fields
539 .iter()
540 .map(|field| self.translate_ty(span, &field.ty))
541 .try_collect()?,
542 output: self.translate_ty(span, output_ty)?,
543 is_unsafe: false,
544 abi: Abi::rust(),
545 is_variadic: false,
546 };
547
548 let body = if item_meta.opacity.with_private_contents().is_opaque() {
549 Body::Opaque
550 } else {
551 self.build_ctor_body(span, def)?
552 };
553 return Ok(FunDecl {
554 def_id,
555 item_meta,
556 generics: self.into_generics(),
557 signature: Box::new(signature),
558 src,
559 body,
560 });
561 }
562
563 trace!("Translating function signature");
565 let signature = match &def.kind {
566 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
567 self.translate_fun_sig(span, &sig.value)?
568 }
569 hax::FullDefKind::Const { ty, .. }
570 | hax::FullDefKind::AssocConst { ty, .. }
571 | hax::FullDefKind::Static { ty, .. } => FunSig {
572 inputs: vec![],
573 output: self.translate_ty(span, ty)?,
574 is_unsafe: false,
575 abi: Abi::rust(),
576 is_variadic: false,
577 },
578 _ => panic!("Unexpected definition for function: {def:?}"),
579 };
580
581 let intrinsic_name = def
582 .def_id()
583 .as_real_def_id()
584 .and_then(|id| self.tcx.intrinsic(id))
585 .map(|i| i.name.to_ident_string());
586
587 let body = if intrinsic_name.as_deref() == Some("type_id") {
588 self.build_type_id_body(span, def, &signature)?
589 } else if let Some(name) = intrinsic_name {
590 let arg_names = self.translate_argument_names(span, def, signature.inputs.len());
591 Body::Intrinsic { name, arg_names }
592 } else if let Some(name) = self.t_ctx.extern_item_symbol_name(def) {
593 Body::Extern(name)
594 } else if item_meta.diagnostic_item.as_deref()
595 == Some(names::BOX_ASSUME_INIT_INTO_VEC_UNSAFE)
596 && self.options.treat_box_as_builtin
597 {
598 self.build_box_assume_init_into_vec_unsafe(span, def)?
601 } else if item_meta.lang_item.as_ref() == Some(&from_rustc::LangItem::DropGlue) {
602 self.build_drop_glue_body(span, def, &signature)?
603 } else if item_meta.opacity.with_private_contents().is_opaque() {
604 Body::Opaque
605 } else {
606 self.translate_def_body(item_meta.span, def)
608 };
609 Ok(FunDecl {
610 def_id,
611 item_meta,
612 generics: self.into_generics(),
613 signature: Box::new(signature),
614 src,
615 body,
616 })
617 }
618
619 #[tracing::instrument(skip(self, item_meta, def))]
621 pub fn translate_global(
622 mut self,
623 def_id: GlobalDeclId,
624 item_meta: ItemMeta,
625 def: &hax::FullDef<'tcx>,
626 ) -> Result<GlobalDecl, Error> {
627 let span = item_meta.span;
628
629 let item_source = match self.get_trait_item_source(span, def)? {
631 None => GlobalSource::Normal,
632 Some(TraitItemSource::Default { trait_ref, item_id }) => GlobalSource::TraitDefault {
633 trait_ref,
634 item_id: *item_id.as_const().unwrap(),
635 },
636 Some(TraitItemSource::Impl {
637 impl_ref,
638 trait_ref,
639 item_id,
640 reuses_default,
641 }) => GlobalSource::TraitImpl {
642 impl_ref,
643 trait_ref,
644 item_id: *item_id.as_const().unwrap(),
645 reuses_default,
646 },
647 };
648
649 trace!("Translating global type");
650 let ty = match &def.kind {
651 hax::FullDefKind::Const { ty, .. }
652 | hax::FullDefKind::AssocConst { ty, .. }
653 | hax::FullDefKind::Static { ty, .. } => ty,
654 _ => panic!("Unexpected def for constant: {def:?}"),
655 };
656 let ty = self.translate_ty(span, ty)?;
657
658 let global_kind = match &def.kind {
659 hax::FullDefKind::Static {
660 thread_local: true, ..
661 } => GlobalKind::ThreadLocal,
662 hax::FullDefKind::Static { .. } => GlobalKind::Static,
663 hax::FullDefKind::Const {
664 kind: hax::ConstKind::TopLevel,
665 ..
666 }
667 | hax::FullDefKind::AssocConst { .. } => GlobalKind::NamedConst,
668 hax::FullDefKind::Const { .. } => GlobalKind::AnonConst,
669 _ => panic!("Unexpected def for constant: {def:?}"),
670 };
671
672 let value = if matches!(self.options.consts, ConstHandling::Values)
676 && let Some(evaluated) = self.evaluate_const_def(def)
677 {
678 self.translate_constant_expr(span, &evaluated)?
679 } else {
680 let initializer = self.register_item(span, def.this(), TransItemSourceKind::Fun);
683 ConstantExpr::new(
684 ConstantExprKind::Call(
685 FnPtr::new(
686 FnPtrKind::Fun(initializer),
687 self.outermost_generics().identity_args(),
688 ),
689 vec![],
690 ),
691 ty.clone(),
692 )
693 };
694
695 Ok(GlobalDecl {
696 def_id,
697 item_meta,
698 generics: self.into_generics(),
699 ty,
700 src: item_source,
701 global_kind,
702 value,
703 })
704 }
705
706 #[tracing::instrument(skip(self, item_meta, def))]
708 pub fn translate_trait_decl(
709 mut self,
710 trait_decl_id: TraitDeclId,
711 item_meta: ItemMeta,
712 def: &hax::FullDef<'tcx>,
713 ) -> Result<TraitDecl, Error> {
714 let span = item_meta.span;
715
716 let (hax::FullDefKind::Trait {
717 implied_predicates, ..
718 }
719 | hax::FullDefKind::TraitAlias {
720 implied_predicates, ..
721 }) = def.kind()
722 else {
723 raise_error!(self, span, "Unexpected definition: {def:?}");
724 };
725 let src = match def.kind() {
726 hax::FullDefKind::Trait { .. } => TraitDeclSource::Normal,
727 hax::FullDefKind::TraitAlias { .. } => TraitDeclSource::TraitAlias,
728 _ => unreachable!(),
729 };
730
731 let mut implied_clauses = Default::default();
734 self.translate_predicates(
735 implied_predicates,
736 PredicateOrigin::WhereClauseOnTrait,
737 Some(&mut implied_clauses),
738 )?;
739
740 let vtable = self.translate_vtable_struct_ref_no_enqueue(span, def.this())?;
741
742 if let hax::FullDefKind::TraitAlias { .. } = def.kind() {
743 return Ok(TraitDecl {
745 def_id: trait_decl_id,
746 item_meta,
747 src,
748 implied_clauses,
749 generics: self.into_generics(),
750 consts: Default::default(),
751 types: Default::default(),
752 methods: Default::default(),
753 vtable,
754 });
755 }
756
757 let hax::FullDefKind::Trait {
758 items,
759 self_predicate,
760 ..
761 } = &def.kind
762 else {
763 unreachable!()
764 };
765 let self_trait_ref = TraitRef::new(
766 TraitRefKind::SelfId,
767 RegionBinder::empty(self.translate_trait_predicate(span, self_predicate)?),
768 );
769
770 self.register_assoc_items(def.def_id(), trait_decl_id)?;
772 let mut consts: IndexMap<AssocConstId, _> = IndexMap::new();
773 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
774 let mut methods: IndexMap<TraitMethodId, _> = IndexMap::new();
775
776 if def.lang_item == Some(sym::destruct) {
777 let destruct_trait_def_id = def.def_id();
779 let method_id =
780 self.translate_drop_glue_method_id(destruct_trait_def_id, trait_decl_id)?;
781 self.mark_method_as_used(trait_decl_id, method_id);
782 let method = {
783 let method_name = self.translated.assoc_item_name(trait_decl_id, method_id);
784 let mut method_item_meta = ItemMeta::dummy_public(
785 span,
786 item_meta.name.clone(),
787 item_meta.is_local,
788 item_meta.opacity,
789 );
790 method_item_meta.name.name.push(PathElem::Ident(
791 method_name.to_string(),
792 Disambiguator::ZERO,
793 ));
794 let self_ty = if self.monomorphize() {
795 Ty::mk_unit()
797 } else {
798 TyKind::TypeVar(DeBruijnVar::bound(DeBruijnId::one(), TypeVarId::ZERO))
799 .into_ty()
800 };
801 let signature = self.drop_glue_method_sig(
802 self_ty,
803 Region::Var(DeBruijnVar::new_at_zero(RegionId::ZERO)),
804 );
805 let method_params = Self::drop_glue_params();
806 Binder::new(
807 BinderKind::TraitMethod(trait_decl_id, method_id),
808 method_params,
809 TraitMethod {
810 name: method_name,
811 default: None,
812 item_meta: method_item_meta,
813 signature,
814 },
815 )
816 };
817 methods.set_slot_extend(method_id, method);
818 }
819
820 if self.monomorphize() {
824 return Ok(TraitDecl {
825 def_id: trait_decl_id,
826 item_meta,
827 src,
828 implied_clauses,
829 generics: self.into_generics(),
830 consts,
831 types,
832 methods,
833 vtable,
834 });
835 }
836
837 for hax_item in items {
838 let item_def_id = &hax_item.def_id;
839 let item_span = self.def_span(item_def_id);
840 let assoc_item_id = self.translate_assoc_item_id(trait_decl_id, item_def_id)?;
841 let item_name = self
842 .translated
843 .assoc_item_name(trait_decl_id, assoc_item_id);
844
845 let trans_kind = match hax_item.kind {
848 hax::AssocKind::Fn { .. } => TransItemSourceKind::Fun,
849 hax::AssocKind::Const { .. } => TransItemSourceKind::Global,
850 hax::AssocKind::Type { .. } => TransItemSourceKind::Type,
851 };
852
853 let item_def = self.poly_hax_def(item_def_id)?;
854 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
855 let attr_info = self.translate_attr_info(&item_def);
856
857 match item_def.kind() {
858 hax::FullDefKind::AssocFn {
859 sig,
860 associated_item,
861 ..
862 } => {
863 let trait_method_id = *assoc_item_id.as_method().unwrap();
864 let method_name = self.translate_name(&item_src)?;
865 let method_opacity = self.opacity_for_name(&method_name);
866 let method_item_meta =
867 self.translate_item_meta(&item_def, &item_src, method_name, method_opacity);
868 if self.options.translate_all_methods
871 || item_meta.opacity.is_transparent()
872 || !hax_item.has_value
873 {
874 self.mark_method_as_used(trait_decl_id, trait_method_id);
875 }
876 let default_fun_id = associated_item.has_value.then(|| {
877 let fun_id = self.register_no_enqueue(item_span, &item_src);
878 self.register_method_impl(trait_decl_id, trait_method_id, fun_id);
880 fun_id
881 });
882
883 let binder_kind = BinderKind::TraitMethod(trait_decl_id, trait_method_id);
884 let mut method = self.translate_binder_for_def(
885 item_span,
886 binder_kind,
887 &item_def,
888 |bt_ctx| {
889 assert_eq!(bt_ctx.binding_levels.len(), 2);
890 let default = default_fun_id.map(|id| {
891 let fun_generics = bt_ctx
892 .outermost_binder()
893 .params
894 .identity_args_at_depth(DeBruijnId::one())
895 .concat(
896 &bt_ctx
897 .innermost_binder()
898 .params
899 .identity_args_at_depth(DeBruijnId::zero()),
900 );
901 FunDeclRef {
902 id,
903 generics: Box::new(fun_generics),
904 }
905 });
906 let signature =
909 bt_ctx.translate_fun_sig(span, sig.hax_skip_binder_ref())?;
910 Ok(TraitMethod {
911 name: item_name,
912 item_meta: method_item_meta,
913 signature,
914 default,
915 })
916 },
917 )?;
918 struct ReplaceSelfVisitor;
923 impl VarsVisitor for ReplaceSelfVisitor {
924 fn visit_clause_var(&mut self, v: ClauseDbVar) -> Option<TraitRefKind> {
925 if let DeBruijnVar::Bound(DeBruijnId::ZERO, clause_id) = v {
926 Some(if let Some(new_id) = clause_id.index().checked_sub(1) {
928 TraitRefKind::Clause(DeBruijnVar::Bound(
929 DeBruijnId::ZERO,
930 TraitClauseId::new(new_id),
931 ))
932 } else {
933 TraitRefKind::SelfId
934 })
935 } else {
936 None
937 }
938 }
939 }
940 method.params.visit_vars(&mut ReplaceSelfVisitor);
941 method.skip_binder.visit_vars(&mut ReplaceSelfVisitor);
942 method
943 .params
944 .trait_clauses
945 .remove_and_shift_ids(TraitClauseId::ZERO);
946 method.params.trait_clauses.iter_mut().for_each(|clause| {
947 clause.clause_id -= 1;
948 });
949
950 methods.set_slot_extend(trait_method_id, method);
953 }
954 hax::FullDefKind::AssocConst { ty, .. } => {
955 let assoc_const_id = *assoc_item_id.as_const().unwrap();
956 let bound_assoc_const = self.translate_binder_for_def(
959 item_span,
960 BinderKind::Other,
961 &item_def,
962 |ctx| {
963 let default = hax_item.has_value.then(|| {
965 let id = ctx.register_and_enqueue(item_span, item_src);
968 let generics = ctx
969 .outermost_binder()
970 .params
971 .identity_args_at_depth(DeBruijnId::one())
972 .concat(
973 &ctx.innermost_binder()
974 .params
975 .identity_args_at_depth(DeBruijnId::zero()),
976 );
977 GlobalDeclRef {
978 id,
979 generics: Box::new(generics),
980 }
981 });
982 let ty = ctx.translate_ty(item_span, ty)?;
983 Ok(TraitAssocConst {
984 name: item_name,
985 attr_info,
986 ty,
987 default,
988 })
989 },
990 )?;
991 let assoc_const = bound_assoc_const.apply(&{
992 let mut generics = GenericArgs::empty();
993 generics.trait_refs.push(self_trait_ref.clone());
995 generics
996 });
997 consts.set_slot_extend(assoc_const_id, assoc_const);
998 }
999 hax::FullDefKind::AssocTy {
1000 implied_predicates,
1001 value: default,
1002 ..
1003 } => {
1004 let assoc_type_id = *assoc_item_id.as_type().unwrap();
1005 let binder_kind = BinderKind::TraitType(trait_decl_id, assoc_type_id);
1006 let assoc_ty =
1007 self.translate_binder_for_def(item_span, binder_kind, &item_def, |ctx| {
1008 let mut implied_clauses = Default::default();
1010 ctx.translate_predicates(
1011 implied_predicates,
1012 PredicateOrigin::TraitItem(assoc_type_id),
1013 Some(&mut implied_clauses),
1014 )?;
1015
1016 let default = default
1017 .as_ref()
1018 .map(|(ty, trait_proofs)| -> Result<_, Error> {
1019 let ty = ctx.translate_ty(item_span, ty)?;
1020 let trefs = ctx.translate_trait_proofs(span, trait_proofs)?;
1021 Ok(TraitAssocTyImpl {
1022 value: ty,
1023 implied_trait_refs: trefs,
1024 })
1025 })
1026 .transpose()?;
1027 Ok(TraitAssocTy {
1028 name: item_name,
1029 attr_info,
1030 default,
1031 implied_clauses,
1032 })
1033 })?;
1034 types.set_slot_extend(assoc_type_id, assoc_ty);
1035 }
1036 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
1037 }
1038 }
1039
1040 Ok(TraitDecl {
1044 def_id: trait_decl_id,
1045 item_meta,
1046 src,
1047 implied_clauses,
1048 generics: self.into_generics(),
1049 consts,
1050 types,
1051 methods,
1052 vtable,
1053 })
1054 }
1055
1056 #[tracing::instrument(skip(self, item_meta, def))]
1057 pub fn translate_trait_impl(
1058 mut self,
1059 def_id: TraitImplId,
1060 item_meta: ItemMeta,
1061 def: &hax::FullDef<'tcx>,
1062 ) -> Result<TraitImpl, Error> {
1063 let span = item_meta.span;
1064
1065 let hax::FullDefKind::TraitImpl {
1066 trait_pred,
1067 implied_trait_proofs,
1068 items: impl_items,
1069 ..
1070 } = &def.kind
1071 else {
1072 unreachable!()
1073 };
1074
1075 let implemented_trait = self.translate_trait_ref(span, &trait_pred.trait_ref)?;
1077 let trait_id = implemented_trait.id;
1078
1079 if self.is_poly_in_mono(&self.item_src) {
1081 return Ok(TraitImpl {
1082 def_id,
1083 item_meta,
1084 src: TraitImplSource::Normal,
1085 impl_trait: implemented_trait,
1086 generics: self.into_generics(),
1087 implied_trait_refs: Default::default(),
1088 consts: Default::default(),
1089 types: Default::default(),
1090 methods: Default::default(),
1091 vtable: None,
1092 });
1093 }
1094
1095 let self_predicate = TraitRef::new(
1097 TraitRefKind::TraitImpl(TraitImplRef {
1098 id: def_id,
1099 generics: Box::new(self.the_only_binder().params.identity_args()),
1100 }),
1101 RegionBinder::empty(implemented_trait.clone()),
1102 );
1103
1104 let vtable = self.translate_vtable_instance_ref_no_enqueue(
1105 span,
1106 &trait_pred.trait_ref,
1107 def.this(),
1108 TransImplSource::Normal,
1109 )?;
1110
1111 let implied_trait_refs = self.translate_trait_proofs(span, implied_trait_proofs)?;
1113
1114 {
1115 let ctx = self.into_fmt();
1117 let refs = implied_trait_refs
1118 .iter()
1119 .map(|c| c.with_ctx(&ctx))
1120 .format("\n");
1121 trace!(
1122 "Trait impl: {:?}\n- implied_trait_refs:\n{}",
1123 def.def_id(),
1124 refs
1125 );
1126 }
1127
1128 let implemented_trait_def = self.poly_hax_def(&trait_pred.trait_ref.def_id)?;
1129 if implemented_trait_def.lang_item == Some(sym::destruct) {
1130 raise_error!(
1131 self,
1132 span,
1133 "found an explicit impl of `core::marker::Destruct`, this should not happen"
1134 );
1135 }
1136
1137 let mut consts: IndexMap<AssocConstId, _> = IndexMap::new();
1139 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
1140 let mut methods: IndexMap<TraitMethodId, _> = IndexMap::new();
1141
1142 if self.monomorphize() {
1144 return Ok(TraitImpl {
1145 def_id,
1146 item_meta,
1147 src: TraitImplSource::Normal,
1148 impl_trait: implemented_trait,
1149 generics: self.into_generics(),
1150 implied_trait_refs,
1151 consts,
1152 types,
1153 methods,
1154 vtable,
1155 });
1156 }
1157
1158 for impl_item in impl_items {
1159 let item_def_id = impl_item.def_id().unwrap_or(impl_item.decl_def_id());
1160 let item_span = self.def_span(item_def_id);
1161 let assoc_item_id = self.translate_assoc_item_id(trait_id, item_def_id)?;
1162
1163 let item_def = self.poly_hax_def(item_def_id)?;
1165 let trans_kind = match item_def.kind() {
1166 hax::FullDefKind::AssocFn { .. } => TransItemSourceKind::Fun,
1167 hax::FullDefKind::AssocConst { .. } => TransItemSourceKind::Global,
1168 hax::FullDefKind::AssocTy { .. } => TransItemSourceKind::Type,
1169 _ => unreachable!(),
1170 };
1171 let item_src = TransItemSource::polymorphic(item_def_id, trans_kind);
1172
1173 match item_def.kind() {
1174 hax::FullDefKind::AssocFn { .. } => {
1175 let trait_method_id = *assoc_item_id.as_method().unwrap();
1176 let binder_kind = BinderKind::TraitMethod(trait_id, trait_method_id);
1177 let bound_fn_ref = match &impl_item.value {
1178 Some(value) => {
1179 if item_meta.opacity.is_transparent() {
1182 self.mark_method_as_used(trait_id, trait_method_id);
1183 }
1184 self.translate_item_binder(
1185 item_span,
1186 binder_kind,
1187 value,
1188 PredicateOrigin::WhereClauseOnFn,
1189 |ctx, value| {
1190 let bound_fn_ptr = ctx.translate_bound_fn_ptr_no_enqueue(
1191 item_span,
1192 &value.item,
1193 TransItemSourceKind::Fun,
1194 )?;
1195 let late_bound_regions = ctx
1197 .innermost_binder()
1198 .bound_region_vars
1199 .iter()
1200 .map(|rid| Region::Var(DeBruijnVar::new_at_zero(*rid)))
1201 .collect();
1202 let fn_ptr = bound_fn_ptr.apply(late_bound_regions);
1203 Ok(FunDeclRef {
1204 id: *fn_ptr.kind.as_fun().unwrap(),
1205 generics: fn_ptr.generics,
1206 })
1207 },
1208 )?
1209 }
1210 None => {
1211 let bound_method = match self.get_or_translate(trait_id.into()) {
1213 Ok(ItemRef::TraitDecl(tdecl)) => {
1214 tdecl.methods.get(trait_method_id).cloned()
1215 }
1216 _ => None,
1217 };
1218 let Some(bound_method) = bound_method else {
1219 continue;
1220 };
1221 bound_method
1222 .substitute_with_tref(&self_predicate)
1223 .map(|method| {
1224 method
1225 .default
1226 .expect("default method should have a default")
1227 })
1228 }
1229 };
1230
1231 self.register_method_impl(
1233 trait_id,
1234 trait_method_id,
1235 bound_fn_ref.skip_binder.id,
1236 );
1237
1238 methods.set_slot_extend(trait_method_id, bound_fn_ref);
1241 }
1242 hax::FullDefKind::AssocConst { .. } => {
1243 let assoc_const_id = *assoc_item_id.as_const().unwrap();
1244 let id = self.register_and_enqueue(item_span, item_src);
1245 let generics = match &impl_item.value {
1248 Some(_) => self.the_only_binder().params.identity_args(),
1249 None => {
1250 let mut generics = implemented_trait.generics.as_ref().clone();
1251 generics.trait_refs.push(self_predicate.clone());
1253 generics
1254 }
1255 };
1256 let gref = GlobalDeclRef {
1257 id,
1258 generics: Box::new(generics),
1259 };
1260 consts.set_slot_extend(assoc_const_id, gref);
1261 }
1262 hax::FullDefKind::AssocTy { .. } => {
1263 let assoc_type_id = *assoc_item_id.as_type().unwrap();
1264 let binder_kind = BinderKind::TraitType(trait_id, assoc_type_id);
1265 let assoc_ty = match &impl_item.value {
1266 Some(impl_value) => self.translate_item_binder(
1267 item_span,
1268 binder_kind,
1269 impl_value,
1270 PredicateOrigin::WhereClauseOnType,
1271 |ctx, impl_value| {
1272 let ty = ctx.translate_ty(
1273 item_span,
1274 impl_value.assoc_ty_value.as_ref().unwrap(),
1275 )?;
1276 let implied_trait_refs = ctx.translate_trait_proofs(
1277 item_span,
1278 &impl_value.implied_trait_proofs,
1279 )?;
1280 Ok(TraitAssocTyImpl {
1281 value: ty,
1282 implied_trait_refs,
1283 })
1284 },
1285 )?,
1286 None => {
1287 let trait_id = implemented_trait.id;
1289 let bound_ty = match self.get_or_translate(trait_id.into()) {
1290 Ok(ItemRef::TraitDecl(tdecl)) => tdecl.types.get(assoc_type_id),
1291 _ => None,
1292 };
1293 let Some(bound_ty) = bound_ty else {
1294 register_error!(
1295 self,
1296 item_span,
1297 "couldn't translate defaulted associated type; \
1298 either the corresponding trait decl caused errors \
1299 or it was declared opaque."
1300 );
1301 continue;
1302 };
1303 bound_ty
1304 .clone()
1305 .substitute_with_tref(&self_predicate)
1306 .map(|ty_decl: TraitAssocTy| ty_decl.default.unwrap())
1307 }
1308 };
1309
1310 types.set_slot_extend(assoc_type_id, assoc_ty);
1311 }
1312 _ => panic!("Unexpected definition for trait item: {item_def:?}"),
1313 }
1314 }
1315
1316 Ok(TraitImpl {
1317 def_id,
1318 item_meta,
1319 src: TraitImplSource::Normal,
1320 impl_trait: implemented_trait,
1321 generics: self.into_generics(),
1322 implied_trait_refs,
1323 consts,
1324 types,
1325 methods,
1326 vtable,
1327 })
1328 }
1329
1330 #[tracing::instrument(skip(self, item_meta, def))]
1340 pub fn translate_trait_alias_blanket_impl(
1341 mut self,
1342 def_id: TraitImplId,
1343 item_meta: ItemMeta,
1344 def: &hax::FullDef<'tcx>,
1345 ) -> Result<TraitImpl, Error> {
1346 let span = item_meta.span;
1347
1348 let hax::FullDefKind::TraitAlias {
1349 implied_predicates,
1350 self_predicate,
1351 ..
1352 } = &def.kind
1353 else {
1354 raise_error!(self, span, "Unexpected definition: {def:?}");
1355 };
1356
1357 let implemented_trait = self.translate_trait_ref(span, &self_predicate.trait_ref)?;
1359
1360 assert!(self.innermost_generics_mut().trait_clauses.is_empty());
1362 self.register_predicates(implied_predicates, PredicateOrigin::WhereClauseOnTrait)?;
1363
1364 let mut generics = self.the_only_binder().params.identity_args();
1365 let implied_trait_refs = mem::take(&mut generics.trait_refs);
1367
1368 let mut timpl = TraitImpl {
1369 def_id,
1370 item_meta,
1371 src: TraitImplSource::TraitAlias,
1372 impl_trait: implemented_trait,
1373 generics: self.the_only_binder().params.clone(),
1374 implied_trait_refs,
1375 consts: Default::default(),
1376 types: Default::default(),
1377 methods: Default::default(),
1378 vtable: None,
1380 };
1381 {
1384 struct FixSelfVisitor {
1385 binder_depth: DeBruijnId,
1386 }
1387 struct UnhandledSelf;
1388 impl Visitor for FixSelfVisitor {
1389 type Break = UnhandledSelf;
1390 }
1391 impl VisitorWithBinderDepth for FixSelfVisitor {
1392 fn binder_depth_mut(&mut self) -> &mut DeBruijnId {
1393 &mut self.binder_depth
1394 }
1395 }
1396 impl VisitAstMut for FixSelfVisitor {
1397 fn visit<T: AstVisitable>(&mut self, x: &mut T) -> ControlFlow<Self::Break> {
1398 VisitWithBinderDepth::new(self).visit(x)
1399 }
1400 fn visit_trait_ref_kind(
1401 &mut self,
1402 kind: &mut TraitRefKind,
1403 ) -> ControlFlow<Self::Break> {
1404 match kind {
1405 TraitRefKind::SelfId => return ControlFlow::Break(UnhandledSelf),
1406 TraitRefKind::ParentClause(sub, clause_id)
1407 if matches!(sub.kind, TraitRefKind::SelfId) =>
1408 {
1409 *kind = TraitRefKind::Clause(DeBruijnVar::bound(
1410 self.binder_depth,
1411 *clause_id,
1412 ))
1413 }
1414 _ => (),
1415 }
1416 self.visit_inner(kind)
1417 }
1418 }
1419 match timpl.drive_mut(&mut FixSelfVisitor {
1420 binder_depth: DeBruijnId::zero(),
1421 }) {
1422 ControlFlow::Continue(()) => {}
1423 ControlFlow::Break(UnhandledSelf) => {
1424 register_error!(
1425 self,
1426 span,
1427 "Found `Self` clause we can't handle \
1428 in a trait alias blanket impl."
1429 );
1430 }
1431 }
1432 };
1433
1434 Ok(timpl)
1435 }
1436
1437 #[tracing::instrument(skip(self, item_meta))]
1440 pub fn translate_virtual_trait_impl(
1441 &mut self,
1442 def_id: TraitImplId,
1443 item_meta: ItemMeta,
1444 vtable_item: &hax::ItemRef,
1445 impl_kind: TransImplSource,
1446 vimpl: &hax::VirtualTraitImpl,
1447 ) -> Result<TraitImpl, Error> {
1448 let span = item_meta.span;
1449 let src = match impl_kind {
1450 TransImplSource::Callable(kind) => TraitImplSource::Closure { kind },
1451 TransImplSource::ImplicitDestruct => TraitImplSource::Destruct,
1452 _ => unreachable!("not a virtual impl source: {impl_kind:?}"),
1453 };
1454 let trait_def = self.hax_def(&vimpl.trait_pred.trait_ref)?;
1455 let hax::FullDefKind::Trait {
1456 items: trait_items, ..
1457 } = trait_def.kind()
1458 else {
1459 panic!()
1460 };
1461
1462 let implemented_trait = self.translate_trait_predicate(span, &vimpl.trait_pred)?;
1463 let implied_trait_refs = self.translate_trait_proofs(span, &vimpl.implied_trait_proofs)?;
1464 let vtable = self.translate_vtable_instance_ref_no_enqueue(
1465 span,
1466 &vimpl.trait_pred.trait_ref,
1467 vtable_item,
1468 impl_kind,
1469 )?;
1470
1471 let mut types: IndexMap<AssocTypeId, _> = IndexMap::new();
1472 if !self.monomorphize() {
1474 let type_items = trait_items
1475 .iter()
1476 .filter(|assoc| matches!(assoc.kind, hax::AssocKind::Type { .. }));
1477 for ((ty, trait_proofs), assoc) in vimpl.types.iter().zip(type_items) {
1478 let assoc_type_id =
1479 self.translate_assoc_type_id(implemented_trait.id, &assoc.def_id)?;
1480 let assoc_ty = TraitAssocTyImpl {
1481 value: self.translate_ty(span, ty)?,
1482 implied_trait_refs: self.translate_trait_proofs(span, trait_proofs)?,
1483 };
1484 let binder_kind = BinderKind::TraitType(implemented_trait.id, assoc_type_id);
1485 types.set_slot_extend(assoc_type_id, Binder::empty(binder_kind, assoc_ty));
1486 }
1487 }
1488
1489 let generics = self.the_only_binder().params.clone();
1490 Ok(TraitImpl {
1491 def_id,
1492 item_meta,
1493 src,
1494 impl_trait: implemented_trait,
1495 generics,
1496 implied_trait_refs,
1497 consts: IndexMap::new(),
1498 types,
1499 methods: IndexMap::new(),
1500 vtable,
1501 })
1502 }
1503}