1use crate::prelude::*;
2use paste::paste;
3
4macro_rules! mk_aux {
5 ($state:ident {$($lts:lifetime)*} $field:ident {$($field_type:tt)+} {$($gen:tt)*} {$($gen_full:tt)*} {$($params:tt)*} {$($fields:tt)*}) => {
6 paste ! {
7 pub trait [<Has $field:camel>]<$($lts,)*> {
8 fn $field(self: &Self) -> $($field_type)+<$($lts)*>;
9 }
10 impl<$($lts,)*$($gen)*> [<Has $field:camel>]<$($lts,)*> for $state<$($params)*> {
11 fn $field(self: &Self) -> $($field_type)+<$($lts)*> {
12 self.$field.clone()
13 }
14 }
15 }
16 };
17}
18macro_rules! mk {
19 (struct $state:ident<$($glts:lifetime),*> {$($field:ident : {$($lts:lifetime),*} $field_type:ty),*$(,)?}) => {
20 mk!(@$state {} {$($field)*} {$($field: {$($lts),*} {$field_type},)*});
21 };
22 (@$state:ident {$($acc:tt)*} $fields:tt {
23 $field:ident : $lts:tt $field_type:tt
24 $(,$($rest:tt)*)?
25 }) => {mk!(@$state {
26 $($acc)* $fields $field: $lts $field_type,
27 } $fields {$($($rest)*)?} );};
28 (@$state:ident $body:tt $fields:tt {$(,)?}) => { mk! (@@ $state $body ); };
29 (@@$state:ident {$({$($fields:tt)*} $field:ident : {$($lts:lifetime)*} {$($field_type:tt)+},)*}) => {
30 paste! {
31 #[derive(Clone)]
32 pub struct $state<$([<$field:camel>],)*>{
33 $(pub $field: [<$field:camel>],)*
34 }
35 }
36 $(
37 macro_rules! __inner_helper {
38 ($gen:tt {$$($full_gen:tt)*} {$$($params:tt)*} $field $$($rest:tt)*) => {
39 paste! {__inner_helper!(
40 $gen {$$($full_gen)*[<$field:camel>],}
41 {$$($params)*$($field_type)+<$($lts,)*>,} $$($rest)*
42 );}
43 };
44 ({$$($gen:tt)*} {$$($full_gen:tt)*} {$$($params:tt)*} $i:ident $$($rest:tt)*) => {
45 paste! {__inner_helper!(
46 {$$($gen)*[<$i:camel>],} {$$($full_gen)*[<$i:camel>],}
47 {$$($params)*[<$i:camel>],} $$($rest)*
48 );}
49 };
50 ($gen:tt $full_gen:tt $params:tt $$(,)?) => {
51 mk_aux!($state {$($lts)*} $field {$($field_type)+} $gen $full_gen $params {$($fields)*});
52 };
53 }
54 __inner_helper!({} {} {} $($fields)*);
55 )*
56 };
57}
58
59mod types {
60 use crate::prelude::*;
61 use rustc_middle::ty;
62 use std::{cell::RefCell, sync::Arc};
63
64 pub struct LocalContextS {
65 pub vars: HashMap<rustc_middle::thir::LocalVarId, String>,
66 }
67
68 impl Default for LocalContextS {
69 fn default() -> Self {
70 Self::new()
71 }
72 }
73
74 impl LocalContextS {
75 pub fn new() -> LocalContextS {
76 LocalContextS {
77 vars: HashMap::new(),
78 }
79 }
80 }
81
82 #[derive(Default)]
84 pub struct GlobalCache<'tcx> {
85 pub spans: HashMap<rustc_span::Span, Span>,
87 pub per_item: HashMap<RDefId, ItemCache<'tcx>>,
89 pub id_table_session: id_table::Session,
91 pub reverse_item_refs_map: HashMap<id_table::Id, ty::GenericArgsRef<'tcx>>,
93 pub synthetic_def_ids: HashMap<SyntheticItem, RDefId>,
96 pub reverse_synthetic_map: HashMap<RDefId, SyntheticItem>,
97 }
98
99 pub struct FullDefMapper;
101 impl TypeMapper for FullDefMapper {
102 type Value<Body: TypeMappable> = Arc<FullDef<Body>>;
103 }
104
105 #[derive(Default)]
107 pub struct ItemCache<'tcx> {
108 pub def_id: Option<DefId>,
110 pub full_defs:
115 HashMap<(Option<PromotedId>, Option<ty::GenericArgsRef<'tcx>>), TypeMap<FullDefMapper>>,
116 pub tys: HashMap<ty::Ty<'tcx>, Ty>,
118 pub item_refs: HashMap<(RDefId, ty::GenericArgsRef<'tcx>), ItemRef>,
120 pub predicate_searcher: Option<crate::traits::PredicateSearcher<'tcx>>,
122 pub impl_exprs: HashMap<ty::PolyTraitRef<'tcx>, crate::traits::ImplExpr>,
124 }
125
126 #[derive(Clone)]
127 pub struct Base<'tcx> {
128 pub options: Rc<hax_frontend_exporter_options::Options>,
129 pub local_ctx: Rc<RefCell<LocalContextS>>,
130 pub opt_def_id: Option<rustc_hir::def_id::DefId>,
131 pub cache: Rc<RefCell<GlobalCache<'tcx>>>,
132 pub tcx: ty::TyCtxt<'tcx>,
133 pub silence_resolution_errors: bool,
135 }
136
137 impl<'tcx> Base<'tcx> {
138 pub fn new(
139 tcx: rustc_middle::ty::TyCtxt<'tcx>,
140 options: hax_frontend_exporter_options::Options,
141 ) -> Self {
142 Self {
143 tcx,
144 cache: Default::default(),
145 options: Rc::new(options),
146 opt_def_id: None,
149 local_ctx: Rc::new(RefCell::new(LocalContextS::new())),
150 silence_resolution_errors: false,
151 }
152 }
153 }
154
155 pub type MacroCalls = Rc<HashMap<Span, Span>>;
156 pub type RcThir<'tcx> = Rc<rustc_middle::thir::Thir<'tcx>>;
157 pub type RcMir<'tcx> = Rc<rustc_middle::mir::Body<'tcx>>;
158 pub type UnitBinder<'tcx> = rustc_middle::ty::Binder<'tcx, ()>;
159}
160
161mk!(
162 struct State<'tcx> {
163 base: {'tcx} types::Base,
164 owner_id: {} rustc_hir::def_id::DefId,
165 thir: {'tcx} types::RcThir,
166 mir: {'tcx} types::RcMir,
167 binder: {'tcx} types::UnitBinder,
168 ty: {'tcx} rustc_middle::ty::Ty,
169 }
170);
171
172pub use self::types::*;
173
174pub type StateWithBase<'tcx> = State<Base<'tcx>, (), (), (), (), ()>;
175pub type StateWithOwner<'tcx> = State<Base<'tcx>, rustc_hir::def_id::DefId, (), (), (), ()>;
176pub type StateWithBinder<'tcx> =
177 State<Base<'tcx>, rustc_hir::def_id::DefId, (), (), types::UnitBinder<'tcx>, ()>;
178pub type StateWithThir<'tcx> =
179 State<Base<'tcx>, rustc_hir::def_id::DefId, types::RcThir<'tcx>, (), (), ()>;
180pub type StateWithThirAndTy<'tcx> = State<
181 Base<'tcx>,
182 rustc_hir::def_id::DefId,
183 types::RcThir<'tcx>,
184 (),
185 (),
186 rustc_middle::ty::Ty<'tcx>,
187>;
188pub type StateWithMir<'tcx> =
189 State<Base<'tcx>, rustc_hir::def_id::DefId, (), types::RcMir<'tcx>, (), ()>;
190
191impl<'tcx> StateWithBase<'tcx> {
192 pub fn new(
193 tcx: rustc_middle::ty::TyCtxt<'tcx>,
194 options: hax_frontend_exporter_options::Options,
195 ) -> Self {
196 Self {
197 base: Base::new(tcx, options),
198 owner_id: (),
199 thir: (),
200 mir: (),
201 binder: (),
202 ty: (),
203 }
204 }
205}
206
207pub trait BaseState<'tcx>: HasBase<'tcx> + Clone {
208 fn with_owner_id(&self, owner_id: rustc_hir::def_id::DefId) -> StateWithOwner<'tcx> {
210 let mut base = self.base();
211 base.opt_def_id = Some(owner_id);
212 State {
213 owner_id,
214 base,
215 thir: (),
216 mir: (),
217 binder: (),
218 ty: (),
219 }
220 }
221}
222impl<'tcx, T: HasBase<'tcx> + Clone> BaseState<'tcx> for T {}
223
224pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwnerId {
226 fn with_base(&self, base: types::Base<'tcx>) -> StateWithOwner<'tcx> {
227 State {
228 owner_id: self.owner_id(),
229 base,
230 thir: (),
231 mir: (),
232 binder: (),
233 ty: (),
234 }
235 }
236 fn with_binder(&self, binder: types::UnitBinder<'tcx>) -> StateWithBinder<'tcx> {
237 State {
238 base: self.base(),
239 owner_id: self.owner_id(),
240 binder,
241 thir: (),
242 mir: (),
243 ty: (),
244 }
245 }
246 fn with_thir(&self, thir: types::RcThir<'tcx>) -> StateWithThir<'tcx> {
247 State {
248 base: self.base(),
249 owner_id: self.owner_id(),
250 thir,
251 mir: (),
252 binder: (),
253 ty: (),
254 }
255 }
256 fn with_mir(&self, mir: types::RcMir<'tcx>) -> StateWithMir<'tcx> {
257 State {
258 base: self.base(),
259 owner_id: self.owner_id(),
260 mir,
261 thir: (),
262 binder: (),
263 ty: (),
264 }
265 }
266}
267impl<'tcx, T: BaseState<'tcx> + HasOwnerId> UnderOwnerState<'tcx> for T {}
268
269pub trait UnderBinderState<'tcx> = UnderOwnerState<'tcx> + HasBinder<'tcx>;
271
272pub trait ExprState<'tcx>: UnderOwnerState<'tcx> + HasThir<'tcx> {
275 fn with_ty(&self, ty: rustc_middle::ty::Ty<'tcx>) -> StateWithThirAndTy<'tcx> {
276 State {
277 base: self.base(),
278 owner_id: self.owner_id(),
279 thir: self.thir(),
280 mir: (),
281 binder: (),
282 ty,
283 }
284 }
285}
286impl<'tcx, T> ExprState<'tcx> for T where T: UnderOwnerState<'tcx> + HasThir<'tcx> {}
287
288pub trait WithGlobalCacheExt<'tcx>: BaseState<'tcx> {
289 fn with_global_cache<T>(&self, f: impl FnOnce(&mut GlobalCache<'tcx>) -> T) -> T {
292 let base = self.base();
293 let mut cache = base.cache.borrow_mut();
294 f(&mut *cache)
295 }
296 fn with_item_cache<T>(&self, def_id: RDefId, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
299 self.with_global_cache(|cache| f(cache.per_item.entry(def_id).or_default()))
300 }
301}
302impl<'tcx, S: BaseState<'tcx>> WithGlobalCacheExt<'tcx> for S {}
303
304pub trait WithItemCacheExt<'tcx>: UnderOwnerState<'tcx> {
305 fn with_cache<T>(&self, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
308 self.with_item_cache(self.owner_id(), f)
309 }
310 fn with_predicate_searcher<T>(&self, f: impl FnOnce(&mut PredicateSearcher<'tcx>) -> T) -> T {
311 self.with_cache(|cache| {
312 f(cache.predicate_searcher.get_or_insert_with(|| {
313 PredicateSearcher::new_for_owner(
314 self.base().tcx,
315 self.owner_id(),
316 self.base().options.bounds_options,
317 )
318 }))
319 })
320 }
321}
322impl<'tcx, S: UnderOwnerState<'tcx>> WithItemCacheExt<'tcx> for S {}
323
324impl ImplInfos {
325 fn from<'tcx, S: BaseState<'tcx>>(s: &S, did: rustc_hir::def_id::DefId) -> Self {
326 let tcx = s.base().tcx;
327 let s = &s.with_owner_id(did);
328
329 Self {
330 generics: tcx.generics_of(did).sinto(s),
331 typ: tcx.type_of(did).instantiate_identity().sinto(s),
332 trait_ref: match tcx.def_kind(did) {
333 rustc_hir::def::DefKind::Impl { of_trait: true } => {
334 Some(tcx.impl_trait_ref(did).instantiate_identity().sinto(s))
335 }
336 _ => None,
337 },
338 clauses: predicates_defined_on(tcx, did).as_ref().sinto(s),
339 }
340 }
341}
342
343pub fn impl_def_ids_to_impled_types_and_bounds<'tcx, S: BaseState<'tcx>>(
346 s: &S,
347) -> HashMap<DefId, ImplInfos> {
348 let tcx = s.base().tcx;
349
350 let def_ids: Vec<_> = s.with_global_cache(|cache| cache.per_item.keys().copied().collect());
351 let with_parents = |mut did: rustc_hir::def_id::DefId| {
352 let mut acc = vec![did];
353 while let Some(parent) = tcx.opt_parent(did) {
354 did = parent;
355 acc.push(did);
356 }
357 acc.into_iter()
358 };
359 use itertools::Itertools;
360 def_ids
361 .into_iter()
362 .flat_map(with_parents)
363 .unique()
364 .filter(|&did| {
365 matches!(
367 tcx.def_path(did).data.last(),
368 Some(rustc_hir::definitions::DisambiguatedDefPathData {
369 data: rustc_hir::definitions::DefPathData::Impl,
370 ..
371 })
372 )
373 })
374 .map(|did| (did.sinto(s), ImplInfos::from(s, did)))
375 .collect()
376}