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