1use crate::hax::prelude::*;
2use annotate_snippets::Level;
3use rustc_middle::ty::{self, TyCtxt};
4
5mod base {
6 use crate::hax::prelude::*;
7 use itertools::Itertools;
8 use rustc_hash::FxHashMap;
9 use rustc_hir::def_id::{CrateNum, LOCAL_CRATE};
10 use rustc_middle::ty;
11 use rustc_span::symbol::Symbol;
12 use rustc_trait_elaboration::{ElaborationCtx, ItemRefKey, intern::Interner};
13 use std::{cell::RefCell, sync::Arc};
14
15 pub struct LocalContextS {
16 pub vars: HashMap<rustc_middle::thir::LocalVarId, String>,
17 }
18
19 impl Default for LocalContextS {
20 fn default() -> Self {
21 Self::new()
22 }
23 }
24
25 impl LocalContextS {
26 pub fn new() -> LocalContextS {
27 LocalContextS {
28 vars: HashMap::default(),
29 }
30 }
31 }
32
33 #[derive(Default)]
35 pub struct GlobalCache<'tcx> {
36 pub per_item: HashMap<DefId, ItemCache<'tcx>>,
38 pub def_ids: HashMap<RDefId, DefId>,
40 pub synthetic_item_data: HashMap<SyntheticItem, SyntheticItemData<'tcx>>,
42 pub anon_allocs: indexmap::IndexSet<RAllocId>,
45 pub alloc_types: rustc_const_uneval::AllocTypes<'tcx>,
47 pub disambiguated_crate_names: Option<FxHashMap<CrateNum, (Symbol, u32)>>,
49 }
50
51 impl<'tcx> GlobalCache<'tcx> {
52 pub fn crate_name(&mut self, tcx: ty::TyCtxt<'tcx>, krate: CrateNum) -> (Symbol, u32) {
53 self.disambiguated_crate_names
54 .get_or_insert_with(|| {
55 std::iter::once(LOCAL_CRATE)
56 .chain(tcx.crates(()).iter().copied())
57 .into_group_map_by(|&cnum| tcx.crate_name(cnum))
58 .into_iter()
59 .filter(|(_, crates_by_this_name)| crates_by_this_name.len() > 1)
60 .flat_map(|(name, mut crates_by_this_name)| {
61 crates_by_this_name.sort_by_key(|&cnum| {
62 let source_file = tcx
65 .sess
66 .source_map()
67 .span_to_filename(tcx.def_span(cnum.as_def_id()))
68 .prefer_remapped_unconditionally()
69 .to_string_lossy()
70 .into_owned();
71 let extern_paths = if cnum == LOCAL_CRATE {
72 Vec::new()
73 } else {
74 tcx.crate_extern_paths(cnum)
75 .iter()
76 .map(|path| path.display().to_string())
77 .collect_vec()
78 };
79 (
80 cnum != LOCAL_CRATE,
81 source_file,
82 extern_paths,
83 cnum.as_u32(),
84 )
85 });
86 crates_by_this_name.into_iter().enumerate().map(
87 move |(disambiguator, cnum)| (cnum, (name, disambiguator as u32)),
88 )
89 })
90 .collect()
91 })
92 .get(&krate)
93 .copied()
94 .unwrap_or_else(|| (tcx.crate_name(krate), 0))
95 }
96 }
97
98 #[derive(Default)]
100 pub struct ItemCache<'tcx> {
101 pub full_defs:
106 HashMap<(Option<PromotedId>, Option<ty::GenericArgsRef<'tcx>>), Arc<FullDef<'tcx>>>,
107 pub tys: HashMap<ty::Ty<'tcx>, Ty<'tcx>>,
109 pub item_refs: HashMap<ItemRefKey<'tcx, DefId>, ItemRef<'tcx>>,
111 pub trait_proofs: HashMap<ty::PolyTraitRef<'tcx>, crate::hax::traits::TraitProof<'tcx>>,
113 pub virtual_generics: Option<&'tcx ty::Generics>,
115 }
116
117 #[derive(Clone)]
118 pub struct Base<'tcx> {
119 pub ty_interner: &'tcx Interner<'tcx, TyKind<'tcx>>,
120 pub trait_proof_interner: &'tcx Interner<'tcx, TraitProofContents<'tcx>>,
121 pub item_ref_interner: &'tcx Interner<'tcx, ItemRefContents<'tcx>>,
122 pub options: Rc<crate::hax::options::Options>,
123 pub local_ctx: Rc<RefCell<LocalContextS>>,
124 pub opt_def_id: Option<rustc_hir::def_id::DefId>,
125 pub cache: Rc<RefCell<GlobalCache<'tcx>>>,
126 pub elab_ctx: crate::hax::traits::ElaborationCtx<'tcx, DefId>,
127 pub tcx: ty::TyCtxt<'tcx>,
128 }
129
130 impl<'tcx> Base<'tcx> {
131 pub fn new(
132 tcx: rustc_middle::ty::TyCtxt<'tcx>,
133 options: crate::hax::options::Options,
134 bounds_options: crate::hax::options::BoundsOptions,
135 ) -> Self {
136 Self {
137 tcx,
138 ty_interner: Box::leak(Box::default()),
139 trait_proof_interner: Box::leak(Box::default()),
140 item_ref_interner: Box::leak(Box::default()),
141 cache: Default::default(),
142 options: Rc::new(options),
143 opt_def_id: None,
146 local_ctx: Rc::new(RefCell::new(LocalContextS::new())),
147 elab_ctx: ElaborationCtx::new(tcx, bounds_options),
148 }
149 }
150 }
151}
152
153pub use self::base::*;
154
155pub trait BaseState<'tcx>: Sized {
156 fn base(&self) -> Base<'tcx>;
157
158 fn tcx(&self) -> TyCtxt<'tcx> {
159 self.base().tcx
160 }
161
162 fn raise(&self, level: Level, span: Span, msg: String) {
164 let backtrace = std::backtrace::Backtrace::capture();
165 eprintln!("{}", backtrace);
166 let dcx = self.tcx().dcx();
167 if level == Level::ERROR {
168 dcx.span_err(span, msg);
169 } else {
170 dcx.span_warn(span, msg);
171 }
172 }
173
174 fn with_hax_owner(&self, owner: &DefId) -> StateWithOwner<'tcx> {
176 let mut base = self.base();
177 base.opt_def_id = owner.as_real_or_promoted();
178 State {
179 owner: owner.clone(),
180 base,
181 }
182 }
183 fn with_rustc_owner(&self, owner_id: RDefId) -> StateWithOwner<'tcx> {
185 let owner = &owner_id.sinto(self);
186 Self::with_hax_owner(self, owner)
187 }
188
189 fn base_state(&self) -> StateWithBase<'tcx> {
191 State {
192 base: self.base(),
193 owner: (),
194 }
195 }
196
197 fn with_global_cache<T>(&self, f: impl FnOnce(&mut GlobalCache<'tcx>) -> T) -> T {
200 let base = self.base();
201 let mut cache = base.cache.borrow_mut();
202 f(&mut cache)
203 }
204 fn with_item_cache<T>(&self, def_id: &DefId, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
207 self.with_global_cache(|cache| f(cache.per_item.entry(def_id.clone()).or_default()))
208 }
209}
210
211pub trait UnderOwnerState<'tcx>: BaseState<'tcx> {
212 fn owner(&self) -> DefId;
213
214 fn param_env(&self) -> ty::ParamEnv<'tcx> {
215 self.owner().param_env(self)
216 }
217 fn typing_env(&self) -> ty::TypingEnv<'tcx> {
218 self.owner().typing_env(self)
219 }
220
221 fn as_state_with_owner(&self) -> StateWithOwner<'tcx> {
222 State {
223 base: self.base(),
224 owner: self.owner(),
225 }
226 }
227
228 fn with_cache<T>(&self, f: impl FnOnce(&mut ItemCache<'tcx>) -> T) -> T {
231 self.with_item_cache(&self.owner(), f)
232 }
233 fn with_predicate_searcher<T>(
234 &self,
235 f: impl FnOnce(&mut PredicateSearcher<'tcx>, &StateWithBase<'tcx>) -> T,
236 ) -> T {
237 let s = self;
238 let base = s.base();
239 let owner = s.owner();
240 let base_state = s.base_state();
241 let mut predicate_searcher = base.elab_ctx.predicate_searcher_for(&base_state, owner);
242 f(&mut predicate_searcher, &base_state)
243 }
244}
245
246#[derive(Clone)]
247pub struct State<'tcx, Owner> {
248 pub base: Base<'tcx>,
249 pub owner: Owner,
250}
251
252pub type StateWithBase<'tcx> = State<'tcx, ()>;
253pub type StateWithOwner<'tcx> = State<'tcx, DefId>;
254
255impl<'tcx> StateWithBase<'tcx> {
256 pub fn new(
257 tcx: rustc_middle::ty::TyCtxt<'tcx>,
258 options: crate::hax::options::Options,
259 bounds_options: crate::hax::options::BoundsOptions,
260 ) -> Self {
261 Self {
262 base: Base::new(tcx, options, bounds_options),
263 owner: (),
264 }
265 }
266}
267impl<'tcx, O> BaseState<'tcx> for State<'tcx, O> {
268 fn base(&self) -> Base<'tcx> {
269 self.base.clone()
270 }
271}
272impl<'tcx> UnderOwnerState<'tcx> for StateWithOwner<'tcx> {
273 fn owner(&self) -> DefId {
274 self.owner.clone()
275 }
276}
277
278impl<'tcx, A: BaseState<'tcx>, B> BaseState<'tcx> for (A, B) {
279 fn base(&self) -> Base<'tcx> {
280 self.0.base()
281 }
282}
283impl<'tcx, A: UnderOwnerState<'tcx>, B> UnderOwnerState<'tcx> for (A, B) {
284 fn owner(&self) -> DefId {
285 self.0.owner()
286 }
287}