1use crate::prelude::*;
2
3#[cfg(feature = "rustc")]
4pub mod resolution;
5#[cfg(feature = "rustc")]
6mod utils;
7#[cfg(feature = "rustc")]
8pub use utils::{
9 Predicates, ToPolyTraitRef, erase_and_norm, erase_free_regions, implied_predicates, normalize,
10 predicates_defined_on, required_predicates, self_predicate,
11};
12
13#[cfg(feature = "rustc")]
14pub use resolution::PredicateSearcher;
15#[cfg(feature = "rustc")]
16use rustc_middle::ty;
17#[cfg(feature = "rustc")]
18use rustc_span::def_id::DefId as RDefId;
19
20#[cfg(feature = "rustc")]
21pub use utils::is_sized_related_trait;
22
23#[derive_group(Serializers)]
24#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
25pub enum ImplExprPathChunk {
26 AssocItem {
27 item: ItemRef,
35 assoc_item: AssocItem,
36 predicate: Binder<TraitPredicate>,
38 predicate_id: PredicateId,
39 index: usize,
41 },
42 Parent {
43 predicate: Binder<TraitPredicate>,
45 predicate_id: PredicateId,
46 index: usize,
48 },
49}
50
51#[cfg(feature = "rustc")]
52impl<'tcx, S: UnderOwnerState<'tcx>> SInto<S, ImplExprPathChunk> for resolution::PathChunk<'tcx> {
53 fn sinto(&self, s: &S) -> ImplExprPathChunk {
54 match self {
55 resolution::PathChunk::AssocItem {
56 item,
57 generic_args,
58 predicate,
59 index,
60 ..
61 } => ImplExprPathChunk::AssocItem {
62 item: translate_item_ref(s, item.def_id, generic_args),
63 assoc_item: AssocItem::sfrom(s, item),
64 predicate: predicate.sinto(s),
65 predicate_id: <_ as SInto<_, Clause>>::sinto(predicate, s).id,
66 index: index.sinto(s),
67 },
68 resolution::PathChunk::Parent {
69 predicate, index, ..
70 } => ImplExprPathChunk::Parent {
71 predicate: predicate.sinto(s),
72 predicate_id: <_ as SInto<_, Clause>>::sinto(predicate, s).id,
73 index: index.sinto(s),
74 },
75 }
76 }
77}
78
79#[derive(AdtInto)]
82#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::ImplExprAtom<'tcx>, state: S as s)]
83#[derive_group(Serializers)]
84#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
85pub enum ImplExprAtom {
86 #[custom_arm(FROM_TYPE::Concrete { def_id, generics } => TO_TYPE::Concrete(
88 translate_item_ref(s, *def_id, generics),
89 ),)]
90 Concrete(ItemRef),
91 LocalBound {
93 #[not_in_source]
94 #[value({
95 let Self::LocalBound { predicate, .. } = self else { unreachable!() };
96 predicate.sinto(s).id
97 })]
98 predicate_id: PredicateId,
99 index: usize,
102 r#trait: Binder<TraitRef>,
103 path: Vec<ImplExprPathChunk>,
104 },
105 SelfImpl {
108 r#trait: Binder<TraitRef>,
109 path: Vec<ImplExprPathChunk>,
110 },
111 Dyn,
118 Builtin {
122 trait_data: BuiltinTraitData,
124 impl_exprs: Vec<ImplExpr>,
128 types: Vec<(DefId, Ty, Vec<ImplExpr>)>,
130 },
131 Error(String),
133}
134
135#[derive(AdtInto)]
136#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::BuiltinTraitData<'tcx>, state: S as s)]
137#[derive_group(Serializers)]
138#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
139pub enum BuiltinTraitData {
140 Drop(DropData),
145 Other,
147}
148
149#[derive(AdtInto)]
150#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::DropData<'tcx>, state: S as s)]
151#[derive_group(Serializers)]
152#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
153pub enum DropData {
154 Noop,
156 Implicit,
161 Glue {
165 ty: Ty,
167 impl_exprs: Vec<ImplExpr>,
170 },
171}
172
173#[derive_group(Serializers)]
178#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema, AdtInto)]
179#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::ImplExpr<'tcx>, state: S as s)]
180pub struct ImplExpr {
181 pub r#trait: Binder<TraitRef>,
183 pub r#impl: ImplExprAtom,
185}
186
187#[cfg(feature = "rustc")]
190pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>(
191 s: &S,
192 impl_did: rustc_span::def_id::DefId,
193 clause: rustc_middle::ty::Clause<'tcx>,
194 span: rustc_span::Span,
195) -> Option<(Clause, ImplExpr, Span)> {
196 let tcx = s.base().tcx;
197 let impl_trait_ref = tcx
198 .impl_trait_ref(impl_did)
199 .map(|binder| rustc_middle::ty::Binder::dummy(binder.instantiate_identity()))?;
200 let original_predicate_id = {
201 let s = &s.with_owner_id(impl_trait_ref.def_id());
204 clause.sinto(s).id
205 };
206 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
207 let impl_expr = solve_trait(
208 s,
209 new_clause
210 .as_predicate()
211 .as_trait_clause()?
212 .to_poly_trait_ref(),
213 );
214 let mut new_clause_no_binder = new_clause.sinto(s);
215 new_clause_no_binder.id = original_predicate_id;
216 Some((new_clause_no_binder, impl_expr, span.sinto(s)))
217}
218
219#[cfg(feature = "rustc")]
221#[tracing::instrument(level = "trace", skip(s))]
222pub fn solve_trait<'tcx, S: UnderOwnerState<'tcx>>(
223 s: &S,
224 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
225) -> ImplExpr {
226 let warn = |msg: &str| {
227 if !s.base().ty_alias_mode {
228 crate::warning!(s, "{}", msg)
229 }
230 };
231 if let Some(impl_expr) = s.with_cache(|cache| cache.impl_exprs.get(&trait_ref).cloned()) {
232 return impl_expr;
233 }
234 let resolved =
235 s.with_predicate_searcher(|pred_searcher| pred_searcher.resolve(&trait_ref, &warn));
236 let impl_expr = match resolved {
237 Ok(x) => x.sinto(s),
238 Err(e) => crate::fatal!(s, "{}", e),
239 };
240 s.with_cache(|cache| cache.impl_exprs.insert(trait_ref, impl_expr.clone()));
241 impl_expr
242}
243
244#[cfg(feature = "rustc")]
246#[tracing::instrument(level = "trace", skip(s), ret)]
247pub fn translate_item_ref<'tcx, S: UnderOwnerState<'tcx>>(
248 s: &S,
249 def_id: RDefId,
250 generics: ty::GenericArgsRef<'tcx>,
251) -> ItemRef {
252 ItemRef::translate(s, def_id, generics)
253}
254
255#[cfg(feature = "rustc")]
259#[tracing::instrument(level = "trace", skip(s), ret)]
260pub fn solve_item_required_traits<'tcx, S: UnderOwnerState<'tcx>>(
261 s: &S,
262 def_id: RDefId,
263 generics: ty::GenericArgsRef<'tcx>,
264) -> Vec<ImplExpr> {
265 fn accumulate<'tcx, S: UnderOwnerState<'tcx>>(
266 s: &S,
267 def_id: RDefId,
268 generics: ty::GenericArgsRef<'tcx>,
269 impl_exprs: &mut Vec<ImplExpr>,
270 ) {
271 let tcx = s.base().tcx;
272 use rustc_hir::def::DefKind::*;
273 match tcx.def_kind(def_id) {
274 AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant => {
275 let parent = tcx.parent(def_id);
276 accumulate(s, parent, generics, impl_exprs);
277 }
278 _ => {}
279 }
280 let predicates = required_predicates(tcx, def_id, s.base().options.bounds_options);
281 impl_exprs.extend(solve_item_traits_inner(s, generics, predicates));
282 }
283 let mut impl_exprs = vec![];
284 accumulate(s, def_id, generics, &mut impl_exprs);
285 impl_exprs
286}
287
288#[cfg(feature = "rustc")]
291#[tracing::instrument(level = "trace", skip(s), ret)]
292pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
293 s: &S,
294 def_id: RDefId,
295 generics: ty::GenericArgsRef<'tcx>,
296) -> Vec<ImplExpr> {
297 let predicates = implied_predicates(s.base().tcx, def_id, s.base().options.bounds_options);
298 solve_item_traits_inner(s, generics, predicates)
299}
300
301#[cfg(feature = "rustc")]
304fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
305 s: &S,
306 generics: ty::GenericArgsRef<'tcx>,
307 predicates: utils::Predicates<'tcx>,
308) -> Vec<ImplExpr> {
309 let tcx = s.base().tcx;
310 let typing_env = s.typing_env();
311 predicates
312 .iter()
313 .map(|(clause, _span)| *clause)
314 .filter_map(|clause| clause.as_trait_clause())
315 .map(|clause| clause.to_poly_trait_ref())
316 .map(|trait_ref| ty::EarlyBinder::bind(trait_ref).instantiate(tcx, generics))
318 .map(|trait_ref| {
320 tcx.try_normalize_erasing_regions(typing_env, trait_ref)
321 .unwrap_or(trait_ref)
322 })
323 .map(|trait_ref| solve_trait(s, trait_ref))
325 .collect()
326}
327
328#[cfg(feature = "rustc")]
330pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
331 s: &S,
332 def_id: RDefId,
333 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
334) -> Option<ImplExpr> {
335 let tcx = s.base().tcx;
336
337 let tr_def_id = tcx.trait_of_item(def_id)?;
338 let self_pred = self_predicate(tcx, tr_def_id);
340 let generics = generics.truncate_to(tcx, tcx.generics_of(tr_def_id));
342 let self_pred = ty::EarlyBinder::bind(self_pred).instantiate(tcx, generics);
343
344 Some(solve_trait(s, self_pred))
346}