Skip to main content

hir_ty/next_solver/
predicate.rs

1//! Things related to predicates.
2
3use std::cmp::Ordering;
4
5use intern::{
6    Interned, InternedRef, InternedSlice, InternedSliceRef, impl_internable, impl_slice_internable,
7};
8use macros::{GenericTypeVisitable, TypeFoldable, TypeVisitable};
9use rustc_type_ir::{
10    self as ty, CollectAndApply, EarlyBinder, FlagComputation, Flags, GenericTypeVisitable,
11    PredicatePolarity, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, Upcast,
12    UpcastFrom, WithCachedTypeInfo,
13    elaborate::Elaboratable,
14    error::{ExpectedFound, TypeError},
15    inherent::{IntoKind, SliceLike},
16};
17
18use crate::next_solver::{
19    GenericArg, TraitIdWrapper, default_types, impl_foldable_for_interned_slice,
20    impl_stored_interned_slice, interned_slice,
21};
22
23use super::{Binder, BoundVarKinds, DbInterner, Region, Ty};
24
25pub type BoundExistentialPredicate<'db> = Binder<'db, ExistentialPredicate<'db>>;
26
27pub type TraitRef<'db> = ty::TraitRef<DbInterner<'db>>;
28pub type AliasTerm<'db> = ty::AliasTerm<DbInterner<'db>>;
29pub type ProjectionPredicate<'db> = ty::ProjectionPredicate<DbInterner<'db>>;
30pub type ExistentialPredicate<'db> = ty::ExistentialPredicate<DbInterner<'db>>;
31pub type ExistentialTraitRef<'db> = ty::ExistentialTraitRef<DbInterner<'db>>;
32pub type ExistentialProjection<'db> = ty::ExistentialProjection<DbInterner<'db>>;
33pub type TraitPredicate<'db> = ty::TraitPredicate<DbInterner<'db>>;
34pub type HostEffectPredicate<'db> = ty::HostEffectPredicate<DbInterner<'db>>;
35pub type ClauseKind<'db> = ty::ClauseKind<DbInterner<'db>>;
36pub type PredicateKind<'db> = ty::PredicateKind<DbInterner<'db>>;
37pub type NormalizesTo<'db> = ty::NormalizesTo<DbInterner<'db>>;
38pub type CoercePredicate<'db> = ty::CoercePredicate<DbInterner<'db>>;
39pub type SubtypePredicate<'db> = ty::SubtypePredicate<DbInterner<'db>>;
40pub type OutlivesPredicate<'db, T> = ty::OutlivesPredicate<DbInterner<'db>, T>;
41pub type RegionOutlivesPredicate<'db> = OutlivesPredicate<'db, Region<'db>>;
42pub type TypeOutlivesPredicate<'db> = OutlivesPredicate<'db, Ty<'db>>;
43pub type PolyTraitPredicate<'db> = Binder<'db, TraitPredicate<'db>>;
44pub type PolyRegionOutlivesPredicate<'db> = Binder<'db, RegionOutlivesPredicate<'db>>;
45pub type PolyTypeOutlivesPredicate<'db> = Binder<'db, TypeOutlivesPredicate<'db>>;
46pub type PolySubtypePredicate<'db> = Binder<'db, SubtypePredicate<'db>>;
47pub type PolyCoercePredicate<'db> = Binder<'db, CoercePredicate<'db>>;
48pub type PolyProjectionPredicate<'db> = Binder<'db, ProjectionPredicate<'db>>;
49pub type PolyTraitRef<'db> = Binder<'db, TraitRef<'db>>;
50pub type PolyExistentialTraitRef<'db> = Binder<'db, ExistentialTraitRef<'db>>;
51pub type PolyExistentialProjection<'db> = Binder<'db, ExistentialProjection<'db>>;
52pub type ArgOutlivesPredicate<'db> = OutlivesPredicate<'db, GenericArg<'db>>;
53
54/// Compares via an ordering that will not change if modules are reordered or other changes are
55/// made to the tree. In particular, this ordering is preserved across incremental compilations.
56fn stable_cmp_existential_predicate<'db>(
57    a: &ExistentialPredicate<'db>,
58    b: &ExistentialPredicate<'db>,
59) -> Ordering {
60    // FIXME: this is actual unstable - see impl in predicate.rs in `rustc_middle`
61    match (a, b) {
62        (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
63        (ExistentialPredicate::Projection(_a), ExistentialPredicate::Projection(_b)) => {
64            // Should sort by def path hash
65            Ordering::Equal
66        }
67        (ExistentialPredicate::AutoTrait(_a), ExistentialPredicate::AutoTrait(_b)) => {
68            // Should sort by def path hash
69            Ordering::Equal
70        }
71        (ExistentialPredicate::Trait(_), _) => Ordering::Less,
72        (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => Ordering::Greater,
73        (ExistentialPredicate::Projection(_), _) => Ordering::Less,
74        (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
75    }
76}
77interned_slice!(
78    BoundExistentialPredicatesStorage,
79    BoundExistentialPredicates,
80    StoredBoundExistentialPredicates,
81    bound_existential_predicates,
82    BoundExistentialPredicate<'db>,
83    BoundExistentialPredicate<'static>,
84);
85impl_foldable_for_interned_slice!(BoundExistentialPredicates);
86
87impl<'db> rustc_type_ir::inherent::BoundExistentialPredicates<DbInterner<'db>>
88    for BoundExistentialPredicates<'db>
89{
90    fn principal_def_id(self) -> Option<TraitIdWrapper> {
91        self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
92    }
93
94    fn principal(
95        self,
96    ) -> Option<
97        rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::ExistentialTraitRef<DbInterner<'db>>>,
98    > {
99        self[0]
100            .map_bound(|this| match this {
101                ExistentialPredicate::Trait(tr) => Some(tr),
102                _ => None,
103            })
104            .transpose()
105    }
106
107    fn auto_traits(self) -> impl IntoIterator<Item = TraitIdWrapper> {
108        self.iter().filter_map(|predicate| match predicate.skip_binder() {
109            ExistentialPredicate::AutoTrait(did) => Some(did),
110            _ => None,
111        })
112    }
113
114    fn projection_bounds(
115        self,
116    ) -> impl IntoIterator<
117        Item = rustc_type_ir::Binder<
118            DbInterner<'db>,
119            rustc_type_ir::ExistentialProjection<DbInterner<'db>>,
120        >,
121    > {
122        self.iter().filter_map(|predicate| {
123            predicate
124                .map_bound(|pred| match pred {
125                    ExistentialPredicate::Projection(projection) => Some(projection),
126                    _ => None,
127                })
128                .transpose()
129        })
130    }
131}
132
133impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for BoundExistentialPredicates<'db> {
134    fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
135        relation: &mut R,
136        a: Self,
137        b: Self,
138    ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
139        // We need to perform this deduplication as we sometimes generate duplicate projections in `a`.
140        let mut a_v: Vec<_> = a.into_iter().collect();
141        let mut b_v: Vec<_> = b.into_iter().collect();
142        // `skip_binder` here is okay because `stable_cmp` doesn't look at binders
143        a_v.sort_by(|a, b| {
144            stable_cmp_existential_predicate(a.as_ref().skip_binder(), b.as_ref().skip_binder())
145        });
146        a_v.dedup();
147        b_v.sort_by(|a, b| {
148            stable_cmp_existential_predicate(a.as_ref().skip_binder(), b.as_ref().skip_binder())
149        });
150        b_v.dedup();
151        if a_v.len() != b_v.len() {
152            return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
153        }
154
155        let v = std::iter::zip(a_v, b_v).map(
156            |(ep_a, ep_b): (
157                Binder<'_, ty::ExistentialPredicate<_>>,
158                Binder<'_, ty::ExistentialPredicate<_>>,
159            )| {
160                match (ep_a.skip_binder(), ep_b.skip_binder()) {
161                    (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
162                        Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
163                            relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
164                        )))
165                    }
166                    (
167                        ty::ExistentialPredicate::Projection(a),
168                        ty::ExistentialPredicate::Projection(b),
169                    ) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
170                        relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
171                    ))),
172                    (
173                        ty::ExistentialPredicate::AutoTrait(a),
174                        ty::ExistentialPredicate::AutoTrait(b),
175                    ) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
176                    _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
177                }
178            },
179        );
180
181        BoundExistentialPredicates::new_from_iter(v)
182    }
183}
184
185#[derive(Clone, Copy, PartialEq, Eq, Hash)]
186pub struct Predicate<'db> {
187    interned: InternedRef<'db, PredicateInterned>,
188}
189
190#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
191pub(super) struct PredicateInterned(WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>);
192
193impl_internable!(gc; PredicateInterned);
194
195const _: () = {
196    const fn is_copy<T: Copy>() {}
197    is_copy::<Predicate<'static>>();
198};
199
200impl<'db> Predicate<'db> {
201    pub fn new(_interner: DbInterner<'db>, kind: Binder<'db, PredicateKind<'db>>) -> Self {
202        let kind = unsafe {
203            std::mem::transmute::<
204                Binder<'db, PredicateKind<'db>>,
205                Binder<'static, PredicateKind<'static>>,
206            >(kind)
207        };
208        let flags = FlagComputation::for_predicate(kind);
209        let cached = WithCachedTypeInfo {
210            internee: kind,
211            flags: flags.flags,
212            outer_exclusive_binder: flags.outer_exclusive_binder,
213        };
214        Self { interned: Interned::new_gc(PredicateInterned(cached)) }
215    }
216
217    pub fn inner(&self) -> &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>> {
218        let inner = &self.interned.0;
219        unsafe {
220            std::mem::transmute::<
221                &WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>,
222                &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>>,
223            >(inner)
224        }
225    }
226
227    /// Flips the polarity of a Predicate.
228    ///
229    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
230    pub fn flip_polarity(self, interner: DbInterner<'db>) -> Option<Predicate<'db>> {
231        let kind = self
232            .kind()
233            .map_bound(|kind| match kind {
234                PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
235                    trait_ref,
236                    polarity,
237                })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
238                    trait_ref,
239                    polarity: polarity.flip(),
240                }))),
241
242                _ => None,
243            })
244            .transpose()?;
245
246        Some(Predicate::new(interner, kind))
247    }
248}
249
250impl<'db> std::fmt::Debug for Predicate<'db> {
251    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252        self.kind().fmt(f)
253    }
254}
255
256#[derive(Clone, Copy, PartialEq, Eq, Hash, GenericTypeVisitable)]
257pub struct ClausesCachedTypeInfo(WithCachedTypeInfo<()>);
258
259impl_slice_internable!(gc; ClausesStorage, ClausesCachedTypeInfo, Clause<'static>);
260impl_stored_interned_slice!(ClausesStorage, Clauses, StoredClauses);
261
262#[derive(Clone, Copy, PartialEq, Eq, Hash)]
263pub struct Clauses<'db> {
264    interned: InternedSliceRef<'db, ClausesStorage>,
265}
266
267impl<'db> std::fmt::Debug for Clauses<'db> {
268    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269        self.as_slice().fmt(fmt)
270    }
271}
272
273impl<'db> Clauses<'db> {
274    #[inline]
275    pub fn empty() -> Self {
276        default_types().empty.clauses
277    }
278
279    #[inline]
280    pub fn new_from_slice(slice: &[Clause<'db>]) -> Self {
281        if slice.is_empty() {
282            // Common case: avoid looking up the empty slice.
283            Self::empty()
284        } else {
285            Self::new_from_slice_no_empty_check(slice)
286        }
287    }
288
289    /// Same as [`Self::new_from_slice()`] but won't use the global empty slice `slice.is_empty()`, because someone
290    /// needs to intern the global slice as well.
291    #[inline]
292    pub(crate) fn new_from_slice_no_empty_check(slice: &[Clause<'db>]) -> Self {
293        let slice = unsafe { ::std::mem::transmute::<&[Clause<'db>], &[Clause<'static>]>(slice) };
294        let flags = FlagComputation::<DbInterner<'db>>::for_clauses(slice);
295        let flags = ClausesCachedTypeInfo(WithCachedTypeInfo {
296            internee: (),
297            flags: flags.flags,
298            outer_exclusive_binder: flags.outer_exclusive_binder,
299        });
300        Self { interned: InternedSlice::from_header_and_slice(flags, slice) }
301    }
302
303    #[inline]
304    pub fn new_from_iter<I, T>(args: I) -> T::Output
305    where
306        I: IntoIterator<Item = T>,
307        T: CollectAndApply<Clause<'db>, Self>,
308    {
309        CollectAndApply::collect_and_apply(args.into_iter(), Self::new_from_slice)
310    }
311
312    #[inline]
313    pub fn as_slice(self) -> &'db [Clause<'db>] {
314        let slice = &self.interned.get().slice;
315        unsafe { ::std::mem::transmute::<&[Clause<'static>], &[Clause<'db>]>(slice) }
316    }
317
318    #[inline]
319    pub fn iter(self) -> ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>> {
320        self.as_slice().iter().copied()
321    }
322
323    #[inline]
324    pub fn len(self) -> usize {
325        self.as_slice().len()
326    }
327
328    #[inline]
329    pub fn is_empty(self) -> bool {
330        self.as_slice().is_empty()
331    }
332}
333
334impl Default for Clauses<'_> {
335    #[inline]
336    fn default() -> Self {
337        Self::empty()
338    }
339}
340
341impl<'db> IntoIterator for Clauses<'db> {
342    type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>;
343    type Item = Clause<'db>;
344    #[inline]
345    fn into_iter(self) -> Self::IntoIter {
346        self.iter()
347    }
348}
349
350impl<'db> std::ops::Deref for Clauses<'db> {
351    type Target = [Clause<'db>];
352
353    #[inline]
354    fn deref(&self) -> &Self::Target {
355        (*self).as_slice()
356    }
357}
358
359impl<'db> rustc_type_ir::inherent::SliceLike for Clauses<'db> {
360    type Item = Clause<'db>;
361
362    type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>;
363
364    #[inline]
365    fn iter(self) -> Self::IntoIter {
366        self.iter()
367    }
368
369    #[inline]
370    fn as_slice(&self) -> &[Self::Item] {
371        (*self).as_slice()
372    }
373}
374
375impl<'db> rustc_type_ir::inherent::Clauses<DbInterner<'db>> for Clauses<'db> {}
376
377impl<'db> rustc_type_ir::TypeSuperFoldable<DbInterner<'db>> for Clauses<'db> {
378    fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
379        self,
380        folder: &mut F,
381    ) -> Result<Self, F::Error> {
382        Clauses::new_from_iter(self.iter().map(|clause| clause.try_fold_with(folder)))
383    }
384
385    fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
386        self,
387        folder: &mut F,
388    ) -> Self {
389        Clauses::new_from_iter(self.iter().map(|clause| clause.fold_with(folder)))
390    }
391}
392
393impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for Clauses<'db> {
394    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
395        self,
396        folder: &mut F,
397    ) -> Result<Self, F::Error> {
398        self.try_super_fold_with(folder)
399    }
400    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
401        self.super_fold_with(folder)
402    }
403}
404
405impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Clauses<'db> {
406    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
407        &self,
408        visitor: &mut V,
409    ) -> V::Result {
410        use rustc_ast_ir::visit::VisitorResult;
411        rustc_ast_ir::walk_visitable_list!(visitor, self.iter());
412        V::Result::output()
413    }
414}
415
416impl<'db, V: super::WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Clauses<'db> {
417    fn generic_visit_with(&self, visitor: &mut V) {
418        if visitor.on_interned_slice(self.interned).is_continue() {
419            self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
420        }
421    }
422}
423
424impl<'db> rustc_type_ir::Flags for Clauses<'db> {
425    #[inline]
426    fn flags(&self) -> rustc_type_ir::TypeFlags {
427        self.interned.header.header.0.flags
428    }
429
430    #[inline]
431    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
432        self.interned.header.header.0.outer_exclusive_binder
433    }
434}
435
436impl<'db> rustc_type_ir::TypeSuperVisitable<DbInterner<'db>> for Clauses<'db> {
437    fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
438        &self,
439        visitor: &mut V,
440    ) -> V::Result {
441        self.as_slice().visit_with(visitor)
442    }
443}
444
445#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, GenericTypeVisitable)] // TODO implement Debug by hand
446pub struct Clause<'db>(pub(crate) Predicate<'db>);
447
448// We could cram the reveal into the clauses like rustc does, probably
449#[derive(
450    Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable, GenericTypeVisitable,
451)]
452pub struct ParamEnv<'db> {
453    pub(crate) clauses: Clauses<'db>,
454}
455
456impl<'db> ParamEnv<'db> {
457    #[inline]
458    pub fn empty() -> Self {
459        ParamEnv { clauses: Clauses::empty() }
460    }
461
462    pub fn clauses(self) -> Clauses<'db> {
463        self.clauses
464    }
465}
466
467impl<'db> rustc_type_ir::inherent::ParamEnv<DbInterner<'db>> for ParamEnv<'db> {
468    fn caller_bounds(self) -> impl rustc_type_ir::inherent::SliceLike<Item = Clause<'db>> {
469        self.clauses
470    }
471}
472
473#[derive(Clone, Debug, PartialEq, Eq, Hash)]
474pub struct ParamEnvAnd<'db, T> {
475    pub param_env: ParamEnv<'db>,
476    pub value: T,
477}
478
479impl<'db, T> ParamEnvAnd<'db, T> {
480    pub fn into_parts(self) -> (ParamEnv<'db>, T) {
481        (self.param_env, self.value)
482    }
483}
484
485impl<'db> TypeVisitable<DbInterner<'db>> for Predicate<'db> {
486    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
487        &self,
488        visitor: &mut V,
489    ) -> V::Result {
490        visitor.visit_predicate(*self)
491    }
492}
493
494impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Predicate<'db> {
495    fn generic_visit_with(&self, visitor: &mut V) {
496        if visitor.on_interned(self.interned).is_continue() {
497            self.kind().generic_visit_with(visitor);
498        }
499    }
500}
501
502impl<'db> TypeSuperVisitable<DbInterner<'db>> for Predicate<'db> {
503    fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
504        &self,
505        visitor: &mut V,
506    ) -> V::Result {
507        (*self).kind().visit_with(visitor)
508    }
509}
510
511impl<'db> TypeFoldable<DbInterner<'db>> for Predicate<'db> {
512    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
513        self,
514        folder: &mut F,
515    ) -> Result<Self, F::Error> {
516        folder.try_fold_predicate(self)
517    }
518    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
519        folder.fold_predicate(self)
520    }
521}
522
523impl<'db> TypeSuperFoldable<DbInterner<'db>> for Predicate<'db> {
524    fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
525        self,
526        folder: &mut F,
527    ) -> Result<Self, F::Error> {
528        let new = self.kind().try_fold_with(folder)?;
529        Ok(Predicate::new(folder.cx(), new))
530    }
531    fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
532        self,
533        folder: &mut F,
534    ) -> Self {
535        let new = self.kind().fold_with(folder);
536        Predicate::new(folder.cx(), new)
537    }
538}
539
540impl<'db> Elaboratable<DbInterner<'db>> for Predicate<'db> {
541    fn predicate(&self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
542        *self
543    }
544
545    fn child(&self, clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause) -> Self {
546        clause.as_predicate()
547    }
548
549    fn child_with_derived_cause(
550        &self,
551        clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause,
552        _span: <DbInterner<'db> as rustc_type_ir::Interner>::Span,
553        _parent_trait_pred: rustc_type_ir::Binder<
554            DbInterner<'db>,
555            rustc_type_ir::TraitPredicate<DbInterner<'db>>,
556        >,
557        _index: usize,
558    ) -> Self {
559        clause.as_predicate()
560    }
561}
562
563impl<'db> Flags for Predicate<'db> {
564    fn flags(&self) -> rustc_type_ir::TypeFlags {
565        self.inner().flags
566    }
567
568    fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
569        self.inner().outer_exclusive_binder
570    }
571}
572
573impl<'db> IntoKind for Predicate<'db> {
574    type Kind = Binder<'db, PredicateKind<'db>>;
575
576    fn kind(self) -> Self::Kind {
577        self.inner().internee
578    }
579}
580
581impl<'db> UpcastFrom<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>> for Predicate<'db> {
582    fn upcast_from(from: ty::PredicateKind<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
583        Binder::dummy(from).upcast(interner)
584    }
585}
586impl<'db>
587    UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>>>
588    for Predicate<'db>
589{
590    fn upcast_from(
591        from: ty::Binder<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>>,
592        interner: DbInterner<'db>,
593    ) -> Self {
594        Predicate::new(interner, from)
595    }
596}
597impl<'db> UpcastFrom<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>> for Predicate<'db> {
598    fn upcast_from(from: ty::ClauseKind<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
599        Binder::dummy(PredicateKind::Clause(from)).upcast(interner)
600    }
601}
602impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>>
603    for Predicate<'db>
604{
605    fn upcast_from(
606        from: ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>,
607        interner: DbInterner<'db>,
608    ) -> Self {
609        from.map_bound(PredicateKind::Clause).upcast(interner)
610    }
611}
612impl<'db> UpcastFrom<DbInterner<'db>, Clause<'db>> for Predicate<'db> {
613    fn upcast_from(from: Clause<'db>, _interner: DbInterner<'db>) -> Self {
614        from.0
615    }
616}
617impl<'db> UpcastFrom<DbInterner<'db>, ty::NormalizesTo<DbInterner<'db>>> for Predicate<'db> {
618    fn upcast_from(from: ty::NormalizesTo<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
619        PredicateKind::NormalizesTo(from).upcast(interner)
620    }
621}
622impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>> for Predicate<'db> {
623    fn upcast_from(from: ty::TraitRef<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
624        Binder::dummy(from).upcast(interner)
625    }
626}
627impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>>
628    for Predicate<'db>
629{
630    fn upcast_from(
631        from: ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>,
632        interner: DbInterner<'db>,
633    ) -> Self {
634        from.map_bound(|trait_ref| TraitPredicate {
635            trait_ref,
636            polarity: PredicatePolarity::Positive,
637        })
638        .upcast(interner)
639    }
640}
641impl<'db> UpcastFrom<DbInterner<'db>, Binder<'db, ty::TraitPredicate<DbInterner<'db>>>>
642    for Predicate<'db>
643{
644    fn upcast_from(
645        from: Binder<'db, ty::TraitPredicate<DbInterner<'db>>>,
646        interner: DbInterner<'db>,
647    ) -> Self {
648        from.map_bound(|it| PredicateKind::Clause(ClauseKind::Trait(it))).upcast(interner)
649    }
650}
651impl<'db> UpcastFrom<DbInterner<'db>, Binder<'db, ProjectionPredicate<'db>>> for Predicate<'db> {
652    fn upcast_from(from: Binder<'db, ProjectionPredicate<'db>>, interner: DbInterner<'db>) -> Self {
653        from.map_bound(|it| PredicateKind::Clause(ClauseKind::Projection(it))).upcast(interner)
654    }
655}
656impl<'db> UpcastFrom<DbInterner<'db>, ProjectionPredicate<'db>> for Predicate<'db> {
657    fn upcast_from(from: ProjectionPredicate<'db>, interner: DbInterner<'db>) -> Self {
658        PredicateKind::Clause(ClauseKind::Projection(from)).upcast(interner)
659    }
660}
661impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>> for Predicate<'db> {
662    fn upcast_from(from: ty::TraitPredicate<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
663        PredicateKind::Clause(ClauseKind::Trait(from)).upcast(interner)
664    }
665}
666impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>>
667    for Predicate<'db>
668{
669    fn upcast_from(
670        from: ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>,
671        interner: DbInterner<'db>,
672    ) -> Self {
673        PredicateKind::Clause(ClauseKind::TypeOutlives(from)).upcast(interner)
674    }
675}
676impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>>
677    for Predicate<'db>
678{
679    fn upcast_from(
680        from: ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>,
681        interner: DbInterner<'db>,
682    ) -> Self {
683        PredicateKind::Clause(ClauseKind::RegionOutlives(from)).upcast(interner)
684    }
685}
686impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>>
687    for Clause<'db>
688{
689    fn upcast_from(
690        from: ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>,
691        interner: DbInterner<'db>,
692    ) -> Self {
693        Clause(from.upcast(interner))
694    }
695}
696impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>>
697    for Clause<'db>
698{
699    fn upcast_from(
700        from: ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>,
701        interner: DbInterner<'db>,
702    ) -> Self {
703        Clause(from.upcast(interner))
704    }
705}
706
707impl<'db> UpcastFrom<DbInterner<'db>, PolyRegionOutlivesPredicate<'db>> for Predicate<'db> {
708    fn upcast_from(from: PolyRegionOutlivesPredicate<'db>, tcx: DbInterner<'db>) -> Self {
709        from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
710    }
711}
712
713impl<'db> rustc_type_ir::inherent::Predicate<DbInterner<'db>> for Predicate<'db> {
714    fn as_clause(self) -> Option<<DbInterner<'db> as rustc_type_ir::Interner>::Clause> {
715        match self.kind().skip_binder() {
716            PredicateKind::Clause(..) => Some(self.expect_clause()),
717            _ => None,
718        }
719    }
720}
721
722impl<'db> Predicate<'db> {
723    pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'db>> {
724        let predicate = self.kind();
725        match predicate.skip_binder() {
726            PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
727            _ => None,
728        }
729    }
730
731    pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'db>> {
732        let predicate = self.kind();
733        match predicate.skip_binder() {
734            PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
735            _ => None,
736        }
737    }
738
739    /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
740    pub fn as_clause(self) -> Option<Clause<'db>> {
741        match self.kind().skip_binder() {
742            PredicateKind::Clause(..) => Some(self.expect_clause()),
743            _ => None,
744        }
745    }
746
747    /// Assert that the predicate is a clause.
748    pub fn expect_clause(self) -> Clause<'db> {
749        match self.kind().skip_binder() {
750            PredicateKind::Clause(..) => Clause(self),
751            _ => panic!("{self:?} is not a clause"),
752        }
753    }
754}
755
756impl<'db> TypeVisitable<DbInterner<'db>> for Clause<'db> {
757    fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
758        &self,
759        visitor: &mut V,
760    ) -> V::Result {
761        visitor.visit_predicate((*self).as_predicate())
762    }
763}
764
765impl<'db> TypeFoldable<DbInterner<'db>> for Clause<'db> {
766    fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
767        self,
768        folder: &mut F,
769    ) -> Result<Self, F::Error> {
770        Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
771    }
772    fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
773        folder.fold_predicate(self.as_predicate()).expect_clause()
774    }
775}
776
777impl<'db> IntoKind for Clause<'db> {
778    type Kind = Binder<'db, ClauseKind<'db>>;
779
780    fn kind(self) -> Self::Kind {
781        self.0.kind().map_bound(|pk| match pk {
782            PredicateKind::Clause(kind) => kind,
783            _ => unreachable!(),
784        })
785    }
786}
787
788impl<'db> Clause<'db> {
789    pub fn as_predicate(self) -> Predicate<'db> {
790        self.0
791    }
792}
793
794impl<'db> Elaboratable<DbInterner<'db>> for Clause<'db> {
795    fn predicate(&self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
796        self.0
797    }
798
799    fn child(&self, clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause) -> Self {
800        clause
801    }
802
803    fn child_with_derived_cause(
804        &self,
805        clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause,
806        _span: <DbInterner<'db> as rustc_type_ir::Interner>::Span,
807        _parent_trait_pred: rustc_type_ir::Binder<
808            DbInterner<'db>,
809            rustc_type_ir::TraitPredicate<DbInterner<'db>>,
810        >,
811        _index: usize,
812    ) -> Self {
813        clause
814    }
815}
816
817impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>>
818    for Clause<'db>
819{
820    fn upcast_from(
821        from: ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>,
822        interner: DbInterner<'db>,
823    ) -> Self {
824        Clause(from.map_bound(PredicateKind::Clause).upcast(interner))
825    }
826}
827impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>> for Clause<'db> {
828    fn upcast_from(from: ty::TraitRef<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
829        Clause(from.upcast(interner))
830    }
831}
832impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>>
833    for Clause<'db>
834{
835    fn upcast_from(
836        from: ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>,
837        interner: DbInterner<'db>,
838    ) -> Self {
839        Clause(from.upcast(interner))
840    }
841}
842impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>> for Clause<'db> {
843    fn upcast_from(from: ty::TraitPredicate<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
844        Clause(from.upcast(interner))
845    }
846}
847impl<'db>
848    UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>>>
849    for Clause<'db>
850{
851    fn upcast_from(
852        from: ty::Binder<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>>,
853        interner: DbInterner<'db>,
854    ) -> Self {
855        Clause(from.upcast(interner))
856    }
857}
858impl<'db> UpcastFrom<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>> for Clause<'db> {
859    fn upcast_from(
860        from: ty::ProjectionPredicate<DbInterner<'db>>,
861        interner: DbInterner<'db>,
862    ) -> Self {
863        Clause(from.upcast(interner))
864    }
865}
866impl<'db>
867    UpcastFrom<
868        DbInterner<'db>,
869        ty::Binder<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>>,
870    > for Clause<'db>
871{
872    fn upcast_from(
873        from: ty::Binder<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>>,
874        interner: DbInterner<'db>,
875    ) -> Self {
876        Clause(from.upcast(interner))
877    }
878}
879
880impl<'db> rustc_type_ir::inherent::Clause<DbInterner<'db>> for Clause<'db> {
881    fn as_predicate(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
882        self.0
883    }
884
885    fn instantiate_supertrait(
886        self,
887        cx: DbInterner<'db>,
888        trait_ref: rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::TraitRef<DbInterner<'db>>>,
889    ) -> Self {
890        tracing::debug!(?self, ?trait_ref);
891        // See the rustc impl for a long comment
892        let bound_pred = self.kind();
893        let pred_bound_vars = bound_pred.bound_vars();
894        let trait_bound_vars = trait_ref.bound_vars();
895        // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
896        let shifted_pred =
897            cx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
898        // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
899        let new = EarlyBinder::bind(shifted_pred)
900            .instantiate(cx, trait_ref.skip_binder().args)
901            .skip_norm_wip();
902        // 3) ['x] + ['b] -> ['x, 'b]
903        let bound_vars =
904            BoundVarKinds::new_from_iter(trait_bound_vars.iter().chain(pred_bound_vars.iter()));
905
906        let predicate: Predicate<'db> =
907            ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars).upcast(cx);
908        predicate.expect_clause()
909    }
910}