1use crate::hax::prelude::*;
2use paste::paste;
3use rustc_middle::ty::TyCtxt;
4
5macro_rules! mk_aux {
6 ($state:ident {$($lts:lifetime)*} $field:ident {$($field_type:tt)+} {$($gen:tt)*} {$($gen_full:tt)*} {$($params:tt)*} {$($fields:tt)*}) => {
7 paste ! {
8 pub trait [<Has $field:camel>]<$($lts,)*> {
9 fn $field(self: &Self) -> $($field_type)+<$($lts)*>;
10 }
11 impl<$($lts,)*$($gen)*> [<Has $field:camel>]<$($lts,)*> for $state<$($params)*> {
12 fn $field(self: &Self) -> $($field_type)+<$($lts)*> {
13 self.$field.clone()
14 }
15 }
16 }
17 };
18}
19macro_rules! mk {
20 (struct $state:ident<$($glts:lifetime),*> {$($field:ident : {$($lts:lifetime),*} $field_type:ty),*$(,)?}) => {
21 mk!(@$state {} {$($field)*} {$($field: {$($lts),*} {$field_type},)*});
22 };
23 (@$state:ident {$($acc:tt)*} $fields:tt {
24 $field:ident : $lts:tt $field_type:tt
25 $(,$($rest:tt)*)?
26 }) => {mk!(@$state {
27 $($acc)* $fields $field: $lts $field_type,
28 } $fields {$($($rest)*)?} );};
29 (@$state:ident $body:tt $fields:tt {$(,)?}) => { mk! (@@ $state $body ); };
30 (@@$state:ident {$({$($fields:tt)*} $field:ident : {$($lts:lifetime)*} {$($field_type:tt)+},)*}) => {
31 paste! {
32 #[derive(Clone)]
33 pub struct $state<$([<$field:camel>],)*>{
34 $(pub $field: [<$field:camel>],)*
35 }
36 }
37 $(
38 macro_rules! __inner_helper {
39 ($gen:tt {$$($full_gen:tt)*} {$$($params:tt)*} $field $$($rest:tt)*) => {
40 paste! {__inner_helper!(
41 $gen {$$($full_gen)*[<$field:camel>],}
42 {$$($params)*$($field_type)+<$($lts,)*>,} $$($rest)*
43 );}
44 };
45 ({$$($gen:tt)*} {$$($full_gen:tt)*} {$$($params:tt)*} $i:ident $$($rest:tt)*) => {
46 paste! {__inner_helper!(
47 {$$($gen)*[<$i:camel>],} {$$($full_gen)*[<$i:camel>],}
48 {$$($params)*[<$i:camel>],} $$($rest)*
49 );}
50 };
51 ($gen:tt $full_gen:tt $params:tt $$(,)?) => {
52 mk_aux!($state {$($lts)*} $field {$($field_type)+} $gen $full_gen $params {$($fields)*});
53 };
54 }
55 __inner_helper!({} {} {} $($fields)*);
56 )*
57 };
58}
59
60mod types {
61 use crate::hax::prelude::*;
62 use rustc_middle::ty;
63 use std::{cell::RefCell, sync::Arc};
64
65 pub struct LocalContextS {
66 pub vars: HashMap<rustc_middle::thir::LocalVarId, String>,
67 }
68
69 impl Default for LocalContextS {
70 fn default() -> Self {
71 Self::new()
72 }
73 }
74
75 impl LocalContextS {
76 pub fn new() -> LocalContextS {
77 LocalContextS {
78 vars: HashMap::new(),
79 }
80 }
81 }
82
83 #[derive(Default)]
85 pub struct GlobalCache<'tcx> {
86 pub per_item: HashMap<RDefId, ItemCache<'tcx>>,
88 pub reverse_item_refs_map: HashMap<ItemRef, ty::GenericArgsRef<'tcx>>,
90 pub synthetic_def_ids: HashMap<SyntheticItem, RDefId>,
93 pub reverse_synthetic_map: HashMap<RDefId, SyntheticItem>,
94 }
95
96 #[derive(Default)]
98 pub struct ItemCache<'tcx> {
99 pub def_id: Option<DefId>,
101 pub full_defs:
106 HashMap<(Option<PromotedId>, Option<ty::GenericArgsRef<'tcx>>), Arc<FullDef>>,
107 pub tys: HashMap<ty::Ty<'tcx>, Ty>,
109 pub item_refs: HashMap<(DefId, ty::GenericArgsRef<'tcx>, bool), ItemRef>,
111 pub predicate_searcher: Option<crate::hax::traits::PredicateSearcher<'tcx>>,
113 pub impl_exprs: HashMap<ty::PolyTraitRef<'tcx>, crate::hax::traits::ImplExpr>,
115 }
116
117 #[derive(Clone)]
118 pub struct Base<'tcx> {
119 pub options: Rc<crate::hax::options::Options>,
120 pub local_ctx: Rc<RefCell<LocalContextS>>,
121 pub opt_def_id: Option<rustc_hir::def_id::DefId>,
122 pub cache: Rc<RefCell<GlobalCache<'tcx>>>,
123 pub tcx: ty::TyCtxt<'tcx>,
124 }
125
126 impl<'tcx> Base<'tcx> {
127 pub fn new(
128 tcx: rustc_middle::ty::TyCtxt<'tcx>,
129 options: crate::hax::options::Options,
130 ) -> Self {
131 Self {
132 tcx,
133 cache: Default::default(),
134 options: Rc::new(options),
135 opt_def_id: None,
138 local_ctx: Rc::new(RefCell::new(LocalContextS::new())),
139 }
140 }
141 }
142
143 pub type UnitBinder<'tcx> = rustc_middle::ty::Binder<'tcx, ()>;
144}
145
146mk!(
147 struct State<'tcx> {
148 base: {'tcx} types::Base,
149 owner: {} DefId,
150 binder: {'tcx} types::UnitBinder,
151 }
152);
153
154pub use self::types::*;
155
156pub type StateWithBase<'tcx> = State<Base<'tcx>, (), ()>;
157pub type StateWithOwner<'tcx> = State<Base<'tcx>, DefId, ()>;
158pub type StateWithBinder<'tcx> = State<Base<'tcx>, DefId, types::UnitBinder<'tcx>>;
159
160impl<'tcx> StateWithBase<'tcx> {
161 pub fn new(tcx: rustc_middle::ty::TyCtxt<'tcx>, options: crate::hax::options::Options) -> Self {
162 Self {
163 base: Base::new(tcx, options),
164 owner: (),
165 binder: (),
166 }
167 }
168}
169
170pub trait BaseState<'tcx>: HasBase<'tcx> + Clone {
171 fn tcx(&self) -> TyCtxt<'tcx> {
172 self.base().tcx
173 }
174
175 fn with_hax_owner(&self, owner: &DefId) -> StateWithOwner<'tcx> {
177 let mut base = self.base();
178 base.opt_def_id = owner.underlying_rust_def_id();
179 State {
180 owner: owner.clone(),
181 base,
182 binder: (),
183 }
184 }
185 fn with_rustc_owner(&self, owner_id: RDefId) -> StateWithOwner<'tcx> {
187 let owner = &owner_id.sinto(self);
188 Self::with_hax_owner(self, owner)
189 }
190}
191impl<'tcx, T: HasBase<'tcx> + Clone> BaseState<'tcx> for T {}
192
193pub trait UnderOwnerState<'tcx>: BaseState<'tcx> + HasOwner {
195 fn owner_id(&self) -> RDefId {
196 self.owner().as_def_id_even_synthetic()
197 }
198 fn with_base(&self, base: types::Base<'tcx>) -> StateWithOwner<'tcx> {
199 State {
200 owner: self.owner().clone(),
201 base,
202 binder: (),
203 }
204 }
205 fn with_binder(&self, binder: types::UnitBinder<'tcx>) -> StateWithBinder<'tcx> {
206 State {
207 base: self.base(),
208 owner: self.owner().clone(),
209 binder,
210 }
211 }
212}
213impl<'tcx, T: BaseState<'tcx> + HasOwner> UnderOwnerState<'tcx> for T {}
214
215pub trait UnderBinderState<'tcx> = UnderOwnerState<'tcx> + HasBinder<'tcx>;
217
218pub trait WithGlobalCacheExt<'tcx>: BaseState<'tcx> {
219 fn with_global_cache<T>(&self, f: impl FnOnce(&mut GlobalCache<'tcx>) -> T) -> T {
222 let base = self.base();
223 let mut cache = base.cache.borrow_mut();
224 f(&mut cache)
225 }
226 fn with_item_cache<T>(&self, def_id: RDefId, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
229 self.with_global_cache(|cache| f(cache.per_item.entry(def_id).or_default()))
230 }
231}
232impl<'tcx, S: BaseState<'tcx>> WithGlobalCacheExt<'tcx> for S {}
233
234pub trait WithItemCacheExt<'tcx>: UnderOwnerState<'tcx> {
235 fn with_cache<T>(&self, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
238 self.with_item_cache(self.owner_id(), f)
239 }
240 fn with_predicate_searcher<T>(&self, f: impl FnOnce(&mut PredicateSearcher<'tcx>) -> T) -> T {
241 self.with_cache(|cache| {
242 f(cache.predicate_searcher.get_or_insert_with(|| {
243 PredicateSearcher::new_for_owner(
244 self.base().tcx,
245 self.owner_id(),
246 &self.base().options.bounds_options,
247 )
248 }))
249 })
250 }
251}
252impl<'tcx, S: UnderOwnerState<'tcx>> WithItemCacheExt<'tcx> for S {}