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 predicate: Binder<TraitRef>,
26 index: usize,
28 },
29 Parent {
30 predicate: Binder<TraitRef>,
32 index: usize,
34 },
35}
36
37impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, ImplExprPathChunk> for elaboration::PathChunk<'tcx> {
38 fn sinto(&self, s: &S) -> ImplExprPathChunk {
39 match self {
40 elaboration::PathChunk::AssocItem {
41 item,
42 predicate,
43 index,
44 ..
45 } => ImplExprPathChunk::AssocItem {
46 item: item.sinto(s),
47 predicate: predicate.sinto(s),
48 index: index.sinto(s),
49 },
50 elaboration::PathChunk::Parent {
51 predicate, index, ..
52 } => ImplExprPathChunk::Parent {
53 predicate: predicate.sinto(s),
54 index: index.sinto(s),
55 },
56 }
57 }
58}
59
60#[derive(AdtInto)]
63#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::ImplExprAtom<'tcx>, state: S as s)]
64#[derive(Clone, Debug, Hash, PartialEq, Eq)]
65pub enum ImplExprAtom {
66 Concrete(ItemRef),
68 LocalBound {
70 id: GenericPredicateId,
71 r#trait: Binder<TraitRef>,
72 path: Vec<ImplExprPathChunk>,
73 },
74 SelfImpl {
77 r#trait: Binder<TraitRef>,
78 path: Vec<ImplExprPathChunk>,
79 },
80 Dyn,
87 Builtin {
91 trait_data: BuiltinTraitData,
93 impl_exprs: Vec<ImplExpr>,
97 types: Vec<(DefId, Ty, Vec<ImplExpr>)>,
99 },
100 Error(String),
102}
103
104#[derive(AdtInto)]
105#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::BuiltinTraitData<'tcx>, state: S as s)]
106#[derive(Clone, Debug, Hash, PartialEq, Eq)]
107pub enum BuiltinTraitData {
108 Destruct(DestructData),
113 Other,
115}
116
117#[derive(AdtInto)]
118#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::DestructData<'tcx>, state: S as s)]
119#[derive(Clone, Debug, Hash, PartialEq, Eq)]
120pub enum DestructData {
121 Noop,
123 Implicit,
128 Glue {
130 ty: Ty,
132 },
133}
134
135pub type ImplExpr = HashConsed<ImplExprContents>;
140
141#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
142#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::ImplExpr<'tcx>, state: S as s)]
143pub struct ImplExprContents {
144 pub r#trait: Binder<TraitRef>,
146 pub r#impl: ImplExprAtom,
148}
149
150impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, ImplExpr> for elaboration::ImplExpr<'tcx> {
151 fn sinto(&self, s: &S) -> ImplExpr {
152 HashConsed::new(self.sinto(s))
153 }
154}
155
156pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>(
159 s: &S,
160 impl_did: rustc_span::def_id::DefId,
161 clause: rustc_middle::ty::Clause<'tcx>,
162 span: rustc_span::Span,
163) -> Option<(Clause, ImplExpr, Span)> {
164 let tcx = s.base().tcx;
165 if !matches!(
166 tcx.def_kind(impl_did),
167 rustc_hir::def::DefKind::Impl { of_trait: true }
168 ) {
169 return None;
170 }
171 let impl_trait_ref =
172 rustc_middle::ty::Binder::dummy(tcx.impl_trait_ref(impl_did).instantiate_identity());
173 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
174 let impl_expr = solve_trait(
175 s,
176 new_clause
177 .as_predicate()
178 .as_trait_clause()?
179 .to_poly_trait_ref(),
180 );
181 let new_clause = new_clause.sinto(s);
182 Some((new_clause, impl_expr, span.sinto(s)))
183}
184
185#[tracing::instrument(level = "trace", skip(s))]
187pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
188 s: &S,
189 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
190) -> ImplExpr {
191 if let Some(impl_expr) = s.with_cache(|cache| cache.impl_exprs.get(&trait_ref).cloned()) {
192 return impl_expr;
193 }
194 let impl_expr = s.with_predicate_searcher(|pred_searcher| pred_searcher.resolve(&trait_ref));
195 let impl_expr: ImplExpr = impl_expr.sinto(s);
196 s.with_cache(|cache| cache.impl_exprs.insert(trait_ref, impl_expr.clone()));
197 impl_expr
198}
199
200#[tracing::instrument(level = "trace", skip(s), ret)]
202pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
203 s: &S,
204 def_id: RDefId,
205 generics: ty::GenericArgsRef<'tcx>,
206) -> ItemRef {
207 ItemRef::translate(s, def_id, generics)
208}
209
210#[tracing::instrument(level = "trace", skip(s), ret)]
214pub fn solve_item_required_traits<'tcx, S: UnderOwnerState<'tcx>>(
215 s: &S,
216 def_id: RDefId,
217 generics: ty::GenericArgsRef<'tcx>,
218) -> Vec<ImplExpr> {
219 let predicates = ItemPredicates::required_recursively(
220 s.base().tcx,
221 def_id,
222 &s.base().options.bounds_options,
223 );
224 solve_item_traits_inner(s, generics, predicates)
225}
226
227#[tracing::instrument(level = "trace", skip(s), ret)]
230pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
231 s: &S,
232 def_id: RDefId,
233 generics: ty::GenericArgsRef<'tcx>,
234) -> Vec<ImplExpr> {
235 let predicates =
236 ItemPredicates::implied(s.base().tcx, def_id, &s.base().options.bounds_options);
237 solve_item_traits_inner(s, generics, predicates)
238}
239
240fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
243 s: &S,
244 generics: ty::GenericArgsRef<'tcx>,
245 predicates: ItemPredicates<'tcx>,
246) -> Vec<ImplExpr> {
247 let tcx = s.base().tcx;
248 let typing_env = s.typing_env();
249 predicates
250 .iter_trait_clauses()
251 .map(|(_, trait_ref)| ty::EarlyBinder::bind(trait_ref).instantiate(tcx, generics))
253 .map(|trait_ref| {
255 tcx.try_normalize_erasing_regions(typing_env, trait_ref)
256 .unwrap_or(trait_ref)
257 })
258 .map(|trait_ref| solve_trait(s, trait_ref))
260 .collect()
261}
262
263pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
265 s: &S,
266 def_id: RDefId,
267 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
268) -> Option<ImplExpr> {
269 let tcx = s.base().tcx;
270
271 let tr_def_id = tcx.trait_of_assoc(def_id)?;
272 let self_pred = self_predicate(tcx, tr_def_id);
274 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
276 let self_pred = ty::EarlyBinder::bind(self_pred).instantiate(tcx, generics);
277
278 Some(solve_trait(s, self_pred))
280}
281
282pub fn solve_sized<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> ImplExpr {
284 let tcx = s.base().tcx;
285 let sized_trait = tcx.lang_items().sized_trait().unwrap();
286 let ty = erase_free_regions(tcx, ty);
287 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, sized_trait, [ty]));
288 solve_trait(s, tref)
289}
290
291pub fn solve_destruct<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> ImplExpr {
293 let tcx = s.base().tcx;
294 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
295 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, destruct_trait, [ty]));
296 solve_trait(s, tref)
297}