1use super::translate_crate::RustcItem;
3pub use super::translate_crate::{TraitImplSource, TransItemSource, TransItemSourceKind};
4use super::translate_generics::BindingLevel;
5use charon_lib::ast::*;
6use charon_lib::formatter::{FmtCtx, IntoFormatter};
7use charon_lib::ids::Vector;
8use charon_lib::options::TranslateOptions;
9use hax_frontend_exporter::{self as hax, SInto};
10use rustc_middle::ty::TyCtxt;
11use std::borrow::Cow;
12use std::cell::RefCell;
13use std::collections::{BTreeSet, HashMap, HashSet};
14use std::fmt::Debug;
15use std::path::PathBuf;
16use std::sync::Arc;
17use std::{fmt, mem};
18
19pub(crate) use charon_lib::errors::{
21 DepSource, ErrorCtx, Level, error_assert, raise_error, register_error,
22};
23
24pub struct TranslateCtx<'tcx> {
26 pub tcx: TyCtxt<'tcx>,
28 pub sysroot: PathBuf,
30 pub hax_state: hax::StateWithBase<'tcx>,
32
33 pub options: TranslateOptions,
35 pub translated: TranslatedCrate,
37
38 pub id_map: HashMap<TransItemSource, AnyTransId>,
40 pub reverse_id_map: HashMap<AnyTransId, TransItemSource>,
42 pub file_to_id: HashMap<FileName, FileId>,
44
45 pub errors: RefCell<ErrorCtx>,
47 pub items_to_translate: BTreeSet<TransItemSource>,
50 pub processed: HashSet<TransItemSource>,
52 pub translate_stack: Vec<AnyTransId>,
54 pub cached_names: HashMap<RustcItem, Name>,
56 pub cached_item_metas: HashMap<TransItemSource, ItemMeta>,
58}
59
60pub(crate) struct ItemTransCtx<'tcx, 'ctx> {
63 pub item_src: TransItemSource,
65 pub item_id: Option<AnyTransId>,
67 pub t_ctx: &'ctx mut TranslateCtx<'tcx>,
69 pub error_on_impl_expr_error: bool,
72
73 pub binding_levels: BindingStack<BindingLevel>,
77 pub parent_trait_clauses: Vector<TraitClauseId, TraitClause>,
79 pub item_trait_clauses: HashMap<TraitItemName, Vector<TraitClauseId, TraitClause>>,
81}
82
83pub fn catch_sinto<S, T, U>(
85 s: &S,
86 err: &mut ErrorCtx,
87 krate: &TranslatedCrate,
88 span: Span,
89 x: &T,
90) -> Result<U, Error>
91where
92 T: Debug + SInto<S, U>,
93{
94 let unwind_safe_s = std::panic::AssertUnwindSafe(s);
95 let unwind_safe_x = std::panic::AssertUnwindSafe(x);
96 std::panic::catch_unwind(move || unwind_safe_x.sinto(*unwind_safe_s)).or_else(|_| {
97 raise_error!(
98 err,
99 crate(krate),
100 span,
101 "Hax panicked when translating `{x:?}`."
102 )
103 })
104}
105
106impl<'tcx, 'ctx> TranslateCtx<'tcx> {
107 pub fn span_err(&self, span: Span, msg: &str, level: Level) -> Error {
109 self.errors
110 .borrow_mut()
111 .span_err(&self.translated, span, msg, level)
112 }
113
114 pub fn catch_sinto<S, T, U>(&mut self, s: &S, span: Span, x: &T) -> Result<U, Error>
116 where
117 T: Debug + SInto<S, U>,
118 {
119 catch_sinto(s, &mut *self.errors.borrow_mut(), &self.translated, span, x)
120 }
121
122 pub fn poly_hax_def(&mut self, def_id: &hax::DefId) -> Result<Arc<hax::FullDef>, Error> {
127 self.hax_def_for_item(&RustcItem::Poly(def_id.clone()))
128 }
129
130 pub fn hax_def_for_item(&mut self, item: &RustcItem) -> Result<Arc<hax::FullDef>, Error> {
133 let def_id = item.def_id();
134 let span = self.def_span(def_id);
135 if let RustcItem::Mono(item_ref) = item
136 && item_ref.has_param
137 {
138 raise_error!(self, span, "Item is not monomorphic: {item:?}")
139 }
140 let unwind_safe_s = std::panic::AssertUnwindSafe(&self.hax_state);
142 std::panic::catch_unwind(move || match item {
143 RustcItem::Poly(def_id) => def_id.full_def(*unwind_safe_s),
144 RustcItem::Mono(item_ref) => item_ref.instantiated_full_def(*unwind_safe_s),
145 })
146 .or_else(|_| raise_error!(self, span, "Hax panicked when translating `{def_id:?}`."))
147 }
148
149 pub(crate) fn with_def_id<F, T>(
150 &mut self,
151 def_id: &hax::DefId,
152 item_id: Option<AnyTransId>,
153 f: F,
154 ) -> T
155 where
156 F: FnOnce(&mut Self) -> T,
157 {
158 let mut errors = self.errors.borrow_mut();
159 let current_def_id = mem::replace(&mut errors.def_id, item_id);
160 let current_def_id_is_local = mem::replace(&mut errors.def_id_is_local, def_id.is_local);
161 drop(errors); let ret = f(self);
163 let mut errors = self.errors.borrow_mut();
164 errors.def_id = current_def_id;
165 errors.def_id_is_local = current_def_id_is_local;
166 ret
167 }
168}
169
170impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
171 pub(crate) fn new(
173 item_src: TransItemSource,
174 item_id: Option<AnyTransId>,
175 t_ctx: &'ctx mut TranslateCtx<'tcx>,
176 ) -> Self {
177 ItemTransCtx {
178 item_src,
179 item_id,
180 t_ctx,
181 error_on_impl_expr_error: true,
182 binding_levels: Default::default(),
183 parent_trait_clauses: Default::default(),
184 item_trait_clauses: Default::default(),
185 }
186 }
187
188 pub fn monomorphize(&self) -> bool {
190 matches!(self.item_src.item, RustcItem::Mono(..))
191 }
192
193 pub fn span_err(&self, span: Span, msg: &str, level: Level) -> Error {
194 self.t_ctx.span_err(span, msg, level)
195 }
196
197 pub fn hax_state(&self) -> &hax::StateWithBase<'tcx> {
198 &self.t_ctx.hax_state
199 }
200
201 pub fn hax_state_with_id(&self) -> hax::StateWithOwner<'tcx> {
202 use hax::BaseState;
203 let def_id = self.item_src.def_id().underlying_rust_def_id();
204 self.t_ctx.hax_state.clone().with_owner_id(def_id)
205 }
206
207 pub fn hax_def(&mut self, item: &hax::ItemRef) -> Result<Arc<hax::FullDef>, Error> {
210 let item = if self.monomorphize() {
211 RustcItem::Mono(item.clone())
212 } else {
213 RustcItem::Poly(item.def_id.clone())
214 };
215 self.t_ctx.hax_def_for_item(&item)
216 }
217
218 pub(crate) fn poly_hax_def(&mut self, def_id: &hax::DefId) -> Result<Arc<hax::FullDef>, Error> {
219 self.t_ctx.poly_hax_def(def_id)
220 }
221}
222
223impl<'a> IntoFormatter for &'a TranslateCtx<'_> {
224 type C = FmtCtx<'a>;
225 fn into_fmt(self) -> Self::C {
226 self.translated.into_fmt()
227 }
228}
229
230impl<'a> IntoFormatter for &'a ItemTransCtx<'_, '_> {
231 type C = FmtCtx<'a>;
232 fn into_fmt(self) -> Self::C {
233 FmtCtx {
234 translated: Some(&self.t_ctx.translated),
235 generics: self.binding_levels.map_ref(|bl| Cow::Borrowed(&bl.params)),
236 locals: None,
237 indent_level: 0,
238 }
239 }
240}
241
242impl<'tcx, 'ctx> fmt::Display for TranslateCtx<'tcx> {
243 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
244 self.translated.fmt(f)
245 }
246}