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 AssocItemResolution, ElaborationCtx, ItemId, ItemPredicate, ItemPredicateId, ItemPredicates,
7 PredicateDirection, ToPolyTraitRef, erase_and_norm, erase_free_regions, normalize,
8 self_predicate,
9};
10
11use crate::hax::prelude::*;
12use charon_lib::ast::HashConsed;
13
14pub type PredicateSearcher<'tcx> = elaboration::PredicateSearcher<'tcx, DefId>;
15
16#[derive(AdtInto)]
17#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::ImpliedPredicate<'tcx, DefId>, state: S as s)]
18#[derive(Clone, Debug, Hash, PartialEq, Eq)]
19pub enum TraitProofImpliedPredicate {
20 AssocItem {
21 item: ItemRef,
29 index: usize,
31 },
32 Parent {
33 index: usize,
35 },
36}
37
38#[derive(AdtInto)]
41#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::TraitProofKind<'tcx, DefId>, state: S as s)]
42#[derive(Clone, Debug, Hash, PartialEq, Eq)]
43pub enum TraitProofKind {
44 Concrete(ItemRef),
46 LocalBound(GenericPredicateId),
48 SelfProof,
51 Dyn,
58 Builtin {
62 trait_data: BuiltinTraitData,
64 proofs: Vec<TraitProof>,
68 types: Vec<(DefId, Ty, Vec<TraitProof>)>,
70 },
71 Derived {
73 base: TraitProof,
74 path: TraitProofImpliedPredicate,
75 },
76 Error(String),
78}
79
80#[derive(AdtInto)]
81#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::BuiltinTraitData<'tcx>, state: S as s)]
82#[derive(Clone, Debug, Hash, PartialEq, Eq)]
83pub enum BuiltinTraitData {
84 Destruct(DestructData),
89 Auto,
91 Other,
93}
94
95#[derive(AdtInto)]
96#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::DestructData<'tcx>, state: S as s)]
97#[derive(Clone, Debug, Hash, PartialEq, Eq)]
98pub enum DestructData {
99 Noop,
101 Implicit,
106 Glue {
108 ty: Ty,
110 },
111}
112
113pub type TraitProof = HashConsed<TraitProofContents>;
118
119#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
120#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::TraitProofContents<'tcx, DefId>, state: S as s)]
121pub struct TraitProofContents {
122 pub pred: Binder<TraitRef>,
124 pub kind: TraitProofKind,
126}
127
128impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, TraitProof> for elaboration::TraitProof<'tcx, DefId> {
129 fn sinto(&self, s: &S) -> TraitProof {
130 HashConsed::new(self.contents().sinto(s))
131 }
132}
133
134pub fn super_clause_to_clause_and_trait_proof<'tcx, S: UnderOwnerState<'tcx>>(
137 s: &S,
138 impl_did: rustc_span::def_id::DefId,
139 clause: rustc_middle::ty::Clause<'tcx>,
140 span: rustc_span::Span,
141) -> Option<(Clause, TraitProof, Span)> {
142 let tcx = s.base().tcx;
143 if !matches!(
144 tcx.def_kind(impl_did),
145 rustc_hir::def::DefKind::Impl { of_trait: true }
146 ) {
147 return None;
148 }
149 let impl_trait_ref = rustc_middle::ty::Binder::dummy(
150 tcx.impl_trait_ref(impl_did)
151 .instantiate_identity()
152 .skip_normalization(),
153 );
154 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
155 let trait_proof = solve_trait(
156 s,
157 new_clause
158 .as_predicate()
159 .as_trait_clause()?
160 .to_poly_trait_ref(),
161 );
162 let new_clause = new_clause.sinto(s);
163 Some((new_clause, trait_proof, span.sinto(s)))
164}
165
166#[tracing::instrument(level = "trace", skip(s))]
168pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
169 s: &S,
170 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
171) -> TraitProof {
172 if let Some(trait_proof) = s.with_cache(|cache| cache.trait_proofs.get(&trait_ref).cloned()) {
173 return trait_proof;
174 }
175 let trait_proof = s.with_predicate_searcher(|pred_searcher, elab_ctx| {
176 pred_searcher.resolve(elab_ctx, &trait_ref)
177 });
178 let trait_proof: TraitProof = trait_proof.sinto(s);
179 s.with_cache(|cache| cache.trait_proofs.insert(trait_ref, trait_proof.clone()));
180 trait_proof
181}
182
183#[tracing::instrument(level = "trace", skip(s), ret)]
185pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
186 s: &S,
187 def_id: RDefId,
188 generics: ty::GenericArgsRef<'tcx>,
189) -> ItemRef {
190 ItemRef::translate(s, def_id, generics)
191}
192
193#[tracing::instrument(level = "trace", skip(s), ret)]
196pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
197 s: &S,
198 def_id: RDefId,
199 generics: ty::GenericArgsRef<'tcx>,
200) -> Vec<TraitProof> {
201 let predicates = ItemPredicates::implied(s.base().elab_ctx, &s.base_state(), def_id.sinto(s));
202 solve_item_traits_inner(s, generics, predicates)
203}
204
205fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
208 s: &S,
209 generics: ty::GenericArgsRef<'tcx>,
210 predicates: ItemPredicates<'tcx, DefId>,
211) -> Vec<TraitProof> {
212 let tcx = s.base().tcx;
213 let typing_env = s.typing_env();
214 predicates
215 .iter_trait_clauses()
216 .map(|(_, trait_ref)| ty::EarlyBinder::bind(trait_ref).instantiate(tcx, generics))
218 .map(|trait_ref| normalize(tcx, typing_env, trait_ref))
219 .map(|trait_ref| solve_trait(s, trait_ref))
221 .collect()
222}
223
224pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
226 s: &S,
227 def_id: RDefId,
228 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
229) -> Option<TraitProof> {
230 let tcx = s.base().tcx;
231
232 let tr_def_id = tcx.trait_of_assoc(def_id)?;
233 let self_pred = self_predicate(tcx, tr_def_id);
235 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
237 let self_pred = ty::EarlyBinder::bind(self_pred)
238 .instantiate(tcx, generics)
239 .skip_normalization();
240
241 Some(solve_trait(s, self_pred))
243}
244
245pub fn solve_sized<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof {
247 let tcx = s.base().tcx;
248 let sized_trait = tcx.lang_items().sized_trait().unwrap();
249 let ty = erase_free_regions(tcx, ty);
250 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, sized_trait, [ty]));
251 solve_trait(s, tref)
252}
253
254pub fn solve_destruct<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof {
256 let tcx = s.base().tcx;
257 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
258 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, destruct_trait, [ty]));
259 solve_trait(s, tref)
260}