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