1use crate::prelude::*;
2
3#[cfg(feature = "rustc")]
4mod resolution;
5#[cfg(feature = "rustc")]
6mod utils;
7#[cfg(feature = "rustc")]
8pub use utils::{
9 erase_and_norm, implied_predicates, predicates_defined_on, required_predicates, self_predicate,
10 ToPolyTraitRef,
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#[derive(AdtInto)]
21#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::PathChunk<'tcx>, state: S as s)]
22#[derive_group(Serializers)]
23#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
24pub enum ImplExprPathChunk {
25 AssocItem {
26 item: AssocItem,
27 generic_args: Vec<GenericArg>,
29 impl_exprs: Vec<ImplExpr>,
37 predicate: Binder<TraitPredicate>,
39 #[value(<_ as SInto<_, Clause>>::sinto(predicate, s).id)]
40 predicate_id: PredicateId,
41 index: usize,
43 },
44 Parent {
45 predicate: Binder<TraitPredicate>,
47 #[value(<_ as SInto<_, Clause>>::sinto(predicate, s).id)]
48 predicate_id: PredicateId,
49 index: usize,
51 },
52}
53
54#[derive(AdtInto)]
57#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::ImplExprAtom<'tcx>, state: S as s)]
58#[derive_group(Serializers)]
59#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema)]
60pub enum ImplExprAtom {
61 Concrete {
63 #[from(def_id)]
64 id: GlobalIdent,
65 generics: Vec<GenericArg>,
66 impl_exprs: Vec<ImplExpr>,
68 },
69 LocalBound {
71 #[not_in_source]
72 #[value({
73 let Self::LocalBound { predicate, .. } = self else { unreachable!() };
74 predicate.sinto(s).id
75 })]
76 predicate_id: PredicateId,
77 index: usize,
80 r#trait: Binder<TraitRef>,
81 path: Vec<ImplExprPathChunk>,
82 },
83 SelfImpl {
86 r#trait: Binder<TraitRef>,
87 path: Vec<ImplExprPathChunk>,
88 },
89 Dyn,
96 Builtin {
100 r#trait: Binder<TraitRef>,
101 impl_exprs: Vec<ImplExpr>,
105 types: Vec<(DefId, Ty)>,
107 },
108 Error(String),
110}
111
112#[derive_group(Serializers)]
117#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, JsonSchema, AdtInto)]
118#[args(<'tcx, S: UnderOwnerState<'tcx> >, from: resolution::ImplExpr<'tcx>, state: S as s)]
119pub struct ImplExpr {
120 pub r#trait: Binder<TraitRef>,
122 pub r#impl: ImplExprAtom,
124}
125
126#[cfg(feature = "rustc")]
129pub fn super_clause_to_clause_and_impl_expr<'tcx, S: UnderOwnerState<'tcx>>(
130 s: &S,
131 impl_did: rustc_span::def_id::DefId,
132 clause: rustc_middle::ty::Clause<'tcx>,
133 span: rustc_span::Span,
134) -> Option<(Clause, ImplExpr, Span)> {
135 let tcx = s.base().tcx;
136 let impl_trait_ref = tcx
137 .impl_trait_ref(impl_did)
138 .map(|binder| rustc_middle::ty::Binder::dummy(binder.instantiate_identity()))?;
139 let original_predicate_id = {
140 let s = &with_owner_id(s.base(), (), (), impl_trait_ref.def_id());
143 clause.sinto(s).id
144 };
145 let new_clause = clause.instantiate_supertrait(tcx, impl_trait_ref);
146 let impl_expr = solve_trait(
147 s,
148 new_clause
149 .as_predicate()
150 .as_trait_clause()?
151 .to_poly_trait_ref(),
152 );
153 let mut new_clause_no_binder = new_clause.sinto(s);
154 new_clause_no_binder.id = original_predicate_id;
155 Some((new_clause_no_binder, impl_expr, span.sinto(s)))
156}
157
158#[cfg(feature = "rustc")]
160#[tracing::instrument(level = "trace", skip(s))]
161pub fn solve_trait<'tcx, S: BaseState<'tcx> + HasOwnerId>(
162 s: &S,
163 trait_ref: rustc_middle::ty::PolyTraitRef<'tcx>,
164) -> ImplExpr {
165 let warn = |msg: &str| {
166 if !s.base().ty_alias_mode {
167 crate::warning!(s, "{}", msg)
168 }
169 };
170 if let Some(impl_expr) = s.with_cache(|cache| cache.impl_exprs.get(&trait_ref).cloned()) {
171 return impl_expr;
172 }
173 let resolved = s.with_cache(|cache| {
174 cache
175 .predicate_searcher
176 .get_or_insert_with(|| PredicateSearcher::new_for_owner(s.base().tcx, s.owner_id()))
177 .resolve(&trait_ref, &warn)
178 });
179 let impl_expr = match resolved {
180 Ok(x) => x.sinto(s),
181 Err(e) => crate::fatal!(s, "{}", e),
182 };
183 s.with_cache(|cache| cache.impl_exprs.insert(trait_ref, impl_expr.clone()));
184 impl_expr
185}
186
187#[cfg(feature = "rustc")]
191#[tracing::instrument(level = "trace", skip(s), ret)]
192pub fn solve_item_required_traits<'tcx, S: UnderOwnerState<'tcx>>(
193 s: &S,
194 def_id: RDefId,
195 generics: ty::GenericArgsRef<'tcx>,
196) -> Vec<ImplExpr> {
197 fn accumulate<'tcx, S: UnderOwnerState<'tcx>>(
198 s: &S,
199 def_id: RDefId,
200 generics: ty::GenericArgsRef<'tcx>,
201 impl_exprs: &mut Vec<ImplExpr>,
202 ) {
203 let tcx = s.base().tcx;
204 use rustc_hir::def::DefKind::*;
205 match tcx.def_kind(def_id) {
206 AssocTy | AssocFn | AssocConst | Closure | Ctor(..) | Variant => {
207 let parent = tcx.parent(def_id);
208 accumulate(s, parent, generics, impl_exprs);
209 }
210 _ => {}
211 }
212 let predicates = required_predicates(tcx, def_id);
213 impl_exprs.extend(solve_item_traits_inner(s, generics, predicates));
214 }
215 let mut impl_exprs = vec![];
216 accumulate(s, def_id, generics, &mut impl_exprs);
217 impl_exprs
218}
219
220#[cfg(feature = "rustc")]
223#[tracing::instrument(level = "trace", skip(s), ret)]
224pub fn solve_item_implied_traits<'tcx, S: UnderOwnerState<'tcx>>(
225 s: &S,
226 def_id: RDefId,
227 generics: ty::GenericArgsRef<'tcx>,
228) -> Vec<ImplExpr> {
229 let predicates = implied_predicates(s.base().tcx, def_id);
230 solve_item_traits_inner(s, generics, predicates)
231}
232
233#[cfg(feature = "rustc")]
236fn solve_item_traits_inner<'tcx, S: UnderOwnerState<'tcx>>(
237 s: &S,
238 generics: ty::GenericArgsRef<'tcx>,
239 predicates: ty::GenericPredicates<'tcx>,
240) -> Vec<ImplExpr> {
241 let tcx = s.base().tcx;
242 let typing_env = s.typing_env();
243 predicates
244 .predicates
245 .iter()
246 .map(|(clause, _span)| *clause)
247 .filter_map(|clause| clause.as_trait_clause())
248 .map(|clause| clause.to_poly_trait_ref())
249 .map(|trait_ref| ty::EarlyBinder::bind(trait_ref).instantiate(tcx, generics))
251 .map(|trait_ref| {
253 tcx.try_normalize_erasing_regions(typing_env, trait_ref)
254 .unwrap_or(trait_ref)
255 })
256 .map(|trait_ref| solve_trait(s, trait_ref))
258 .collect()
259}
260
261#[cfg(feature = "rustc")]
263pub fn self_clause_for_item<'tcx, S: UnderOwnerState<'tcx>>(
264 s: &S,
265 def_id: RDefId,
266 generics: rustc_middle::ty::GenericArgsRef<'tcx>,
267) -> Option<ImplExpr> {
268 use rustc_middle::ty::EarlyBinder;
269 let tcx = s.base().tcx;
270
271 let tr_def_id = tcx.trait_of_item(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 = EarlyBinder::bind(self_pred).instantiate(tcx, generics);
277
278 Some(solve_trait(s, self_pred))
280}