1use std::marker::PhantomData;
2
3use smallvec::smallvec;
4
5use crate::data_structures::HashSet;
6use crate::inherent::*;
7use crate::lang_items::SolverTraitLangItem;
8use crate::outlives::{Component, push_outlives_components};
9use crate::{self as ty, Interner, Unnormalized, Upcast as _};
10
11pub struct Elaborator<I: Interner, O> {
18 cx: I,
19 stack: Vec<O>,
20 visited: HashSet<ty::Binder<I, ty::PredicateKind<I>>>,
21 mode: Filter,
22 elaborate_sized: ElaborateSized,
23}
24
25enum Filter {
26 All,
27 OnlySelf,
28}
29
30#[derive(#[automatically_derived]
impl ::core::cmp::Eq for ElaborateSized {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for ElaborateSized {
#[inline]
fn eq(&self, other: &ElaborateSized) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq)]
31enum ElaborateSized {
32 Yes,
33 No,
34}
35
36pub trait Elaboratable<I: Interner> {
38 fn predicate(&self) -> I::Predicate;
39
40 fn child(&self, clause: I::Clause) -> Self;
42
43 fn child_with_derived_cause(
46 &self,
47 clause: I::Clause,
48 span: I::Span,
49 parent_trait_pred: ty::Binder<I, ty::TraitPredicate<I>>,
50 index: usize,
51 ) -> Self;
52}
53
54pub struct ClauseWithSupertraitSpan<I: Interner> {
55 pub clause: I::Clause,
56 pub supertrait_span: I::Span,
58}
59
60impl<I: Interner> ClauseWithSupertraitSpan<I> {
61 pub fn new(clause: I::Clause, span: I::Span) -> Self {
62 ClauseWithSupertraitSpan { clause, supertrait_span: span }
63 }
64}
65
66impl<I: Interner> Elaboratable<I> for ClauseWithSupertraitSpan<I> {
67 fn predicate(&self) -> <I as Interner>::Predicate {
68 self.clause.as_predicate()
69 }
70
71 fn child(&self, clause: <I as Interner>::Clause) -> Self {
72 ClauseWithSupertraitSpan { clause, supertrait_span: self.supertrait_span }
73 }
74
75 fn child_with_derived_cause(
76 &self,
77 clause: <I as Interner>::Clause,
78 supertrait_span: <I as Interner>::Span,
79 _parent_trait_pred: crate::Binder<I, crate::TraitPredicate<I>>,
80 _index: usize,
81 ) -> Self {
82 ClauseWithSupertraitSpan { clause, supertrait_span }
83 }
84}
85
86pub fn elaborate<I: Interner, O: Elaboratable<I>>(
87 cx: I,
88 obligations: impl IntoIterator<Item = O>,
89) -> Elaborator<I, O> {
90 let mut elaborator = Elaborator {
91 cx,
92 stack: Vec::new(),
93 visited: HashSet::default(),
94 mode: Filter::All,
95 elaborate_sized: ElaborateSized::No,
96 };
97 elaborator.extend_deduped(obligations);
98 elaborator
99}
100
101impl<I: Interner, O: Elaboratable<I>> Elaborator<I, O> {
102 fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = O>) {
104 self.stack.extend(
109 obligations.into_iter().filter(|o| {
110 self.visited.insert(self.cx.anonymize_bound_vars(o.predicate().kind()))
111 }),
112 );
113 }
114
115 pub fn filter_only_self(mut self) -> Self {
118 self.mode = Filter::OnlySelf;
119 self
120 }
121
122 pub fn elaborate_sized(mut self) -> Self {
125 self.elaborate_sized = ElaborateSized::Yes;
126 self
127 }
128
129 fn elaborate(&mut self, elaboratable: &O) {
130 let cx = self.cx;
131
132 let Some(clause) = elaboratable.predicate().as_clause() else {
134 return;
135 };
136
137 if self.elaborate_sized == ElaborateSized::No
144 && let Some(did) = clause.as_trait_clause().map(|c| c.def_id())
145 && self.cx.is_trait_lang_item(did, SolverTraitLangItem::Sized)
146 {
147 return;
148 }
149
150 let bound_clause = clause.kind();
151 match bound_clause.skip_binder() {
152 ty::ClauseKind::Trait(data) => {
153 if data.polarity != ty::PredicatePolarity::Positive {
155 return;
156 }
157
158 let map_to_child_clause =
159 |(index, (clause, span)): (usize, (I::Clause, I::Span))| {
160 elaboratable.child_with_derived_cause(
161 clause.instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
162 span,
163 bound_clause.rebind(data),
164 index,
165 )
166 };
167
168 match self.mode {
170 Filter::All => self.extend_deduped(
171 cx.explicit_implied_predicates_of(data.def_id().into())
172 .iter_identity()
173 .map(Unnormalized::skip_norm_wip)
174 .enumerate()
175 .map(map_to_child_clause),
176 ),
177 Filter::OnlySelf => self.extend_deduped(
178 cx.explicit_super_predicates_of(data.def_id())
179 .iter_identity()
180 .map(Unnormalized::skip_norm_wip)
181 .enumerate()
182 .map(map_to_child_clause),
183 ),
184 };
185 }
186 ty::ClauseKind::HostEffect(data) => self.extend_deduped(
188 cx.explicit_implied_const_bounds(data.def_id().into()).iter_identity().map(
189 |trait_ref| {
190 elaboratable.child(
191 trait_ref
192 .to_host_effect_clause(cx, data.constness)
193 .skip_norm_wip()
194 .instantiate_supertrait(cx, bound_clause.rebind(data.trait_ref)),
195 )
196 },
197 ),
198 ),
199 ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty_max, r_min)) => {
200 if r_min.is_bound() {
215 return;
216 }
217
218 let mut components = ::smallvec::SmallVec::new()smallvec![];
219 push_outlives_components(cx, ty_max, &mut components);
220 self.extend_deduped(
221 components
222 .into_iter()
223 .filter_map(|component| elaborate_component_to_clause(cx, component, r_min))
224 .map(|clause| elaboratable.child(bound_clause.rebind(clause).upcast(cx))),
225 );
226 }
227 ty::ClauseKind::RegionOutlives(..) => {
228 }
230 ty::ClauseKind::WellFormed(..) => {
231 }
234 ty::ClauseKind::Projection(..) => {
235 }
237 ty::ClauseKind::ConstEvaluatable(..) => {
238 }
241 ty::ClauseKind::ConstArgHasType(..) => {
242 }
244 ty::ClauseKind::UnstableFeature(_) => {
245 }
247 }
248 }
249}
250
251fn elaborate_component_to_clause<I: Interner>(
252 cx: I,
253 component: Component<I>,
254 outlives_region: I::Region,
255) -> Option<ty::ClauseKind<I>> {
256 match component {
257 Component::Region(r) => {
258 if r.is_bound() {
259 None
260 } else {
261 Some(ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r, outlives_region)))
262 }
263 }
264
265 Component::Param(p) => {
266 let ty = Ty::new_param(cx, p);
267 Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives_region)))
268 }
269
270 Component::Placeholder(p) => {
271 let ty = Ty::new_placeholder(cx, p);
272 Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, outlives_region)))
273 }
274
275 Component::UnresolvedInferenceVariable(_) => None,
276
277 Component::Alias(alias_ty) => {
278 Some(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
281 alias_ty.to_ty(cx, ty::IsRigid::No),
282 outlives_region,
283 )))
284 }
285
286 Component::EscapingAlias(_) => {
287 None
290 }
291 }
292}
293
294impl<I: Interner, O: Elaboratable<I>> Iterator for Elaborator<I, O> {
295 type Item = O;
296
297 fn size_hint(&self) -> (usize, Option<usize>) {
298 (self.stack.len(), None)
299 }
300
301 fn next(&mut self) -> Option<Self::Item> {
302 if let Some(obligation) = self.stack.pop() {
304 self.elaborate(&obligation);
305 Some(obligation)
306 } else {
307 None
308 }
309 }
310}
311
312pub fn supertrait_def_ids<I: Interner>(
321 cx: I,
322 trait_def_id: I::TraitId,
323) -> impl Iterator<Item = I::TraitId> {
324 let mut set = HashSet::default();
325 let mut stack = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[trait_def_id]))vec![trait_def_id];
326
327 set.insert(trait_def_id);
328
329 std::iter::from_fn(move || {
330 let trait_def_id = stack.pop()?;
331
332 for (predicate, _) in cx
333 .explicit_super_predicates_of(trait_def_id)
334 .iter_identity()
335 .map(Unnormalized::skip_norm_wip)
336 {
337 if let ty::ClauseKind::Trait(data) = predicate.kind().skip_binder()
338 && set.insert(data.def_id())
339 {
340 stack.push(data.def_id());
341 }
342 }
343
344 Some(trait_def_id)
345 })
346}
347
348pub fn supertraits<I: Interner>(
349 cx: I,
350 trait_ref: ty::Binder<I, ty::TraitRef<I>>,
351) -> FilterToTraits<I, Elaborator<I, I::Clause>> {
352 elaborate(cx, [trait_ref.upcast(cx)]).filter_only_self().filter_to_traits()
353}
354
355impl<I: Interner> Elaborator<I, I::Clause> {
356 fn filter_to_traits(self) -> FilterToTraits<I, Self> {
357 FilterToTraits { _cx: PhantomData, base_iterator: self }
358 }
359}
360
361pub struct FilterToTraits<I: Interner, It: Iterator<Item = I::Clause>> {
364 _cx: PhantomData<I>,
365 base_iterator: It,
366}
367
368impl<I: Interner, It: Iterator<Item = I::Clause>> Iterator for FilterToTraits<I, It> {
369 type Item = ty::Binder<I, ty::TraitRef<I>>;
370
371 fn next(&mut self) -> Option<ty::Binder<I, ty::TraitRef<I>>> {
372 while let Some(pred) = self.base_iterator.next() {
373 if let Some(data) = pred.as_trait_clause() {
374 return Some(data.map_bound(|t| t.trait_ref));
375 }
376 }
377 None
378 }
379
380 fn size_hint(&self) -> (usize, Option<usize>) {
381 let (_, upper) = self.base_iterator.size_hint();
382 (0, upper)
383 }
384}
385
386pub fn elaborate_outlives_assumptions<I: Interner>(
387 cx: I,
388 assumptions: impl IntoIterator<Item = ty::OutlivesPredicate<I, I::GenericArg>>,
389) -> HashSet<ty::OutlivesPredicate<I, I::GenericArg>> {
390 let mut collected = HashSet::default();
391
392 for ty::OutlivesPredicate(arg1, r2) in assumptions {
393 collected.insert(ty::OutlivesPredicate(arg1, r2));
394 match arg1.kind() {
395 ty::GenericArgKind::Type(ty1) => {
398 let mut components = ::smallvec::SmallVec::new()smallvec![];
399 push_outlives_components(cx, ty1, &mut components);
400 for c in components {
401 match c {
402 Component::Region(r1) => {
403 if !r1.is_bound() {
404 collected.insert(ty::OutlivesPredicate(r1.into(), r2));
405 }
406 }
407
408 Component::Param(p) => {
409 let ty = Ty::new_param(cx, p);
410 collected.insert(ty::OutlivesPredicate(ty.into(), r2));
411 }
412
413 Component::Placeholder(p) => {
414 let ty = Ty::new_placeholder(cx, p);
415 collected.insert(ty::OutlivesPredicate(ty.into(), r2));
416 }
417
418 Component::Alias(alias_ty) => {
419 collected.insert(ty::OutlivesPredicate(
420 alias_ty.to_ty(cx, ty::IsRigid::No).into(),
421 r2,
422 ));
423 }
424
425 Component::UnresolvedInferenceVariable(_) | Component::EscapingAlias(_) => {
426 }
427 }
428 }
429 }
430 ty::GenericArgKind::Lifetime(_) => {}
432 ty::GenericArgKind::Const(_) => {}
434 }
435 }
436
437 collected
438}