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 rustc_data_structures::intern::Interned;
13use std::ops::Deref;
14
15pub type PredicateSearcher<'tcx> = elaboration::PredicateSearcher<'tcx, DefId>;
16
17#[derive(AdtInto)]
18#[args(< S: UnderOwnerState<'tcx> >, from: elaboration::ImpliedPredicate<'tcx, DefId>, state: S as s)]
19#[derive(Debug, Clone, PartialEq, Eq, Hash)]
20pub enum TraitProofImpliedPredicate<'tcx> {
21 AssocItem {
22 item: ItemRef<'tcx>,
30 index: usize,
32 bound_region_count: usize,
34 },
35 Parent {
36 index: usize,
38 bound_region_count: usize,
40 },
41}
42
43#[derive(AdtInto)]
46#[args(< S: UnderOwnerState<'tcx> >, from: elaboration::TraitProofKind<'tcx, DefId>, state: S as s)]
47#[derive(Debug, Clone, PartialEq, Eq, Hash)]
48pub enum TraitProofKind<'tcx> {
49 Concrete(ItemRef<'tcx>),
51 LocalBound(GenericPredicateId),
53 SelfProof,
56 Dyn(DynBinder<'tcx, TraitProof<'tcx>>),
65 Builtin {
69 trait_data: BuiltinTraitData<'tcx>,
71 proofs: Vec<TraitProof<'tcx>>,
75 types: Vec<(DefId, Ty<'tcx>, Vec<TraitProof<'tcx>>)>,
77 },
78 Derived {
80 base: TraitProof<'tcx>,
81 path: TraitProofImpliedPredicate<'tcx>,
82 },
83 Error(String),
85}
86
87impl<'tcx> TraitProofKind<'tcx> {
88 pub fn is_error(&self) -> bool {
90 matches!(self, TraitProofKind::Error(_))
91 }
92}
93
94#[derive(AdtInto)]
95#[args(< S: UnderOwnerState<'tcx> >, from: elaboration::BuiltinTraitData<'tcx>, state: S as s)]
96#[derive(Debug, Clone, PartialEq, Eq, Hash)]
97pub enum BuiltinTraitData<'tcx> {
98 Destruct(DestructData<'tcx>),
103 Alias,
105 Auto,
107 Other(SolverTraitLangItem),
109}
110
111sinto_reexport!(rustc_middle::ty::lang_items::SolverTraitLangItem);
112
113#[derive(AdtInto)]
114#[args(< S: UnderOwnerState<'tcx> >, from: elaboration::DestructData<'tcx>, state: S as s)]
115#[derive(Debug, Clone, PartialEq, Eq, Hash)]
116pub enum DestructData<'tcx> {
117 Noop,
119 Implicit,
124 Glue {
126 ty: Ty<'tcx>,
128 },
129}
130
131#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct TraitProof<'tcx> {
137 contents: Interned<'tcx, TraitProofContents<'tcx>>,
138}
139
140impl<'tcx> Deref for TraitProof<'tcx> {
141 type Target = TraitProofContents<'tcx>;
142
143 fn deref(&self) -> &Self::Target {
144 &self.contents
145 }
146}
147
148#[derive(Debug, Clone, PartialEq, Eq, Hash)]
149#[derive(AdtInto)]
150#[args(< S: UnderOwnerState<'tcx> >, from: elaboration::TraitProofContents<'tcx, DefId>, state: S as s)]
151pub struct TraitProofContents<'tcx> {
152 pub pred: Binder<TraitRef<'tcx>>,
154 pub kind: TraitProofKind<'tcx>,
156}
157
158impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, TraitProof<'tcx>>
159 for elaboration::TraitProof<'tcx, DefId>
160{
161 fn sinto(&self, s: &S) -> TraitProof<'tcx> {
162 TraitProof {
163 contents: s
164 .base()
165 .trait_proof_interner
166 .intern(self.contents().sinto(s)),
167 }
168 }
169}
170
171pub fn super_clause_to_clause_and_trait_proof<'tcx, S: UnderOwnerState<'tcx>>(
174 s: &S,
175 impl_did: rustc_span::def_id::DefId,
176 clause: rustc_middle::ty::Clause<'tcx>,
177 span: rustc_span::Span,
178) -> Option<(Clause<'tcx>, TraitProof<'tcx>, Span)> {
179 let tcx = s.base().tcx;
180 if !matches!(
181 tcx.def_kind(impl_did),
182 rustc_hir::def::DefKind::Impl { of_trait: true }
183 ) {
184 return None;
185 }
186 let impl_trait_ref = rustc_middle::ty::Binder::dummy(
187 tcx.impl_trait_ref(impl_did)
188 .instantiate_identity()
189 .skip_normalization(),
190 );
191 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
192 let trait_proof = solve_trait(
193 s,
194 new_clause
195 .as_predicate()
196 .as_trait_clause()?
197 .to_poly_trait_ref(),
198 );
199 let new_clause = new_clause.sinto(s);
200 Some((new_clause, trait_proof, span.sinto(s)))
201}
202
203#[tracing::instrument(level = "trace", skip(s))]
205pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
206 s: &S,
207 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
208) -> TraitProof<'tcx> {
209 if let Some(trait_proof) = s.with_cache(|cache| cache.trait_proofs.get(&trait_ref).cloned()) {
210 return trait_proof;
211 }
212 let trait_proof = s.with_predicate_searcher(|pred_searcher, elab_ctx| {
213 pred_searcher.resolve(elab_ctx, &trait_ref)
214 });
215 let trait_proof: TraitProof = trait_proof.sinto(s);
216 s.with_cache(|cache| cache.trait_proofs.insert(trait_ref, trait_proof.clone()));
217 trait_proof
218}
219
220#[tracing::instrument(level = "trace", skip(s), ret)]
222pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
223 s: &S,
224 def_id: RDefId,
225 generics: ty::GenericArgsRef<'tcx>,
226) -> ItemRef<'tcx> {
227 ItemRef::translate(s, def_id, generics)
228}
229
230#[tracing::instrument(level = "trace", skip(s), ret)]
233pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
234 s: &S,
235 def_id: RDefId,
236 generics: ty::GenericArgsRef<'tcx>,
237) -> Vec<TraitProof<'tcx>> {
238 let predicates = ItemPredicates::implied(s.base().elab_ctx, &s.base_state(), def_id.sinto(s));
239 solve_item_traits_inner(s, generics, predicates)
240}
241
242fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
245 s: &S,
246 generics: ty::GenericArgsRef<'tcx>,
247 predicates: ItemPredicates<'tcx, DefId>,
248) -> Vec<TraitProof<'tcx>> {
249 let tcx = s.base().tcx;
250 let typing_env = s.typing_env();
251 predicates
252 .iter_trait_clauses()
253 .map(|(_, trait_ref)| ty::EarlyBinder::bind(tcx, trait_ref).instantiate(tcx, generics))
255 .map(|trait_ref| normalize(tcx, typing_env, trait_ref))
256 .map(|trait_ref| solve_trait(s, trait_ref))
258 .collect()
259}
260
261pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
263 s: &S,
264 def_id: RDefId,
265 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
266) -> Option<TraitProof<'tcx>> {
267 let tcx = s.base().tcx;
268
269 let tr_def_id = tcx.trait_of_assoc(def_id)?;
270 let self_pred = self_predicate(tcx, tr_def_id);
272 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
274 let self_pred = ty::EarlyBinder::bind(tcx, self_pred)
275 .instantiate(tcx, generics)
276 .skip_normalization();
277
278 Some(solve_trait(s, self_pred))
280}
281
282pub fn solve_sized<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof<'tcx> {
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_copy<'tcx, S: UnderOwnerState<'tcx>>(
293 s: &S,
294 ty: ty::Ty<'tcx>,
295) -> Option<TraitProof<'tcx>> {
296 let tcx = s.base().tcx;
297 let copy_trait = tcx.lang_items().copy_trait().unwrap();
298 let ty = erase_free_regions(tcx, ty);
299 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, copy_trait, [ty]));
300 let proof = solve_trait(s, tref);
301 (!proof.kind.is_error()).then_some(proof)
302}
303
304pub fn solve_destruct<'tcx, S: UnderOwnerState<'tcx>>(s: &S, ty: ty::Ty<'tcx>) -> TraitProof<'tcx> {
306 let tcx = s.base().tcx;
307 let destruct_trait = tcx.lang_items().destruct_trait().unwrap();
308 let tref = ty::Binder::dummy(ty::TraitRef::new(tcx, destruct_trait, [ty]));
309 solve_trait(s, tref)
310}