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::options::{CliOpts, StartFrom, TranslateOptions};
29use charon_lib::transform::TransformCtx;
30use macros::VariantIndexArity;
31
32#[derive(Clone, Debug, PartialEq, Eq, Hash)]
36pub struct TransItemSource {
37 pub item: RustcItem,
38 pub kind: TransItemSourceKind,
39}
40
41#[derive(Clone, Debug, PartialEq, Eq, Hash)]
49pub enum RustcItem {
50 Poly(hax::DefId),
51 Mono(hax::ItemRef),
52 MonoTrait(hax::DefId),
53}
54
55#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, VariantIndexArity)]
57pub enum TransItemSourceKind {
58 Global,
59 TraitDecl,
60 TraitImpl(TraitImplSource),
61 Fun,
62 Type,
63 InherentImpl,
65 Module,
67 DefaultedMethod(TraitImplSource, TraitDeclId, TraitMethodId),
70 ClosureMethod(ClosureKind),
72 ClosureAsFnCast,
74 DropInPlaceMethod(Option<TraitImplSource>),
80 VTable,
82 VTableInstance(TraitImplSource),
84 VTableInstanceInitializer(TraitImplSource),
86 VTableMethod,
90 VTableDropShim,
92}
93
94#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, VariantIndexArity)]
96pub enum TraitImplSource {
97 Normal,
99 TraitAlias,
101 Closure(ClosureKind),
103 ImplicitDestruct,
106}
107
108impl TransItemSource {
109 pub fn new(item: RustcItem, kind: TransItemSourceKind) -> Self {
110 if let RustcItem::Mono(item) = &item {
111 if item.has_param {
112 panic!("Item is not monomorphic: {item:?}")
113 }
114 } else if let RustcItem::MonoTrait(_) = &item
115 && !matches!(
116 kind,
117 TransItemSourceKind::TraitDecl | TransItemSourceKind::VTable
118 )
119 {
120 panic!("Item kind {kind:?} should not be translated as monomorphic_trait")
121 }
122 Self { item, kind }
123 }
124
125 pub fn from_item(item: &hax::ItemRef, kind: TransItemSourceKind, monomorphize: bool) -> Self {
128 if monomorphize {
129 Self::monomorphic(item, kind)
130 } else {
131 Self::polymorphic(&item.def_id, kind)
132 }
133 }
134
135 pub fn polymorphic(def_id: &hax::DefId, kind: TransItemSourceKind) -> Self {
137 Self::new(RustcItem::Poly(def_id.clone()), kind)
138 }
139
140 pub fn monomorphic(item: &hax::ItemRef, kind: TransItemSourceKind) -> Self {
142 Self::new(RustcItem::Mono(item.clone()), kind)
143 }
144
145 pub fn monomorphic_trait(def_id: &hax::DefId, kind: TransItemSourceKind) -> Self {
148 Self::new(RustcItem::MonoTrait(def_id.clone()), kind)
149 }
150
151 pub fn def_id(&self) -> &hax::DefId {
152 self.item.def_id()
153 }
154
155 pub(crate) fn with_kind(&self, kind: TransItemSourceKind) -> Self {
157 let mut ret = self.clone();
158 ret.kind = kind;
159 ret
160 }
161
162 pub(crate) fn parent(&self) -> Option<Self> {
165 let parent_kind = match self.kind {
166 TransItemSourceKind::ClosureMethod(kind) => {
167 TransItemSourceKind::TraitImpl(TraitImplSource::Closure(kind))
168 }
169 TransItemSourceKind::DefaultedMethod(impl_kind, ..)
170 | TransItemSourceKind::DropInPlaceMethod(Some(impl_kind))
171 | TransItemSourceKind::VTableInstance(impl_kind)
172 | TransItemSourceKind::VTableInstanceInitializer(impl_kind) => {
173 TransItemSourceKind::TraitImpl(impl_kind)
174 }
175 TransItemSourceKind::DropInPlaceMethod(None) => TransItemSourceKind::TraitDecl,
176 _ => return None,
177 };
178 Some(self.with_kind(parent_kind))
179 }
180
181 pub(crate) fn is_derived_item(&self) -> bool {
184 use TransItemSourceKind::*;
185 !matches!(
186 self.kind,
187 Global
188 | TraitDecl
189 | TraitImpl(TraitImplSource::Normal)
190 | InherentImpl
191 | Module
192 | Fun
193 | Type
194 )
195 }
196}
197
198impl RustcItem {
199 pub fn def_id(&self) -> &hax::DefId {
200 match self {
201 RustcItem::Poly(def_id) => def_id,
202 RustcItem::Mono(item_ref) => &item_ref.def_id,
203 RustcItem::MonoTrait(def_id) => def_id,
204 }
205 }
206}
207
208impl<'tcx> TranslateCtx<'tcx> {
209 pub fn base_kind_for_item(&mut self, def_id: &hax::DefId) -> Option<TransItemSourceKind> {
212 use crate::hax::DefKind::*;
213 Some(match &def_id.kind {
214 Enum | Struct | Union | TyAlias | ForeignTy => TransItemSourceKind::Type,
215 Fn | AssocFn => TransItemSourceKind::Fun,
216 Const | Static { .. } | AssocConst => TransItemSourceKind::Global,
217 Trait | TraitAlias => TransItemSourceKind::TraitDecl,
218 Impl { of_trait: true } => TransItemSourceKind::TraitImpl(TraitImplSource::Normal),
219 Impl { of_trait: false } => TransItemSourceKind::InherentImpl,
220 Mod | ForeignMod => TransItemSourceKind::Module,
221
222 ExternCrate | GlobalAsm | Macro { .. } | Use => return None,
224 Ctor { .. } | Variant => return None,
227 AnonConst
229 | AssocTy
230 | Closure
231 | ConstParam
232 | Field
233 | InlineConst
234 | PromotedConst
235 | LifetimeParam
236 | OpaqueTy
237 | SyntheticCoroutineBody
238 | TyParam => {
239 let span = self.def_span(def_id);
240 register_error!(
241 self,
242 span,
243 "Cannot register item `{def_id:?}` with kind `{:?}`",
244 def_id.kind
245 );
246 return None;
247 }
248 })
249 }
250
251 #[tracing::instrument(skip(self))]
255 pub fn enqueue_module_item(&mut self, def_id: &hax::DefId) {
256 let Some(kind) = self.base_kind_for_item(def_id) else {
257 return;
258 };
259 let item_src = if self.options.monomorphize_with_hax {
260 if let Ok(def) = self.poly_hax_def(def_id)
261 && !def.has_any_generics()
262 {
263 TransItemSource::monomorphic(def.this(), kind)
265 } else {
266 return;
268 }
269 } else {
270 TransItemSource::polymorphic(def_id, kind)
271 };
272 let _: Option<ItemId> = self.register_and_enqueue(&None, item_src);
273 }
274
275 pub(crate) fn register_no_enqueue<T: TryFrom<ItemId>>(
276 &mut self,
277 dep_src: &Option<DepSource>,
278 src: &TransItemSource,
279 ) -> Option<T> {
280 let item_id = match self.id_map.get(src) {
281 Some(tid) => *tid,
282 None => {
283 use TransItemSourceKind::*;
284 let trans_id = match src.kind {
285 Type | VTable => ItemId::Type(self.translated.type_decls.reserve_slot()),
286 TraitDecl => ItemId::TraitDecl(self.translated.trait_decls.reserve_slot()),
287 TraitImpl(..) => ItemId::TraitImpl(self.translated.trait_impls.reserve_slot()),
288 Global | VTableInstance(..) => {
289 ItemId::Global(self.translated.global_decls.reserve_slot())
290 }
291 Fun
292 | DefaultedMethod(..)
293 | ClosureMethod(..)
294 | ClosureAsFnCast
295 | DropInPlaceMethod(..)
296 | VTableInstanceInitializer(..)
297 | VTableMethod
298 | VTableDropShim => ItemId::Fun(self.translated.fun_decls.reserve_slot()),
299 InherentImpl | Module => return None,
300 };
301 self.id_map.insert(src.clone(), trans_id);
303 self.reverse_id_map.insert(trans_id, src.clone());
304 if let Ok(name) = self.translate_name(src) {
306 self.translated.item_names.insert(trans_id, name);
307 }
308 trans_id
309 }
310 };
311 self.errors
312 .borrow_mut()
313 .register_dep_source(dep_src, item_id, src.def_id().is_local());
314 item_id.try_into().ok()
315 }
316
317 pub(crate) fn register_and_enqueue<T: TryFrom<ItemId>>(
319 &mut self,
320 dep_src: &Option<DepSource>,
321 item_src: TransItemSource,
322 ) -> Option<T> {
323 let id = self.register_no_enqueue(dep_src, &item_src);
324 self.items_to_translate.push_back(item_src);
325 id
326 }
327
328 pub(crate) fn enqueue_id(&mut self, id: impl Into<ItemId>) {
330 let id = id.into();
331 if self.translated.get_item(id).is_none() {
332 let item_src = self.reverse_id_map[&id].clone();
333 self.items_to_translate.push_back(item_src);
334 }
335 }
336
337 pub fn register_assoc_items(
339 &mut self,
340 trait_def_id: &hax::DefId,
341 trait_id: TraitDeclId,
342 ) -> Result<(), Error> {
343 if self.translated.assoc_item_names.get(trait_id).is_some() {
344 return Ok(());
345 }
346 let trait_def = self.poly_hax_def(trait_def_id)?;
347 let hax::FullDefKind::Trait { items, .. } = trait_def.kind() else {
348 unreachable!()
349 };
350 let names = self
351 .translated
352 .assoc_item_names
353 .get_or_extend_and_insert(trait_id, Default::default);
354 for item in items {
355 let name = TraitItemName(
356 item.name
357 .as_ref()
358 .map(|n| n.to_string().into())
359 .unwrap_or_default(),
360 );
361 let id: AssocItemId = match item.kind {
362 hax::AssocKind::Type { .. } => names.types.push(name).into(),
363 hax::AssocKind::Fn { .. } => names.methods.push(name).into(),
364 hax::AssocKind::Const { .. } => names.consts.push(name).into(),
365 };
366 self.assoc_item_id_map.insert(item.def_id.clone(), id);
367 }
368 if trait_def.lang_item == Some(sym::destruct) {
370 let method_name = TraitItemName("drop_in_place".into());
371 names.methods.push(method_name);
372 }
373 self.method_status.get_or_extend_and_insert(trait_id, || {
374 names.methods.map_ref(|_| MethodStatus::default())
375 });
376 Ok(())
377 }
378
379 pub fn translate_assoc_item_id(
382 &mut self,
383 trait_id: TraitDeclId,
384 item_def_id: &hax::DefId,
385 ) -> Result<AssocItemId, Error> {
386 if let Some(&item_id) = self.assoc_item_id_map.get(item_def_id) {
387 return Ok(item_id);
388 }
389
390 let item_def = self.poly_hax_def(item_def_id)?;
391 let assoc = match item_def.kind() {
392 hax::FullDefKind::AssocTy {
393 associated_item, ..
394 }
395 | hax::FullDefKind::AssocConst {
396 associated_item, ..
397 }
398 | hax::FullDefKind::AssocFn {
399 associated_item, ..
400 } => associated_item,
401 _ => panic!("Unexpected def for associated item: {item_def:?}"),
402 };
403 let decl_def_id = assoc.implemented_trait_item_id();
404
405 if decl_def_id != item_def_id
406 && let Some(&item_id) = self.assoc_item_id_map.get(decl_def_id)
407 {
408 self.assoc_item_id_map.insert(item_def_id.clone(), item_id);
409 return Ok(item_id);
410 }
411
412 let trait_def_id = decl_def_id.parent(&self.hax_state).unwrap();
413 self.register_assoc_items(&trait_def_id, trait_id)?;
414 let item_id = *self.assoc_item_id_map.get(decl_def_id).unwrap();
415 Ok(item_id)
416 }
417
418 pub fn translate_trait_method_id_no_enqueue(
421 &mut self,
422 trait_id: TraitDeclId,
423 def_id: &hax::DefId,
424 ) -> Result<TraitMethodId, Error> {
425 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
426 Ok(*item_id.as_method().unwrap())
427 }
428 pub fn translate_trait_method_id(
431 &mut self,
432 trait_id: TraitDeclId,
433 def_id: &hax::DefId,
434 ) -> Result<TraitMethodId, Error> {
435 let method_id = self.translate_trait_method_id_no_enqueue(trait_id, def_id)?;
436 self.mark_method_as_used(trait_id, method_id);
437 Ok(method_id)
438 }
439 pub fn translate_assoc_type_id(
441 &mut self,
442 trait_id: TraitDeclId,
443 def_id: &hax::DefId,
444 ) -> Result<AssocTypeId, Error> {
445 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
446 Ok(*item_id.as_type().unwrap())
447 }
448 pub fn translate_assoc_const_id(
450 &mut self,
451 trait_id: TraitDeclId,
452 def_id: &hax::DefId,
453 ) -> Result<AssocConstId, Error> {
454 let item_id = self.translate_assoc_item_id(trait_id, def_id)?;
455 Ok(*item_id.as_const().unwrap())
456 }
457
458 pub(crate) fn register_target_info(&mut self) {
459 let target_data = &self.tcx.data_layout;
460 let triple = self.get_target_triple();
461 let info = krate::TargetInfo {
462 target_pointer_size: target_data.pointer_size().bytes(),
463 is_little_endian: matches!(target_data.endian, rustc_abi::Endian::Little),
464 };
465 self.translated.target_information.insert(triple, info);
466 }
467}
468
469impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
471 pub(crate) fn make_dep_source(&self, span: Span) -> Option<DepSource> {
472 Some(DepSource {
473 src_id: self.item_id?,
474 span: self.item_src.def_id().is_local().then_some(span),
475 })
476 }
477
478 pub(crate) fn register_and_enqueue<T: TryFrom<ItemId>>(
480 &mut self,
481 span: Span,
482 item_src: TransItemSource,
483 ) -> T {
484 let dep_src = self.make_dep_source(span);
485 self.t_ctx.register_and_enqueue(&dep_src, item_src).unwrap()
486 }
487
488 pub(crate) fn register_no_enqueue<T: TryFrom<ItemId>>(
489 &mut self,
490 span: Span,
491 src: &TransItemSource,
492 ) -> T {
493 let dep_src = self.make_dep_source(span);
494 self.t_ctx.register_no_enqueue(&dep_src, src).unwrap()
495 }
496
497 pub(crate) fn register_item_maybe_enqueue<T: TryFrom<ItemId>>(
499 &mut self,
500 span: Span,
501 enqueue: bool,
502 item: &hax::ItemRef,
503 kind: TransItemSourceKind,
504 ) -> T {
505 let item = if self.monomorphize() && item.has_param {
506 item.erase(self.hax_state_with_id())
507 } else {
508 item.clone()
509 };
510 let item_src = if self.monomorphize() && matches!(kind, TransItemSourceKind::TraitDecl) {
517 TransItemSource::monomorphic_trait(&item.def_id, kind)
518 } else {
519 TransItemSource::from_item(
520 &item,
521 kind,
522 self.monomorphize()
523 && !matches!(
524 self.item_src.kind,
525 TransItemSourceKind::TraitDecl | TransItemSourceKind::VTable
526 ),
527 )
528 };
529 if enqueue {
530 self.register_and_enqueue(span, item_src)
531 } else {
532 self.register_no_enqueue(span, &item_src)
533 }
534 }
535
536 pub(crate) fn register_item<T: TryFrom<ItemId>>(
538 &mut self,
539 span: Span,
540 item: &hax::ItemRef,
541 kind: TransItemSourceKind,
542 ) -> T {
543 self.register_item_maybe_enqueue(span, true, item, kind)
544 }
545
546 #[expect(dead_code)]
548 pub(crate) fn register_item_no_enqueue<T: TryFrom<ItemId>>(
549 &mut self,
550 span: Span,
551 item: &hax::ItemRef,
552 kind: TransItemSourceKind,
553 ) -> T {
554 self.register_item_maybe_enqueue(span, false, item, kind)
555 }
556
557 pub(crate) fn translate_item_maybe_enqueue<T: TryFrom<DeclRef<ItemId>>>(
559 &mut self,
560 span: Span,
561 enqueue: bool,
562 hax_item: &hax::ItemRef,
563 kind: TransItemSourceKind,
564 ) -> Result<T, Error> {
565 let id: ItemId = self.register_item_maybe_enqueue(span, enqueue, hax_item, kind);
566 let mut generics = if self.monomorphize() && !matches!(kind, TransItemSourceKind::TraitDecl)
568 {
569 GenericArgs::empty()
570 } else {
571 self.translate_generic_args(span, &hax_item.generic_args, &hax_item.impl_exprs)?
572 };
573
574 if matches!(
577 hax_item.def_id.kind,
578 hax::DefKind::Fn | hax::DefKind::AssocFn | hax::DefKind::Closure
579 ) {
580 let def = self.hax_def(hax_item)?;
581 match def.kind() {
582 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
583 generics.regions.extend(
584 sig.bound_vars
585 .iter()
586 .map(|_| self.translate_erased_region()),
587 );
588 }
589 hax::FullDefKind::Closure { args, .. } => {
590 let upvar_regions = if self.item_src.def_id() == &args.item.def_id {
591 assert!(self.outermost_binder().closure_upvar_tys.is_some());
592 self.outermost_binder().closure_upvar_regions.len()
593 } else {
594 let adt_decl_id: ItemId =
598 self.register_item(span, hax_item, TransItemSourceKind::Type);
599 let adt_decl = self.get_or_translate(adt_decl_id)?;
600 let adt_generics = adt_decl.generic_params();
601 adt_generics.regions.len() - generics.regions.len()
602 };
603 generics
604 .regions
605 .extend((0..upvar_regions).map(|_| self.translate_erased_region()));
606 if let TransItemSourceKind::TraitImpl(TraitImplSource::Closure(..))
607 | TransItemSourceKind::ClosureMethod(..)
608 | TransItemSourceKind::ClosureAsFnCast = kind
609 {
610 generics.regions.extend(
611 args.fn_sig
612 .bound_vars
613 .iter()
614 .map(|_| self.translate_erased_region()),
615 );
616 }
617 if let TransItemSourceKind::ClosureMethod(
618 ClosureKind::FnMut | ClosureKind::Fn,
619 ) = kind
620 {
621 generics.regions.push(self.translate_erased_region());
622 }
623 if self.item_src.def_id() == &args.item.def_id {
627 let depth = self.binding_levels.depth();
628 for (a, b) in generics.regions.iter_mut().zip(
629 self.outermost_binder()
630 .params
631 .identity_args_at_depth(depth)
632 .regions,
633 ) {
634 *a = b;
635 }
636 }
637 }
638 _ => {}
639 }
640 }
641
642 let trait_ref = hax_item
643 .in_trait
644 .as_ref()
645 .map(|impl_expr| self.translate_trait_impl_expr(span, impl_expr))
646 .transpose()?;
647 let item = DeclRef {
648 id,
649 generics: Box::new(generics),
650 trait_ref,
651 };
652 Ok(item.try_into().ok().unwrap())
653 }
654
655 pub(crate) fn translate_item<T: TryFrom<DeclRef<ItemId>>>(
661 &mut self,
662 span: Span,
663 item: &hax::ItemRef,
664 kind: TransItemSourceKind,
665 ) -> Result<T, Error> {
666 self.translate_item_maybe_enqueue(span, true, item, kind)
667 }
668
669 #[expect(dead_code)]
671 pub(crate) fn translate_item_no_enqueue<T: TryFrom<DeclRef<ItemId>>>(
672 &mut self,
673 span: Span,
674 item: &hax::ItemRef,
675 kind: TransItemSourceKind,
676 ) -> Result<T, Error> {
677 self.translate_item_maybe_enqueue(span, false, item, kind)
678 }
679
680 pub(crate) fn translate_type_decl_ref(
682 &mut self,
683 span: Span,
684 item: &hax::ItemRef,
685 ) -> Result<TypeDeclRef, Error> {
686 match self.recognize_builtin_type(item)? {
687 Some(id) => {
688 let generics =
689 self.translate_generic_args(span, &item.generic_args, &item.impl_exprs)?;
690 Ok(TypeDeclRef {
691 id: TypeId::Builtin(id),
692 generics: Box::new(generics),
693 })
694 }
695 None => self.translate_item(span, item, TransItemSourceKind::Type),
696 }
697 }
698
699 pub(crate) fn translate_fun_item(
701 &mut self,
702 span: Span,
703 item: &hax::ItemRef,
704 kind: TransItemSourceKind,
705 ) -> Result<MaybeBuiltinFunDeclRef, Error> {
706 match self.recognize_builtin_fun(item)? {
707 Some(id) => {
708 let generics =
709 self.translate_generic_args(span, &item.generic_args, &item.impl_exprs)?;
710 Ok(MaybeBuiltinFunDeclRef {
711 id: FunId::Builtin(id),
712 generics: Box::new(generics),
713 trait_ref: None,
714 })
715 }
716 None => self.translate_item(span, item, kind),
717 }
718 }
719
720 #[tracing::instrument(skip(self, span))]
723 pub(crate) fn translate_bound_fn_ptr(
724 &mut self,
725 span: Span,
726 item: &hax::ItemRef,
727 kind: TransItemSourceKind,
728 ) -> Result<RegionBinder<FnPtr>, Error> {
729 let fun_item = self.translate_fun_item(span, item, kind)?;
730 let fun_id = match fun_item.trait_ref {
731 None => FnPtrKind::Fun(fun_item.id),
733 Some(trait_ref) => {
735 let method_decl_id = *fun_item
736 .id
737 .as_regular()
738 .expect("methods are not builtin functions");
739 let trait_decl_id = trait_ref.trait_id();
740 let method_id = self.translate_trait_method_id(trait_decl_id, &item.def_id)?;
741 FnPtrKind::Trait(trait_ref.move_under_binder(), method_id, method_decl_id)
742 }
743 };
744 let late_bound = match self.hax_def(item)?.kind() {
745 hax::FullDefKind::Fn { sig, .. } | hax::FullDefKind::AssocFn { sig, .. } => {
746 sig.as_ref().rebind(())
747 }
748 _ => hax::Binder {
749 value: (),
750 bound_vars: vec![],
751 },
752 };
753 self.translate_region_binder(span, &late_bound, |ctx, _| {
754 let mut generics = fun_item.generics.move_under_binder();
755 for (a, b) in generics.regions.iter_mut().rev().zip(
758 ctx.innermost_binder()
759 .params
760 .identity_args()
761 .regions
762 .into_iter()
763 .rev(),
764 ) {
765 *a = b;
766 }
767 Ok(FnPtr::new(fun_id, generics))
768 })
769 }
770
771 pub(crate) fn translate_fn_ptr(
772 &mut self,
773 span: Span,
774 item: &hax::ItemRef,
775 kind: TransItemSourceKind,
776 ) -> Result<FnPtr, Error> {
777 let fn_ptr = self.translate_bound_fn_ptr(span, item, kind)?;
778 let fn_ptr = self.erase_region_binder(fn_ptr);
779 Ok(fn_ptr)
780 }
781
782 pub(crate) fn translate_global_decl_ref(
783 &mut self,
784 span: Span,
785 item: &hax::ItemRef,
786 ) -> Result<GlobalDeclRef, Error> {
787 self.translate_item(span, item, TransItemSourceKind::Global)
788 }
789
790 pub(crate) fn translate_trait_decl_ref(
791 &mut self,
792 span: Span,
793 item: &hax::ItemRef,
794 ) -> Result<TraitDeclRef, Error> {
795 self.translate_item(span, item, TransItemSourceKind::TraitDecl)
796 }
797
798 pub(crate) fn translate_trait_impl_ref(
799 &mut self,
800 span: Span,
801 item: &hax::ItemRef,
802 kind: TraitImplSource,
803 ) -> Result<TraitImplRef, Error> {
804 self.translate_item(span, item, TransItemSourceKind::TraitImpl(kind))
805 }
806}
807
808#[tracing::instrument(skip(tcx, error_ctx))]
809pub fn translate<'tcx>(
810 tcx: TyCtxt<'tcx>,
811 cli_options: &CliOpts,
812 mut error_ctx: ErrorCtx,
813 sysroot: PathBuf,
814) -> Result<TransformCtx, Error> {
815 let translate_options = TranslateOptions::new(&mut error_ctx, cli_options);
816
817 let traits_to_remove: HashSet<rustc_hir::def_id::DefId> = {
818 let hax_state = hax::state::State::new(tcx, hax::options::Options::default());
819 translate_options
820 .hide_traits
821 .iter()
822 .flat_map(|pat| super::resolve_path::def_path_def_ids(&hax_state, pat, true).unwrap())
823 .collect()
824 };
825 let hax_state = hax::state::State::new(
826 tcx,
827 hax::options::Options {
828 inline_anon_consts: !translate_options.raw_consts,
829 bounds_options: hax::options::BoundsOptions {
830 add_destruct_bounds: translate_options.add_destruct_bounds,
831 remove_traits: traits_to_remove,
832 },
833 },
834 );
835
836 let crate_def_id: hax::DefId = rustc_span::def_id::CRATE_DEF_ID
837 .to_def_id()
838 .sinto(&hax_state);
839 let crate_name = crate_def_id.crate_name(&hax_state).to_string();
840 trace!("# Crate: {}", crate_name);
841
842 let mut ctx = TranslateCtx {
843 tcx,
844 sysroot,
845 hax_state,
846 options: translate_options,
847 errors: RefCell::new(error_ctx),
848 translated: TranslatedCrate {
849 crate_name,
850 options: cli_options.clone(),
851 ..TranslatedCrate::default()
852 },
853 method_status: Default::default(),
854 assoc_item_id_map: Default::default(),
855 id_map: Default::default(),
856 reverse_id_map: Default::default(),
857 file_to_id: Default::default(),
858 items_to_translate: Default::default(),
859 processed: Default::default(),
860 translate_stack: Default::default(),
861 cached_item_metas: Default::default(),
862 cached_names: Default::default(),
863 lt_mutability_computer: Default::default(),
864 };
865 ctx.register_target_info();
866
867 for start_from in ctx.options.start_from.clone() {
869 match start_from {
870 StartFrom::Pattern { pattern, strict } => {
871 match super::resolve_path::def_path_def_ids(&ctx.hax_state, &pattern, strict) {
872 Ok(resolved) => {
873 for def_id in resolved {
874 let def_id: hax::DefId = def_id.sinto(&ctx.hax_state);
875 ctx.enqueue_module_item(&def_id);
876 }
877 }
878 Err(err) => {
879 register_error!(
880 ctx,
881 Span::dummy(),
882 "when processing starting pattern `{pattern}`: {err}"
883 );
884 }
885 }
886 }
887 StartFrom::Attribute(attr_name) => {
888 let attr_path = attr_name
889 .split("::")
890 .map(rustc_span::Symbol::intern)
891 .collect_vec();
892 let mut add_if_attr_matches = |ldid: rustc_hir::def_id::LocalDefId| {
893 let def_id: hax::DefId = ldid.to_def_id().sinto(&ctx.hax_state);
894 if !matches!(def_id.kind, hax::DefKind::Mod)
895 && def_id.attrs(tcx).iter().any(|a| a.path_matches(&attr_path))
896 {
897 ctx.enqueue_module_item(&def_id);
898 }
899 };
900 for ldid in tcx.hir_crate_items(()).definitions() {
901 add_if_attr_matches(ldid)
902 }
903 }
904 StartFrom::Pub => {
905 let mut add_if_matches = |ldid: rustc_hir::def_id::LocalDefId| {
906 let def_id: hax::DefId = ldid.to_def_id().sinto(&ctx.hax_state);
907 if !matches!(def_id.kind, hax::DefKind::Mod)
908 && def_id.visibility(tcx) == Some(true)
909 {
910 ctx.enqueue_module_item(&def_id);
911 }
912 };
913 for ldid in tcx.hir_crate_items(()).definitions() {
914 add_if_matches(ldid)
915 }
916 }
917 }
918 }
919
920 if ctx.errors.borrow().has_errors() {
921 return Err(Error::dummy());
923 }
924
925 trace!(
926 "Queue after we explored the crate:\n{:?}",
927 &ctx.items_to_translate
928 );
929
930 while let Some(item_src) = ctx.items_to_translate.pop_front() {
940 if ctx.processed.insert(item_src.clone()) {
941 ctx.translate_item(&item_src);
942 }
943 }
944
945 ctx.remove_unused_methods();
948
949 Ok(TransformCtx {
951 options: ctx.options,
952 translated: ctx.translated,
953 errors: ctx.errors,
954 })
955}