1use super::translate_crate::TransItemSource;
3use super::translate_generics::BindingLevel;
4use charon_lib::ast::*;
5use charon_lib::formatter::{FmtCtx, IntoFormatter};
6use charon_lib::ids::Vector;
7use charon_lib::options::TranslateOptions;
8use hax_frontend_exporter::{self as hax, DefId, SInto};
9use rustc_middle::ty::TyCtxt;
10use std::borrow::Cow;
11use std::cell::RefCell;
12use std::collections::{BTreeSet, HashMap, HashSet};
13use std::fmt::Debug;
14use std::path::PathBuf;
15use std::sync::Arc;
16use std::{fmt, mem};
17
18pub(crate) use charon_lib::errors::{
20 error_assert, raise_error, register_error, DepSource, ErrorCtx, Level,
21};
22
23pub struct TranslateCtx<'tcx> {
25 pub tcx: TyCtxt<'tcx>,
27 pub sysroot: PathBuf,
29 pub hax_state: hax::StateWithBase<'tcx>,
31
32 pub options: TranslateOptions,
34 pub translated: TranslatedCrate,
36
37 pub id_map: HashMap<TransItemSource, AnyTransId>,
39 pub reverse_id_map: HashMap<AnyTransId, TransItemSource>,
41 pub file_to_id: HashMap<FileName, FileId>,
43
44 pub errors: RefCell<ErrorCtx>,
46 pub items_to_translate: BTreeSet<TransItemSource>,
49 pub processed: HashSet<TransItemSource>,
51 pub cached_names: HashMap<hax::DefId, Name>,
53 pub cached_item_metas: HashMap<TransItemSource, ItemMeta>,
55}
56
57pub(crate) struct ItemTransCtx<'tcx, 'ctx> {
60 pub def_id: hax::DefId,
63 pub item_id: Option<AnyTransId>,
65 pub t_ctx: &'ctx mut TranslateCtx<'tcx>,
67 pub error_on_impl_expr_error: bool,
70
71 pub binding_levels: BindingStack<BindingLevel>,
75 pub parent_trait_clauses: Vector<TraitClauseId, TraitClause>,
77 pub item_trait_clauses: HashMap<TraitItemName, Vector<TraitClauseId, TraitClause>>,
79 pub self_clause_id: Option<TraitClauseId>,
82}
83
84pub fn catch_sinto<S, T, U>(
86 s: &S,
87 err: &mut ErrorCtx,
88 krate: &TranslatedCrate,
89 span: Span,
90 x: &T,
91) -> Result<U, Error>
92where
93 T: Debug + SInto<S, U>,
94{
95 let unwind_safe_s = std::panic::AssertUnwindSafe(s);
96 let unwind_safe_x = std::panic::AssertUnwindSafe(x);
97 std::panic::catch_unwind(move || unwind_safe_x.sinto(*unwind_safe_s)).or_else(|_| {
98 raise_error!(
99 err,
100 crate(krate),
101 span,
102 "Hax panicked when translating `{x:?}`."
103 )
104 })
105}
106
107impl<'tcx, 'ctx> TranslateCtx<'tcx> {
108 pub fn span_err(&self, span: Span, msg: &str, level: Level) -> Error {
110 self.errors
111 .borrow_mut()
112 .span_err(&self.translated, span, msg, level)
113 }
114
115 pub fn catch_sinto<S, T, U>(&mut self, s: &S, span: Span, x: &T) -> Result<U, Error>
117 where
118 T: Debug + SInto<S, U>,
119 {
120 catch_sinto(s, &mut *self.errors.borrow_mut(), &self.translated, span, x)
121 }
122
123 pub fn hax_def(&mut self, def_id: &hax::DefId) -> Result<Arc<hax::FullDef>, Error> {
124 let span = self.def_span(def_id);
125 let unwind_safe_s = std::panic::AssertUnwindSafe(&self.hax_state);
127 std::panic::catch_unwind(move || def_id.full_def(*unwind_safe_s))
128 .or_else(|_| raise_error!(self, span, "Hax panicked when translating `{def_id:?}`."))
129 }
130
131 pub(crate) fn get_lang_item(&self, item: rustc_hir::LangItem) -> DefId {
132 self.tcx
133 .lang_items()
134 .get(item)
135 .unwrap()
136 .sinto(&self.hax_state)
137 }
138
139 pub(crate) fn with_def_id<F, T>(
140 &mut self,
141 def_id: &hax::DefId,
142 item_id: Option<AnyTransId>,
143 f: F,
144 ) -> T
145 where
146 F: FnOnce(&mut Self) -> T,
147 {
148 let mut errors = self.errors.borrow_mut();
149 let current_def_id = mem::replace(&mut errors.def_id, item_id);
150 let current_def_id_is_local = mem::replace(&mut errors.def_id_is_local, def_id.is_local);
151 drop(errors); let ret = f(self);
153 let mut errors = self.errors.borrow_mut();
154 errors.def_id = current_def_id;
155 errors.def_id_is_local = current_def_id_is_local;
156 ret
157 }
158}
159
160impl<'tcx, 'ctx> ItemTransCtx<'tcx, 'ctx> {
161 pub(crate) fn new(
163 def_id: hax::DefId,
164 item_id: Option<AnyTransId>,
165 t_ctx: &'ctx mut TranslateCtx<'tcx>,
166 ) -> Self {
167 ItemTransCtx {
168 def_id,
169 item_id,
170 t_ctx,
171 error_on_impl_expr_error: true,
172 binding_levels: Default::default(),
173 parent_trait_clauses: Default::default(),
174 item_trait_clauses: Default::default(),
175 self_clause_id: Default::default(),
176 }
177 }
178
179 pub fn span_err(&self, span: Span, msg: &str, level: Level) -> Error {
180 self.t_ctx.span_err(span, msg, level)
181 }
182
183 pub(crate) fn hax_def(&mut self, def_id: &hax::DefId) -> Result<Arc<hax::FullDef>, Error> {
184 self.t_ctx.hax_def(def_id)
185 }
186
187 pub(crate) fn get_lang_item(&self, item: rustc_hir::LangItem) -> DefId {
188 self.t_ctx.get_lang_item(item)
189 }
190}
191
192impl<'a> IntoFormatter for &'a TranslateCtx<'_> {
193 type C = FmtCtx<'a>;
194 fn into_fmt(self) -> Self::C {
195 self.translated.into_fmt()
196 }
197}
198
199impl<'a> IntoFormatter for &'a ItemTransCtx<'_, '_> {
200 type C = FmtCtx<'a>;
201 fn into_fmt(self) -> Self::C {
202 FmtCtx {
203 translated: Some(&self.t_ctx.translated),
204 generics: self.binding_levels.map_ref(|bl| Cow::Borrowed(&bl.params)),
205 locals: None,
206 indent_level: 0,
207 }
208 }
209}
210
211impl<'tcx, 'ctx> fmt::Display for TranslateCtx<'tcx> {
212 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
213 self.translated.fmt(f)
214 }
215}