1use std::cmp::Ordering;
2
3use rustc_data_structures::intern::Interned;
4use rustc_hir::def_id::DefId;
5use rustc_macros::{HashStable, extension};
6use rustc_type_ir as ir;
7
8use crate::ty::{
9    self, DebruijnIndex, EarlyBinder, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom, WithCachedTypeInfo,
10};
11
12pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
13pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
14pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
15pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
16pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
17pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
18pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
19pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate<TyCtxt<'tcx>>;
20pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
21pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
22pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
23pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
24pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
25pub type OutlivesPredicate<'tcx, T> = ir::OutlivesPredicate<TyCtxt<'tcx>, T>;
26pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::Region<'tcx>>;
27pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, Ty<'tcx>>;
28pub type ArgOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>;
29pub type PolyTraitPredicate<'tcx> = ty::Binder<'tcx, TraitPredicate<'tcx>>;
30pub type PolyRegionOutlivesPredicate<'tcx> = ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>;
31pub type PolyTypeOutlivesPredicate<'tcx> = ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>;
32pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
33pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
34pub type PolyProjectionPredicate<'tcx> = ty::Binder<'tcx, ProjectionPredicate<'tcx>>;
35
36#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
43#[rustc_pass_by_value]
44pub struct Predicate<'tcx>(
45    pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
46);
47
48impl<'tcx> rustc_type_ir::inherent::Predicate<TyCtxt<'tcx>> for Predicate<'tcx> {
49    fn as_clause(self) -> Option<ty::Clause<'tcx>> {
50        self.as_clause()
51    }
52
53    fn allow_normalization(self) -> bool {
54        self.allow_normalization()
55    }
56}
57
58impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> {
59    type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>;
60
61    fn kind(self) -> Self::Kind {
62        self.kind()
63    }
64}
65
66impl<'tcx> rustc_type_ir::Flags for Predicate<'tcx> {
67    fn flags(&self) -> TypeFlags {
68        self.0.flags
69    }
70
71    fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
72        self.0.outer_exclusive_binder
73    }
74}
75
76impl<'tcx> Predicate<'tcx> {
77    #[inline]
79    pub fn kind(self) -> ty::Binder<'tcx, PredicateKind<'tcx>> {
80        self.0.internee
81    }
82
83    #[inline(always)]
85    pub fn flags(self) -> TypeFlags {
86        self.0.flags
87    }
88
89    #[inline(always)]
91    pub fn outer_exclusive_binder(self) -> DebruijnIndex {
92        self.0.outer_exclusive_binder
93    }
94
95    pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
99        let kind = self
100            .kind()
101            .map_bound(|kind| match kind {
102                PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
103                    trait_ref,
104                    polarity,
105                })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
106                    trait_ref,
107                    polarity: polarity.flip(),
108                }))),
109
110                _ => None,
111            })
112            .transpose()?;
113
114        Some(tcx.mk_predicate(kind))
115    }
116
117    #[inline]
123    pub fn allow_normalization(self) -> bool {
124        match self.kind().skip_binder() {
125            PredicateKind::Clause(ClauseKind::WellFormed(_)) | PredicateKind::AliasRelate(..) => {
126                false
127            }
128            PredicateKind::Clause(ClauseKind::Trait(_))
129            | PredicateKind::Clause(ClauseKind::HostEffect(..))
130            | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
131            | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
132            | PredicateKind::Clause(ClauseKind::Projection(_))
133            | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
134            | PredicateKind::Clause(ClauseKind::UnstableFeature(_))
135            | PredicateKind::DynCompatible(_)
136            | PredicateKind::Subtype(_)
137            | PredicateKind::Coerce(_)
138            | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
139            | PredicateKind::ConstEquate(_, _)
140            | PredicateKind::NormalizesTo(..)
141            | PredicateKind::Ambiguous => true,
142        }
143    }
144}
145
146impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
147    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
148        ty::tls::with(|tcx| {
149            let pred = tcx.short_string(self, path);
150            rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
151        })
152    }
153}
154
155impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
156    fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
157        ty::tls::with(|tcx| {
158            let clause = tcx.short_string(self, path);
159            rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
160        })
161    }
162}
163
164#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
168#[rustc_pass_by_value]
169pub struct Clause<'tcx>(
170    pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
171);
172
173impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
174    fn as_predicate(self) -> Predicate<'tcx> {
175        self.as_predicate()
176    }
177
178    fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
179        self.instantiate_supertrait(tcx, trait_ref)
180    }
181}
182
183impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> {
184    type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>;
185
186    fn kind(self) -> Self::Kind {
187        self.kind()
188    }
189}
190
191impl<'tcx> Clause<'tcx> {
192    pub fn as_predicate(self) -> Predicate<'tcx> {
193        Predicate(self.0)
194    }
195
196    pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> {
197        self.0.internee.map_bound(|kind| match kind {
198            PredicateKind::Clause(clause) => clause,
199            _ => unreachable!(),
200        })
201    }
202
203    pub fn as_trait_clause(self) -> Option<ty::Binder<'tcx, TraitPredicate<'tcx>>> {
204        let clause = self.kind();
205        if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
206            Some(clause.rebind(trait_clause))
207        } else {
208            None
209        }
210    }
211
212    pub fn as_projection_clause(self) -> Option<ty::Binder<'tcx, ProjectionPredicate<'tcx>>> {
213        let clause = self.kind();
214        if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
215            Some(clause.rebind(projection_clause))
216        } else {
217            None
218        }
219    }
220
221    pub fn as_type_outlives_clause(self) -> Option<ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
222        let clause = self.kind();
223        if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
224            Some(clause.rebind(o))
225        } else {
226            None
227        }
228    }
229
230    pub fn as_region_outlives_clause(
231        self,
232    ) -> Option<ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
233        let clause = self.kind();
234        if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
235            Some(clause.rebind(o))
236        } else {
237            None
238        }
239    }
240}
241
242impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
243
244#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
245impl<'tcx> ExistentialPredicate<'tcx> {
246    fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
249        match (*self, *other) {
250            (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
251            (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
252                tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
253            }
254            (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
255                tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
256            }
257            (ExistentialPredicate::Trait(_), _) => Ordering::Less,
258            (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
259                Ordering::Greater
260            }
261            (ExistentialPredicate::Projection(_), _) => Ordering::Less,
262            (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
263        }
264    }
265}
266
267pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
268
269impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
270    for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
271{
272    fn principal_def_id(self) -> Option<DefId> {
273        self.principal_def_id()
274    }
275
276    fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
277        self.principal()
278    }
279
280    fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
281        self.auto_traits()
282    }
283
284    fn projection_bounds(
285        self,
286    ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
287        self.projection_bounds()
288    }
289}
290
291impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
292    pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
318        self[0]
319            .map_bound(|this| match this {
320                ExistentialPredicate::Trait(tr) => Some(tr),
321                _ => None,
322            })
323            .transpose()
324    }
325
326    pub fn principal_def_id(&self) -> Option<DefId> {
327        self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
328    }
329
330    #[inline]
331    pub fn projection_bounds(
332        &self,
333    ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
334        self.iter().filter_map(|predicate| {
335            predicate
336                .map_bound(|pred| match pred {
337                    ExistentialPredicate::Projection(projection) => Some(projection),
338                    _ => None,
339                })
340                .transpose()
341        })
342    }
343
344    #[inline]
345    pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
346        self.iter().filter_map(|predicate| match predicate.skip_binder() {
347            ExistentialPredicate::AutoTrait(did) => Some(did),
348            _ => None,
349        })
350    }
351
352    pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
353        self.iter().filter(|predicate| {
354            !matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
355        })
356    }
357}
358
359pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
360pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
361pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
362
363impl<'tcx> Clause<'tcx> {
364    pub fn instantiate_supertrait(
370        self,
371        tcx: TyCtxt<'tcx>,
372        trait_ref: ty::PolyTraitRef<'tcx>,
373    ) -> Clause<'tcx> {
374        let bound_pred = self.kind();
449        let pred_bound_vars = bound_pred.bound_vars();
450        let trait_bound_vars = trait_ref.bound_vars();
451        let shifted_pred =
453            tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
454        let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
456        let bound_vars =
458            tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
459
460        tcx.reuse_or_mk_predicate(
462            self.as_predicate(),
463            ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
464        )
465        .expect_clause()
466    }
467}
468
469impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
470    fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
471        ty::Binder::dummy(from).upcast(tcx)
472    }
473}
474
475impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
476    fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
477        tcx.mk_predicate(from)
478    }
479}
480
481impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
482    fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
483        tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
484    }
485}
486
487impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
488    fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
489        tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
490    }
491}
492
493impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
494    fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
495        from.as_predicate()
496    }
497}
498
499impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
500    fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
501        tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
502    }
503}
504
505impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
506    fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
507        tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
508    }
509}
510
511impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
512    fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
513        ty::Binder::dummy(from).upcast(tcx)
514    }
515}
516
517impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
518    fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
519        let p: Predicate<'tcx> = from.upcast(tcx);
520        p.expect_clause()
521    }
522}
523
524impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
525    fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
526        let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
527        pred.upcast(tcx)
528    }
529}
530
531impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
532    fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
533        let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
534        pred.upcast(tcx)
535    }
536}
537
538impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> {
539    fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
540        PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
541    }
542}
543
544impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> {
545    fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
546        from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
547    }
548}
549
550impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> {
551    fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
552        let p: Predicate<'tcx> = from.upcast(tcx);
553        p.expect_clause()
554    }
555}
556
557impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> {
558    fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
559        let p: Predicate<'tcx> = from.upcast(tcx);
560        p.expect_clause()
561    }
562}
563
564impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
565    fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
566        ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
567    }
568}
569
570impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
571    fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
572        from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
573    }
574}
575
576impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
577    fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
578        ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
579    }
580}
581
582impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
583    fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
584        ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
585    }
586}
587
588impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> {
589    fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
590        from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
591    }
592}
593
594impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> {
595    fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
596        let p: Predicate<'tcx> = from.upcast(tcx);
597        p.expect_clause()
598    }
599}
600
601impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> {
602    fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
603        let p: Predicate<'tcx> = from.upcast(tcx);
604        p.expect_clause()
605    }
606}
607
608impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
609    for Predicate<'tcx>
610{
611    fn upcast_from(
612        from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
613        tcx: TyCtxt<'tcx>,
614    ) -> Self {
615        from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
616    }
617}
618
619impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
620    for Clause<'tcx>
621{
622    fn upcast_from(
623        from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
624        tcx: TyCtxt<'tcx>,
625    ) -> Self {
626        from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
627    }
628}
629
630impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
631    fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
632        PredicateKind::NormalizesTo(from).upcast(tcx)
633    }
634}
635
636impl<'tcx> Predicate<'tcx> {
637    pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> {
638        let predicate = self.kind();
639        match predicate.skip_binder() {
640            PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
641            _ => None,
642        }
643    }
644
645    pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
646        let predicate = self.kind();
647        match predicate.skip_binder() {
648            PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
649            _ => None,
650        }
651    }
652
653    pub fn as_clause(self) -> Option<Clause<'tcx>> {
655        match self.kind().skip_binder() {
656            PredicateKind::Clause(..) => Some(self.expect_clause()),
657            _ => None,
658        }
659    }
660
661    pub fn expect_clause(self) -> Clause<'tcx> {
663        match self.kind().skip_binder() {
664            PredicateKind::Clause(..) => Clause(self.0),
665            _ => bug!("{self} is not a clause"),
666        }
667    }
668}
669
670#[cfg(target_pointer_width = "64")]
672mod size_asserts {
673    use rustc_data_structures::static_assert_size;
674
675    use super::*;
676    static_assert_size!(PredicateKind<'_>, 32);
678    static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 56);
679    }