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(DynBinder<TraitProof>),
60 Builtin {
64 trait_data: BuiltinTraitData,
66 proofs: Vec<TraitProof>,
70 types: Vec<(DefId, Ty, Vec<TraitProof>)>,
72 },
73 Derived {
75 base: TraitProof,
76 path: TraitProofImpliedPredicate,
77 },
78 Error(String),
80}
81
82impl TraitProofKind {
83 pub fn is_error(&self) -> bool {
85 matches!(self, TraitProofKind::Error(_))
86 }
87}
88
89#[derive(AdtInto)]
90#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::BuiltinTraitData<'tcx>, state: S as s)]
91#[derive(Clone, Debug, Hash, PartialEq, Eq)]
92pub enum BuiltinTraitData {
93 Destruct(DestructData),
98 Alias,
100 Auto,
102 Other(SolverTraitLangItem),
104}
105
106sinto_reexport!(rustc_type_ir::lang_items::SolverTraitLangItem);
107
108#[derive(AdtInto)]
109#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::DestructData<'tcx>, state: S as s)]
110#[derive(Clone, Debug, Hash, PartialEq, Eq)]
111pub enum DestructData {
112 Noop,
114 Implicit,
119 Glue {
121 ty: Ty,
123 },
124}
125
126pub type TraitProof = HashConsed<TraitProofContents>;
131
132#[derive(Clone, Debug, Hash, PartialEq, Eq, AdtInto)]
133#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: elaboration::TraitProofContents<'tcx, DefId>, state: S as s)]
134pub struct TraitProofContents {
135 pub pred: Binder<TraitRef>,
137 pub kind: TraitProofKind,
139}
140
141impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, TraitProof> for elaboration::TraitProof<'tcx, DefId> {
142 fn sinto(&self, s: &S) -> TraitProof {
143 HashConsed::new(self.contents().sinto(s))
144 }
145}
146
147pub fn super_clause_to_clause_and_trait_proof<'tcx, S: UnderOwnerState<'tcx>>(
150 s: &S,
151 impl_did: rustc_span::def_id::DefId,
152 clause: rustc_middle::ty::Clause<'tcx>,
153 span: rustc_span::Span,
154) -> Option<(Clause, TraitProof, Span)> {
155 let tcx = s.base().tcx;
156 if !matches!(
157 tcx.def_kind(impl_did),
158 rustc_hir::def::DefKind::Impl { of_trait: true }
159 ) {
160 return None;
161 }
162 let impl_trait_ref = rustc_middle::ty::Binder::dummy(
163 tcx.impl_trait_ref(impl_did)
164 .instantiate_identity()
165 .skip_normalization(),
166 );
167 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
168 let trait_proof = solve_trait(
169 s,
170 new_clause
171 .as_predicate()
172 .as_trait_clause()?
173 .to_poly_trait_ref(),
174 );
175 let new_clause = new_clause.sinto(s);
176 Some((new_clause, trait_proof, span.sinto(s)))
177}
178
179#[tracing::instrument(level = "trace", skip(s))]
181pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
182 s: &S,
183 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
184) -> TraitProof {
185 if let Some(trait_proof) = s.with_cache(|cache| cache.trait_proofs.get(&trait_ref).cloned()) {
186 return trait_proof;
187 }
188 let trait_proof = s.with_predicate_searcher(|pred_searcher, elab_ctx| {
189 pred_searcher.resolve(elab_ctx, &trait_ref)
190 });
191 let trait_proof: TraitProof = trait_proof.sinto(s);
192 s.with_cache(|cache| cache.trait_proofs.insert(trait_ref, trait_proof.clone()));
193 trait_proof
194}
195
196#[tracing::instrument(level = "trace", skip(s), ret)]
198pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
199 s: &S,
200 def_id: RDefId,
201 generics: ty::GenericArgsRef<'tcx>,
202) -> ItemRef {
203 ItemRef::translate(s, def_id, generics)
204}
205
206#[tracing::instrument(level = "trace", skip(s), ret)]
209pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
210 s: &S,
211 def_id: RDefId,
212 generics: ty::GenericArgsRef<'tcx>,
213) -> Vec<TraitProof> {
214 let predicates = ItemPredicates::implied(s.base().elab_ctx, &s.base_state(), def_id.sinto(s));
215 solve_item_traits_inner(s, generics, predicates)
216}
217
218fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
221 s: &S,
222 generics: ty::GenericArgsRef<'tcx>,
223 predicates: ItemPredicates<'tcx, DefId>,
224) -> Vec<TraitProof> {
225 let tcx = s.base().tcx;
226 let typing_env = s.typing_env();
227 predicates
228 .iter_trait_clauses()
229 .map(|(_, trait_ref)| ty::EarlyBinder::bind(tcx, trait_ref).instantiate(tcx, generics))
231 .map(|trait_ref| normalize(tcx, typing_env, trait_ref))
232 .map(|trait_ref| solve_trait(s, trait_ref))
234 .collect()
235}
236
237pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
239 s: &S,
240 def_id: RDefId,
241 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
242) -> Option<TraitProof> {
243 let tcx = s.base().tcx;
244
245 let tr_def_id = tcx.trait_of_assoc(def_id)?;
246 let self_pred = self_predicate(tcx, tr_def_id);
248 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
250 let self_pred = ty::EarlyBinder::bind(tcx, self_pred)
251 .instantiate(tcx, generics)
252 .skip_normalization();
253
254 Some(solve_trait(s, self_pred))
256}
257
258pub fn solve_sized<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof {
260 let tcx = s.base().tcx;
261 let sized_trait = tcx.lang_items().sized_trait().unwrap();
262 let ty = erase_free_regions(tcx, ty);
263 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, sized_trait, [ty]));
264 solve_trait(s, tref)
265}
266
267pub fn solve_copy<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> Option<TraitProof> {
269 let tcx = s.base().tcx;
270 let copy_trait = tcx.lang_items().copy_trait().unwrap();
271 let ty = erase_free_regions(tcx, ty);
272 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, copy_trait, [ty]));
273 let proof = solve_trait(s, tref);
274 (!proof.kind.is_error()).then_some(proof)
275}
276
277pub fn solve_destruct<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof {
279 let tcx = s.base().tcx;
280 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
281 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, destruct_trait, [ty]));
282 solve_trait(s, tref)
283}