1use itertools::Itertools;
18use rustc_middle::ty::TyCtxt;
19use rustc_span::sym;
20use std::cell::RefCell;
21use std::collections::HashSet;
22use std::path::PathBuf;
23
24use super::translate_ctx::*;
25use crate::hax;
26use crate::hax::SInto;
27use charon_lib::ast::*;
28use charon_lib::name_matcher::NamePattern;
29use charon_lib::options::{CliOpts, StartFrom, TranslateOptions};
30use charon_lib::transform::TransformCtx;
31use macros::VariantIndexArity;
32
33#[derive(Clone, Debug, PartialEq, Eq, Hash)]
37pub struct TransItemSource {
38 pub item: RustcItem,
39 pub kind: TransItemSourceKind,
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Hash)]
50pub enum RustcItem {
51 Poly(hax::DefId),
52 Mono(hax::ItemRef),
53 MonoTrait(hax::DefId),
54}
55
56#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, VariantIndexArity)]
58pub enum TransItemSourceKind {
59 Global,
60 TraitDecl,
61 TraitImpl(TraitImplSource),
62 Fun,
63 Type,
64 InherentImpl,
66 Module,
68 ClosureMethod(ClosureKind),
70 ClosureAsFnCast,
72 DropGlueMethod(TraitImplSource),
76 VTable,
78 VTableInstance(TraitImplSource),
80 VTableInstanceInitializer(TraitImplSource),
82 VTableMethod,
86 VTableDropShim,
88}
89
90#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, VariantIndexArity)]
92pub enum TraitImplSource {
93 Normal,
95 TraitAlias,
97 Closure(ClosureKind),
99 ImplicitDestruct,
102}
103
104impl TransItemSource {
105 pub fn new(item: RustcItem, kind: TransItemSourceKind) -> Self {
106 if let RustcItem::Mono(item) = &item {
107 if item.has_non_lt_param {
108 panic!("Item is not monomorphic: {item:?}")
109 }
110 } else if let RustcItem::MonoTrait(_) = &item
111 && !matches!(
112 kind,
113 TransItemSourceKind::TraitDecl | TransItemSourceKind::VTable
114 )
115 {
116 panic!("Item kind {kind:?} should not be translated as monomorphic_trait")
117 }
118 Self { item, kind }
119 }
120
121 pub fn from_item(item: &hax::ItemRef, kind: TransItemSourceKind, monomorphize: bool) -> Self {
124 if monomorphize {
125 Self::monomorphic(item, kind)
126 } else {
127 Self::polymorphic(&item.def_id, kind)
128 }
129 }
130
131 pub fn polymorphic(def_id: &hax::DefId, kind: TransItemSourceKind) -> Self {
133 Self::new(RustcItem::Poly(def_id.clone()), kind)
134 }
135
136 pub fn monomorphic(item: &hax::ItemRef, kind: TransItemSourceKind) -> Self {
138 Self::new(RustcItem::Mono(item.clone()), kind)
139 }
140
141 pub fn monomorphic_trait(def_id: &hax::DefId, kind: TransItemSourceKind) -> Self {
144 Self::new(RustcItem::MonoTrait(def_id.clone()), kind)
145 }
146
147 pub fn def_id(&self) -> &hax::DefId {
148 self.item.def_id()
149 }
150
151 pub(crate) fn with_kind(&self, kind: TransItemSourceKind) -> Self {
153 let mut ret = self.clone();
154 ret.kind = kind;
155 ret
156 }
157
158 pub(crate) fn parent(&self) -> Option<Self> {
161 let parent_kind = match self.kind {
162 TransItemSourceKind::ClosureMethod(kind) => {
163 TransItemSourceKind::TraitImpl(TraitImplSource::Closure(kind))
164 }
165 TransItemSourceKind::DropGlueMethod(impl_kind)
166 | TransItemSourceKind::VTableInstance(impl_kind)
167 | TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
168 TransItemSourceKind::TraitImpl(impl_kind)
169 }
170 _ => return None,
171 };
172 Some(self.with_kind(parent_kind))
173 }
174
175 pub(crate) fn is_derived_item(&self) -> bool {
178 use TransItemSourceKind::*;
179 !matches!(
180 self.kind,
181 Global
182 | TraitDecl
183 | TraitImpl(TraitImplSource::Normal)
184 | InherentImpl
185 | Module
186 | Fun
187 | Type
188 )
189 }
190}
191
192impl RustcItem {
193 pub fn def_id(&self) -> &hax::DefId {
194 match self {
195 RustcItem::Poly(def_id) => def_id,
196 RustcItem::Mono(item_ref) => &item_ref.def_id,
197 RustcItem::MonoTrait(def_id) => def_id,
198 }
199 }
200}
201
202impl<'tcx> TranslateCtx<'tcx> {
203 fn is_method_decl_without_default(&mut self, def_id: &hax::DefId) -> Option<hax::DefId> {
205 if matches!(def_id.kind, hax::DefKind::AssocFn)
206 && let def = self.poly_hax_def(def_id).ok()?
207 && let hax::FullDefKind::AssocFn {
208 associated_item, ..
209 } = def.kind()
210 && !associated_item.has_value
211 && let hax::AssocItemContainer::TraitContainer { trait_ref } =
212 &associated_item.container
213 {
214 Some(trait_ref.def_id.clone())
215 } else {
216 None
217 }
218 }
219
220 pub fn resolve_path(
222 &self,
223 span: Span,
224 pat: &NamePattern,
225 strict: bool,
226 ) -> Result<Vec<rustc_span::def_id::DefId>, Error> {
227 super::resolve_path::def_path_def_ids(&self.hax_state, pat, strict).map_err(|err| {
228 register_error!(self, span, "failed to resolve item path `{pat}`: {err}")
229 })
230 }
231
232 pub fn base_kind_for_item(&mut self, def_id: &hax::DefId) -> Option<TransItemSourceKind> {
235 use crate::hax::DefKind::*;
236 Some(match &def_id.kind {
237 Enum | Struct | Union | TyAlias | ForeignTy => TransItemSourceKind::Type,
238 Fn | AssocFn => TransItemSourceKind::Fun,
239 Const { .. } | Static { .. } | AssocConst { .. } => TransItemSourceKind::Global,
240 Trait | TraitAlias => TransItemSourceKind::TraitDecl,
241 Impl { of_trait: true } => TransItemSourceKind::TraitImpl(TraitImplSource::Normal),
242 Impl { of_trait: false } => TransItemSourceKind::InherentImpl,
243 Mod | ForeignMod => TransItemSourceKind::Module,
244
245 ExternCrate | GlobalAsm | Macro { .. } | Use => return None,
247 Ctor { .. } | Variant => return None,
250 AnonConst
252 | AssocTy
253 | Closure
254 | ConstParam
255 | Field
256 | InlineConst
257 | PromotedConst
258 | LifetimeParam
259 | OpaqueTy
260 | SyntheticCoroutineBody
261 | TyParam => {
262 let span = self.def_span(def_id);
263 register_error!(
264 self,
265 span,
266 "Cannot register item `{def_id:?}` with kind `{:?}`",
267 def_id.kind
268 );
269 return None;
270 }
271 })
272 }
273
274 #[tracing::instrument(skip(self))]
278 pub fn enqueue_module_item(&mut self, def_id: &hax::DefId) {
279 if let Some(trait_def_id) = self.is_method_decl_without_default(def_id) {
280 self.enqueue_module_item(&trait_def_id);
283 return;
284 }
285 let Some(kind) = self.base_kind_for_item(def_id) else {
286 return;
287 };
288 let item_src = if self.options.monomorphize_with_hax {
289 if let Ok(def) = self.poly_hax_def(def_id)
290 && !def.has_any_generics()
291 {
292 TransItemSource::monomorphic(def.this(), kind)
294 } else {
295 return;
297 }
298 } else {
299 TransItemSource::polymorphic(def_id, kind)
300 };
301 let _: Option<ItemId> = self.register_and_enqueue(&None, item_src);
302 }
303
304 pub(crate) fn register_no_enqueue<T: TryFrom<ItemId>>(
305 &mut self,
306 dep_src: &Option<DepSource>,
307 src: &TransItemSource,
308 ) -> Option<T> {
309 let item_id = match self.id_map.get(src) {
310 Some(tid) => *tid,
311 None => {
312 use TransItemSourceKind::*;
313 let trans_id = match src.kind {
314 Type | VTable => ItemId::Type(self.translated.type_decls.reserve_slot()),
315 TraitDecl => ItemId::TraitDecl(self.translated.trait_decls.reserve_slot()),
316 TraitImpl(..) => ItemId::TraitImpl(self.translated.trait_impls.reserve_slot()),
317 Global | VTableInstance(..) => {
318 ItemId::Global(self.translated.global_decls.reserve_slot())
319 }
320 Fun
321 | ClosureMethod(..)
322 | ClosureAsFnCast
323 | DropGlueMethod(..)
324 | VTableInstanceInitializer(..)
325 | VTableMethod
326 | VTableDropShim => ItemId::Fun(self.translated.fun_decls.reserve_slot()),
327 InherentImpl | Module => return None,
328 };
329 self.id_map.insert(src.clone(), trans_id);
331 self.reverse_id_map.insert(trans_id, src.clone());
332 if let Ok(name) = self.translate_name(src) {
334 self.translated.item_names.insert(trans_id, name);
335 }
336 trans_id
337 }
338 };
339 self.errors
340 .borrow_mut()
341 .register_dep_source(dep_src, item_id, src.def_id().is_local());
342 item_id.try_into().ok()
343 }
344
345 pub(crate) fn register_and_enqueue<T: TryFrom<ItemId>>(
347 &mut self,
348 dep_src: &Option<DepSource>,
349 item_src: TransItemSource,
350 ) -> Option<T> {
351 let id = self.register_no_enqueue(dep_src, &item_src);
352 self.items_to_translate.push_back(item_src);
353 id
354 }
355
356 pub(crate) fn enqueue_id(&mut self, id: impl Into<ItemId>) {
358 let id = id.into();
359 if self.translated.get_item(id).is_none() {
360 let item_src = self.reverse_id_map[&id].clone();
361 self.items_to_translate.push_back(item_src);
362 }
363 }
364
365 pub fn register_assoc_items(
367 &mut self,
368 trait_def_id: &hax::DefId,
369 trait_id: TraitDeclId,
370 ) -> Result<(), Error> {
371 if self.method_status.get(trait_id).is_some() {
372 return Ok(());
373 }
374 let trait_def = self.poly_hax_def(trait_def_id)?;
375 let hax::FullDefKind::Trait { items, .. } = trait_def.kind() else {
376 unreachable!()
377 };
378 let names = self
379 .translated
380 .assoc_item_names
381 .get_or_extend_and_insert(trait_id, Default::default);
382 for item in items {
383 let name = TraitItemName(
384 item.name
385 .as_ref()
386 .map(|n| n.to_string().into())
387 .unwrap_or_default(),
388 );
389 let id: AssocItemId = match item.kind {
390 hax::AssocKind::Type { .. } => names.types.push(name).into(),
391 hax::AssocKind::Fn { .. } => names.methods.push(name).into(),
392 hax::AssocKind::Const { .. } => names.consts.push(name).into(),
393 };
394 self.assoc_item_id_map.insert(item.def_id.clone(), id);
395 }
396 if trait_def.lang_item == Some(sym::destruct) {
398 let method_name = TraitItemName("drop_glue".into());
399 names.methods.push(method_name);
400 }
401 self.method_status.get_or_extend_and_insert(trait_id, || {
402 names.methods.map_ref(|_| MethodStatus::default())
403 });
404 Ok(())
405 }
406
407 pub fn translate_assoc_item_id(
410 &mut self,
411 trait_id: TraitDeclId,
412 item_def_id: &hax::DefId,
413 ) -> Result<AssocItemId, Error> {
414 if let Some(&item_id) = self.assoc_item_id_map.get(item_def_id)
418 && self.method_status.get(trait_id).is_some()
419 {
420 return Ok(item_id);
421 }
422
423 let item_def = self.poly_hax_def(item_def_id)?;
424 let assoc = match item_def.kind() {
425 hax::FullDefKind::AssocTy {
426 associated_item, ..
427 }
428 | hax::FullDefKind::AssocConst {
429 associated_item, ..
430 }
431 | hax::FullDefKind::AssocFn {
432 associated_item, ..
433 } => associated_item,
434 _ => panic!("Unexpected def for associated item: {item_def:?}"),
435 };
436 let decl_def_id = assoc.implemented_trait_item_id();
437
438 if decl_def_id != item_def_id
439 && let Some(&item_id) = self.assoc_item_id_map.get(decl_def_id)
440 && self.method_status.get(trait_id).is_some()
441 {
442 self.assoc_item_id_map.insert(item_def_id.clone(), item_id);
443 return Ok(item_id);
444 }
445
446 let trait_def_id = decl_def_id.parent(&self.hax_state).unwrap();
447 self.register_assoc_items(&trait_def_id, trait_id)?;
448 let item_id = *self.assoc_item_id_map.get(decl_def_id).unwrap();
449 Ok(item_id)
450 }
451
452 pub fn translate_trait_method_id_no_enqueue(
455 &mut self,
456 trait_id: TraitDeclId,
457 def_id: &hax::DefId,
458 ) -> Result<TraitMethodId, Error> {
459 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
460 Ok(*item_id.as_method().unwrap())
461 }
462 pub fn translate_trait_method_id(
465 &mut self,
466 trait_id: TraitDeclId,
467 def_id: &hax::DefId,
468 ) -> Result<TraitMethodId, Error> {
469 let method_id = self.translate_trait_method_id_no_enqueue(trait_id, def_id)?;
470 self.mark_method_as_used(trait_id, method_id);
471 Ok(method_id)
472 }
473 pub fn translate_assoc_type_id(
475 &mut self,
476 trait_id: TraitDeclId,
477 def_id: &hax::DefId,
478 ) -> Result<AssocTypeId, Error> {
479 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
480 Ok(*item_id.as_type().unwrap())
481 }
482 pub fn translate_assoc_const_id(
484 &mut self,
485 trait_id: TraitDeclId,
486 def_id: &hax::DefId,
487 ) -> Result<AssocConstId, Error> {
488 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
489 Ok(*item_id.as_const().unwrap())
490 }
491
492 pub(crate) fn register_target_info(&mut self) {
493 let target_data = &self.tcx.data_layout;
494 let triple = self.get_target_triple();
495 let info = krate::TargetInfo {
496 target_pointer_size: target_data.pointer_size().bytes(),
497 is_little_endian: matches!(target_data.endian, rustc_abi::Endian::Little),
498 };
499 self.translated.target_information.insert(triple, info);
500 }
501}
502
503impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
505 pub(crate) fn make_dep_source(&self, span: Span) -> Option<DepSource> {
506 Some(DepSource {
507 src_id: self.item_id?,
508 span: self.item_src.def_id().is_local().then_some(span),
509 })
510 }
511
512 pub(crate) fn register_and_enqueue<T: TryFrom<ItemId>>(
514 &mut self,
515 span: Span,
516 item_src: TransItemSource,
517 ) -> T {
518 let dep_src = self.make_dep_source(span);
519 self.t_ctx.register_and_enqueue(&dep_src, item_src).unwrap()
520 }
521
522 pub(crate) fn register_no_enqueue<T: TryFrom<ItemId>>(
523 &mut self,
524 span: Span,
525 src: &TransItemSource,
526 ) -> T {
527 let dep_src = self.make_dep_source(span);
528 self.t_ctx.register_no_enqueue(&dep_src, src).unwrap()
529 }
530
531 pub(crate) fn register_item_maybe_enqueue<T: TryFrom<ItemId>>(
533 &mut self,
534 span: Span,
535 enqueue: bool,
536 item: &hax::ItemRef,
537 kind: TransItemSourceKind,
538 ) -> T {
539 let item = if self.monomorphize() && item.has_param {
540 item.erase(self.hax_state_with_id())
541 } else {
542 item.clone()
543 };
544 let item_src = if self.monomorphize() && matches!(kind, TransItemSourceKind::TraitDecl) {
551 TransItemSource::monomorphic_trait(&item.def_id, kind)
552 } else {
553 TransItemSource::from_item(
554 &item,
555 kind,
556 self.monomorphize()
557 && !matches!(
558 self.item_src.kind,
559 TransItemSourceKind::TraitDecl | TransItemSourceKind::VTable
560 ),
561 )
562 };
563 if enqueue {
564 self.register_and_enqueue(span, item_src)
565 } else {
566 self.register_no_enqueue(span, &item_src)
567 }
568 }
569
570 pub(crate) fn register_item<T: TryFrom<ItemId>>(
572 &mut self,
573 span: Span,
574 item: &hax::ItemRef,
575 kind: TransItemSourceKind,
576 ) -> T {
577 self.register_item_maybe_enqueue(span, true, item, kind)
578 }
579
580 #[expect(dead_code)]
582 pub(crate) fn register_item_no_enqueue<T: TryFrom<ItemId>>(
583 &mut self,
584 span: Span,
585 item: &hax::ItemRef,
586 kind: TransItemSourceKind,
587 ) -> T {
588 self.register_item_maybe_enqueue(span, false, item, kind)
589 }
590
591 pub(crate) fn translate_item_maybe_enqueue<T: TryFrom<DeclRef<ItemId>>>(
593 &mut self,
594 span: Span,
595 hax_item: &hax::ItemRef,
596 kind: TransItemSourceKind,
597 enqueue: bool,
598 ) -> Result<T, Error> {
599 let id: ItemId = self.register_item_maybe_enqueue(span, enqueue, hax_item, kind);
600 let mut generics = if self.monomorphize() && !matches!(kind, TransItemSourceKind::TraitDecl)
602 {
603 GenericArgs::empty()
604 } else {
605 self.translate_generic_args(span, &hax_item.generic_args, &hax_item.trait_proofs)?
606 };
607
608 if matches!(
611 hax_item.def_id.kind,
612 hax::DefKind::Fn | hax::DefKind::AssocFn | hax::DefKind::Closure
613 ) {
614 let def = self.hax_def(hax_item)?;
615 match def.kind() {
616 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
617 generics.regions.extend(
618 sig.bound_vars
619 .iter()
620 .map(|_| self.translate_erased_region()),
621 );
622 }
623 hax::FullDefKind::Closure { args, .. } => {
624 let upvar_regions = if self.item_src.def_id() == &args.item.def_id {
625 assert!(self.outermost_binder().closure_upvar_tys.is_some());
626 self.outermost_binder().closure_upvar_regions.len()
627 } else {
628 let adt_decl_id: ItemId =
632 self.register_item(span, hax_item, TransItemSourceKind::Type);
633 let adt_decl = self.get_or_translate(adt_decl_id)?;
634 let adt_generics = adt_decl.generic_params();
635 adt_generics.regions.len() - generics.regions.len()
636 };
637 generics
638 .regions
639 .extend((0..upvar_regions).map(|_| self.translate_erased_region()));
640 if let TransItemSourceKind::TraitImpl(TraitImplSource::Closure(..))
641 | TransItemSourceKind::ClosureMethod(..)
642 | TransItemSourceKind::ClosureAsFnCast = kind
643 {
644 generics.regions.extend(
645 args.fn_sig
646 .bound_vars
647 .iter()
648 .map(|_| self.translate_erased_region()),
649 );
650 }
651 if let TransItemSourceKind::ClosureMethod(
652 ClosureKind::FnMut | ClosureKind::Fn,
653 ) = kind
654 {
655 generics.regions.push(self.translate_erased_region());
656 }
657 if self.item_src.def_id() == &args.item.def_id {
661 let depth = self.binding_levels.depth();
662 for (a, b) in generics.regions.iter_mut().zip(
663 self.outermost_binder()
664 .params
665 .identity_args_at_depth(depth)
666 .regions,
667 ) {
668 *a = b;
669 }
670 }
671 }
672 _ => {}
673 }
674 }
675 if matches!(
676 kind,
677 TransItemSourceKind::DropGlueMethod(..) | TransItemSourceKind::VTableDropShim
678 ) {
679 generics = generics.concat(&self.drop_glue_generic_args());
680 }
681
682 let trait_ref = hax_item
683 .in_trait
684 .as_ref()
685 .map(|trait_proof| self.translate_trait_proof(span, trait_proof))
686 .transpose()?;
687 let item = DeclRef {
688 id,
689 generics: Box::new(generics),
690 trait_ref,
691 };
692 Ok(item.try_into().ok().unwrap())
693 }
694
695 pub(crate) fn translate_item<T: TryFrom<DeclRef<ItemId>>>(
701 &mut self,
702 span: Span,
703 item: &hax::ItemRef,
704 kind: TransItemSourceKind,
705 ) -> Result<T, Error> {
706 self.translate_item_maybe_enqueue(span, item, kind, true)
707 }
708
709 pub(crate) fn translate_type_decl_ref(
711 &mut self,
712 span: Span,
713 item: &hax::ItemRef,
714 ) -> Result<TypeDeclRef, Error> {
715 match self.recognize_builtin_type(item)? {
716 Some(id) => {
717 let generics =
718 self.translate_generic_args(span, &item.generic_args, &item.trait_proofs)?;
719 Ok(TypeDeclRef {
720 id: TypeId::Builtin(id),
721 generics: Box::new(generics),
722 })
723 }
724 None => self.translate_item(span, item, TransItemSourceKind::Type),
725 }
726 }
727
728 pub(crate) fn translate_fun_item_maybe_enqueue(
729 &mut self,
730 span: Span,
731 item: &hax::ItemRef,
732 kind: TransItemSourceKind,
733 enqueue: bool,
734 ) -> Result<MaybeBuiltinFunDeclRef, Error> {
735 match self.recognize_builtin_fun(item)? {
736 Some(id) => {
737 let generics =
738 self.translate_generic_args(span, &item.generic_args, &item.trait_proofs)?;
739 Ok(MaybeBuiltinFunDeclRef {
740 id: FunId::Builtin(id),
741 generics: Box::new(generics),
742 trait_ref: None,
743 })
744 }
745 None => self.translate_item_maybe_enqueue(span, item, kind, enqueue),
746 }
747 }
748
749 fn translate_method_decl_fn_ptr(
753 &mut self,
754 span: Span,
755 item: &hax::ItemRef,
756 ) -> Result<Option<RegionBinder<FnPtr>>, Error> {
757 let Some(in_trait) = &item.in_trait else {
758 return Ok(None);
759 };
760 let def = self.hax_def(item)?;
761 let hax::FullDefKind::AssocFn {
762 associated_item,
763 sig,
764 ..
765 } = def.kind()
766 else {
767 return Ok(None);
768 };
769 if !matches!(
770 &associated_item.container,
771 hax::AssocItemContainer::TraitContainer { .. }
772 ) {
773 return Ok(None);
774 }
775
776 let trait_ref = self.translate_trait_proof(span, in_trait)?;
777 let generics = self.translate_generic_args(span, &item.generic_args, &item.trait_proofs)?;
778 self.translate_region_binder(span, &sig.as_ref().rebind(()), |ctx, _| {
779 let method_id = ctx.translate_trait_method_id(trait_ref.trait_id(), &item.def_id)?;
780 let fn_kind = FnPtrKind::Trait(trait_ref.move_under_binder(), method_id);
781 let generics = generics.move_under_binder();
782 let generics = generics.concat(&ctx.innermost_binder().params.identity_args());
783 Ok(FnPtr::new(fn_kind, generics))
784 })
785 .map(Some)
786 }
787
788 #[tracing::instrument(skip(self, span))]
791 pub(crate) fn translate_unbound_fn_ptr_maybe_enqueue(
792 &mut self,
793 span: Span,
794 item: &hax::ItemRef,
795 kind: TransItemSourceKind,
796 enqueue: bool,
797 ) -> Result<FnPtr, Error> {
798 let fun_item = self.translate_fun_item_maybe_enqueue(span, item, kind, enqueue)?;
799 let fun_id = match fun_item.trait_ref {
800 None => FnPtrKind::Fun(fun_item.id),
802 Some(trait_ref) => {
804 let trait_decl_id = trait_ref.trait_id();
805 let method_id = self.translate_trait_method_id(trait_decl_id, &item.def_id)?;
806 FnPtrKind::Trait(trait_ref, method_id)
807 }
808 };
809 let mut generics = fun_item.generics;
810 for (a, b) in generics.regions.iter_mut().rev().zip(
813 self.innermost_binder()
814 .params
815 .identity_args()
816 .regions
817 .into_iter()
818 .rev(),
819 ) {
820 *a = b;
821 }
822 Ok(FnPtr::new(fun_id, generics))
823 }
824
825 #[tracing::instrument(skip(self, span))]
826 pub(crate) fn translate_bound_fn_ptr_maybe_enqueue(
827 &mut self,
828 span: Span,
829 item: &hax::ItemRef,
830 kind: TransItemSourceKind,
831 enqueue: bool,
832 ) -> Result<RegionBinder<FnPtr>, Error> {
833 if let Some(fn_ptr) = self.translate_method_decl_fn_ptr(span, item)? {
834 return Ok(fn_ptr);
835 }
836
837 let late_bound = self.hax_def(item)?.late_bound();
838 self.translate_region_binder(span, &late_bound, |ctx, _| {
839 ctx.translate_unbound_fn_ptr_maybe_enqueue(span, item, kind, enqueue)
840 })
841 }
842
843 #[tracing::instrument(skip(self, span))]
845 pub(crate) fn translate_bound_fn_ptr(
846 &mut self,
847 span: Span,
848 item: &hax::ItemRef,
849 kind: TransItemSourceKind,
850 ) -> Result<RegionBinder<FnPtr>, Error> {
851 self.translate_bound_fn_ptr_maybe_enqueue(span, item, kind, true)
852 }
853
854 pub(crate) fn translate_bound_fn_ptr_no_enqueue(
855 &mut self,
856 span: Span,
857 item: &hax::ItemRef,
858 kind: TransItemSourceKind,
859 ) -> Result<RegionBinder<FnPtr>, Error> {
860 self.translate_bound_fn_ptr_maybe_enqueue(span, item, kind, false)
861 }
862
863 pub(crate) fn translate_fn_ptr(
866 &mut self,
867 span: Span,
868 item: &hax::ItemRef,
869 kind: TransItemSourceKind,
870 ) -> Result<FnPtr, Error> {
871 let fn_ptr = self.translate_bound_fn_ptr(span, item, kind)?;
872 let fn_ptr = self.erase_region_binder(fn_ptr);
873 Ok(fn_ptr)
874 }
875
876 pub(crate) fn translate_global_decl_ref(
877 &mut self,
878 span: Span,
879 item: &hax::ItemRef,
880 ) -> Result<GlobalDeclRef, Error> {
881 self.translate_item(span, item, TransItemSourceKind::Global)
882 }
883
884 pub(crate) fn translate_trait_decl_ref(
885 &mut self,
886 span: Span,
887 item: &hax::ItemRef,
888 ) -> Result<TraitDeclRef, Error> {
889 self.translate_item(span, item, TransItemSourceKind::TraitDecl)
890 }
891
892 pub(crate) fn translate_trait_impl_ref(
893 &mut self,
894 span: Span,
895 item: &hax::ItemRef,
896 kind: TraitImplSource,
897 ) -> Result<TraitImplRef, Error> {
898 self.translate_item(span, item, TransItemSourceKind::TraitImpl(kind))
899 }
900}
901
902#[tracing::instrument(skip(tcx, error_ctx))]
903pub fn translate<'tcx>(
904 tcx: TyCtxt<'tcx>,
905 cli_options: &CliOpts,
906 mut error_ctx: ErrorCtx,
907 sysroot: PathBuf,
908) -> Result<TransformCtx, Error> {
909 let translate_options = TranslateOptions::new(&mut error_ctx, cli_options);
910
911 let traits_to_remove: HashSet<rustc_hir::def_id::DefId> = {
912 let hax_state = hax::state::State::new(
913 tcx,
914 hax::options::Options::default(),
915 hax::options::BoundsOptions::default(),
916 );
917 translate_options
918 .hide_traits
919 .iter()
920 .flat_map(|pat| super::resolve_path::def_path_def_ids(&hax_state, pat, true).unwrap())
921 .collect()
922 };
923 let hax_state = hax::state::State::new(
924 tcx,
925 hax::options::Options {
926 inline_anon_consts: !translate_options.raw_consts,
927 },
928 hax::options::BoundsOptions {
929 add_destruct_bounds: translate_options.add_destruct_bounds,
930 remove_traits: traits_to_remove,
931 },
932 );
933
934 let crate_def_id: hax::DefId = rustc_span::def_id::CRATE_DEF_ID
935 .to_def_id()
936 .sinto(&hax_state);
937 let crate_name = crate_def_id.crate_name(&hax_state).to_string();
938 trace!("# Crate: {}", crate_name);
939
940 let mut ctx = TranslateCtx {
941 tcx,
942 sysroot,
943 hax_state,
944 options: translate_options,
945 errors: RefCell::new(error_ctx),
946 translated: TranslatedCrate {
947 crate_name,
948 options: cli_options.clone(),
949 ..TranslatedCrate::default()
950 },
951 method_status: Default::default(),
952 assoc_item_id_map: Default::default(),
953 id_map: Default::default(),
954 reverse_id_map: Default::default(),
955 file_to_id: Default::default(),
956 items_to_translate: Default::default(),
957 processed: Default::default(),
958 translate_stack: Default::default(),
959 cached_item_metas: Default::default(),
960 cached_names: Default::default(),
961 lt_mutability_computer: Default::default(),
962 };
963 ctx.register_target_info();
964
965 for start_from in ctx.options.start_from.clone() {
967 match start_from {
968 StartFrom::Pattern { pattern, strict } => {
969 if let Ok(def_ids) = ctx.resolve_path(Span::dummy(), &pattern, strict) {
970 for def_id in def_ids {
971 let def_id: hax::DefId = def_id.sinto(&ctx.hax_state);
972 ctx.enqueue_module_item(&def_id);
973 }
974 }
975 }
976 StartFrom::Attribute(attr_name) => {
977 let attr_path = attr_name
978 .split("::")
979 .map(rustc_span::Symbol::intern)
980 .collect_vec();
981 let mut add_if_attr_matches = |ldid: rustc_hir::def_id::LocalDefId| {
982 let def_id: hax::DefId = ldid.to_def_id().sinto(&ctx.hax_state);
983 if !matches!(def_id.kind, hax::DefKind::Mod)
984 && def_id.attrs(tcx).iter().any(|a| a.path_matches(&attr_path))
985 {
986 ctx.enqueue_module_item(&def_id);
987 }
988 };
989 for ldid in tcx.hir_crate_items(()).definitions() {
990 add_if_attr_matches(ldid)
991 }
992 }
993 StartFrom::Pub => {
994 let mut add_if_matches = |ldid: rustc_hir::def_id::LocalDefId| {
995 let def_id: hax::DefId = ldid.to_def_id().sinto(&ctx.hax_state);
996 if !matches!(def_id.kind, hax::DefKind::Mod)
997 && def_id.visibility(tcx) == Some(true)
998 {
999 ctx.enqueue_module_item(&def_id);
1000 }
1001 };
1002 for ldid in tcx.hir_crate_items(()).definitions() {
1003 add_if_matches(ldid)
1004 }
1005 }
1006 }
1007 }
1008
1009 if ctx.errors.borrow().has_errors() {
1010 return Err(Error::dummy());
1012 }
1013
1014 trace!(
1015 "Queue after we explored the crate:\n{:?}",
1016 &ctx.items_to_translate
1017 );
1018
1019 while let Some(item_src) = ctx.items_to_translate.pop_front() {
1029 if ctx.processed.insert(item_src.clone()) {
1030 ctx.translate_item(&item_src);
1031 }
1032 }
1033
1034 ctx.remove_unused_methods();
1037
1038 Ok(TransformCtx {
1040 options: ctx.options,
1041 translated: ctx.translated,
1042 errors: ctx.errors,
1043 })
1044}