1use rustc_middle::ty;
2use rustc_span::def_id::DefId as RDefId;
3
4pub use rustc_trait_elaboration as elaboration;
5pub use rustc_trait_elaboration::{
6 ItemPredicate, ItemPredicateId, ItemPredicates, PredicateSearcher, ToPolyTraitRef,
7 erase_and_norm, erase_free_regions, normalize, self_predicate,
8};
9
10use crate::hax::prelude::*;
11use charon_lib::ast::HashConsed;
12
13#[derive(Clone, Debug, Hash, PartialEq, Eq)]
14pub enum ImplExprPathChunk {
15 AssocItem {
16 item: ItemRef,
24 assoc_item: AssocItem,
25 predicate: Binder<TraitRef>,
27 index: usize,
29 },
30 Parent {
31 predicate: Binder<TraitRef>,
33 index: usize,
35 },
36}
37
38impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, ImplExprPathChunk> for elaboration::PathChunk<'tcx> {
39 fn sinto(&self, s: &S) -> ImplExprPathChunk {
40 match self {
41 elaboration::PathChunk::AssocItem {
42 item,
43 generic_args,
44 predicate,
45 index,
46 ..
47 } => ImplExprPathChunk::AssocItem {
48 item: translate_item_ref(s, item.def_id, generic_args),
49 assoc_item: AssocItem::sfrom(s, item),
50 predicate: predicate.sinto(s),
51 index: index.sinto(s),
52 },
53 elaboration::PathChunk::Parent {
54 predicate, index, ..
55 } => ImplExprPathChunk::Parent {
56 predicate: predicate.sinto(s),
57 index: index.sinto(s),
58 },
59 }
60 }
61}
62
63#[derive(AdtInto)]
66#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::ImplExprAtom<'tcx>, state: S as s)]
67#[derive(Clone, Debug, Hash, PartialEq, Eq)]
68pub enum ImplExprAtom {
69 #[custom_arm(FROM_TYPE::Concrete { def_id, generics } => TO_TYPE::Concrete(
71 translate_item_ref(s, *def_id, generics),
72 ),)]
73 Concrete(ItemRef),
74 LocalBound {
76 id: GenericPredicateId,
77 r#trait: Binder<TraitRef>,
78 path: Vec<ImplExprPathChunk>,
79 },
80 SelfImpl {
83 r#trait: Binder<TraitRef>,
84 path: Vec<ImplExprPathChunk>,
85 },
86 Dyn,
93 Builtin {
97 trait_data: BuiltinTraitData,
99 impl_exprs: Vec<ImplExpr>,
103 types: Vec<(DefId, Ty, Vec<ImplExpr>)>,
105 },
106 Error(String),
108}
109
110#[derive(AdtInto)]
111#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::BuiltinTraitData<'tcx>, state: S as s)]
112#[derive(Clone, Debug, Hash, PartialEq, Eq)]
113pub enum BuiltinTraitData {
114 Destruct(DestructData),
119 Other,
121}
122
123#[derive(AdtInto)]
124#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::DestructData<'tcx>, state: S as s)]
125#[derive(Clone, Debug, Hash, PartialEq, Eq)]
126pub enum DestructData {
127 Noop,
129 Implicit,
134 Glue {
136 ty: Ty,
138 },
139}
140
141pub type ImplExpr = HashConsed<ImplExprContents>;
146
147#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
148#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::ImplExpr<'tcx>, state: S as s)]
149pub struct ImplExprContents {
150 pub r#trait: Binder<TraitRef>,
152 pub r#impl: ImplExprAtom,
154}
155
156impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, ImplExpr> for elaboration::ImplExpr<'tcx> {
157 fn sinto(&self, s: &S) -> ImplExpr {
158 HashConsed::new(self.sinto(s))
159 }
160}
161
162pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>(
165 s: &S,
166 impl_did: rustc_span::def_id::DefId,
167 clause: rustc_middle::ty::Clause<'tcx>,
168 span: rustc_span::Span,
169) -> Option<(Clause, ImplExpr, Span)> {
170 let tcx = s.base().tcx;
171 if !matches!(
172 tcx.def_kind(impl_did),
173 rustc_hir::def::DefKind::Impl { of_trait: true }
174 ) {
175 return None;
176 }
177 let impl_trait_ref =
178 rustc_middle::ty::Binder::dummy(tcx.impl_trait_ref(impl_did).instantiate_identity());
179 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
180 let impl_expr = solve_trait(
181 s,
182 new_clause
183 .as_predicate()
184 .as_trait_clause()?
185 .to_poly_trait_ref(),
186 );
187 let new_clause = new_clause.sinto(s);
188 Some((new_clause, impl_expr, span.sinto(s)))
189}
190
191#[tracing::instrument(level = "trace", skip(s))]
193pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
194 s: &S,
195 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
196) -> ImplExpr {
197 let warn = |_msg: &str| {};
198 if let Some(impl_expr) = s.with_cache(|cache| cache.impl_exprs.get(&trait_ref).cloned()) {
199 return impl_expr;
200 }
201 let resolved =
202 s.with_predicate_searcher(|pred_searcher| pred_searcher.resolve(&trait_ref, &warn));
203 let impl_expr: ImplExpr = match resolved {
204 Ok(x) => x.sinto(s),
205 Err(e) => crate::hax::fatal!(s, "{}", e),
206 };
207 s.with_cache(|cache| cache.impl_exprs.insert(trait_ref, impl_expr.clone()));
208 impl_expr
209}
210
211#[tracing::instrument(level = "trace", skip(s), ret)]
213pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
214 s: &S,
215 def_id: RDefId,
216 generics: ty::GenericArgsRef<'tcx>,
217) -> ItemRef {
218 ItemRef::translate(s, def_id, generics)
219}
220
221#[tracing::instrument(level = "trace", skip(s), ret)]
225pub fn solve_item_required_traits<'tcx, S: UnderOwnerState<'tcx>>(
226 s: &S,
227 def_id: RDefId,
228 generics: ty::GenericArgsRef<'tcx>,
229) -> Vec<ImplExpr> {
230 let predicates = ItemPredicates::required_recursively(
231 s.base().tcx,
232 def_id,
233 &s.base().options.bounds_options,
234 );
235 solve_item_traits_inner(s, generics, predicates)
236}
237
238#[tracing::instrument(level = "trace", skip(s), ret)]
241pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
242 s: &S,
243 def_id: RDefId,
244 generics: ty::GenericArgsRef<'tcx>,
245) -> Vec<ImplExpr> {
246 let predicates =
247 ItemPredicates::implied(s.base().tcx, def_id, &s.base().options.bounds_options);
248 solve_item_traits_inner(s, generics, predicates)
249}
250
251fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
254 s: &S,
255 generics: ty::GenericArgsRef<'tcx>,
256 predicates: ItemPredicates<'tcx>,
257) -> Vec<ImplExpr> {
258 let tcx = s.base().tcx;
259 let typing_env = s.typing_env();
260 predicates
261 .iter_trait_clauses()
262 .map(|(_, trait_ref)| ty::EarlyBinder::bind(trait_ref).instantiate(tcx, generics))
264 .map(|trait_ref| {
266 tcx.try_normalize_erasing_regions(typing_env, trait_ref)
267 .unwrap_or(trait_ref)
268 })
269 .map(|trait_ref| solve_trait(s, trait_ref))
271 .collect()
272}
273
274pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
276 s: &S,
277 def_id: RDefId,
278 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
279) -> Option<ImplExpr> {
280 let tcx = s.base().tcx;
281
282 let tr_def_id = tcx.trait_of_assoc(def_id)?;
283 let self_pred = self_predicate(tcx, tr_def_id);
285 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
287 let self_pred = ty::EarlyBinder::bind(self_pred).instantiate(tcx, generics);
288
289 Some(solve_trait(s, self_pred))
291}
292
293pub fn solve_sized<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> ImplExpr {
295 let tcx = s.base().tcx;
296 let sized_trait = tcx.lang_items().sized_trait().unwrap();
297 let ty = erase_free_regions(tcx, ty);
298 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, sized_trait, [ty]));
299 solve_trait(s, tref)
300}
301
302pub fn solve_destruct<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> ImplExpr {
304 let tcx = s.base().tcx;
305 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
306 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, destruct_trait, [ty]));
307 solve_trait(s, tref)
308}