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, PredicatePolarity, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom,
10 WithCachedTypeInfo,
11};
12
13pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
14pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
15pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
16pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
17pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
18pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
19pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
20pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate<TyCtxt<'tcx>>;
21pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
22pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
23pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
24pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
25pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
26pub type OutlivesPredicate<'tcx, T> = ir::OutlivesPredicate<TyCtxt<'tcx>, T>;
27pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::Region<'tcx>>;
28pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, Ty<'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() {
126 PredicateKind::Clause(ClauseKind::WellFormed(_))
127 | PredicateKind::AliasRelate(..)
128 | PredicateKind::NormalizesTo(..) => false,
129 PredicateKind::Clause(ClauseKind::Trait(_))
130 | PredicateKind::Clause(ClauseKind::HostEffect(..))
131 | PredicateKind::Clause(ClauseKind::RegionOutlives(_))
132 | PredicateKind::Clause(ClauseKind::TypeOutlives(_))
133 | PredicateKind::Clause(ClauseKind::Projection(_))
134 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
135 | PredicateKind::DynCompatible(_)
136 | PredicateKind::Subtype(_)
137 | PredicateKind::Coerce(_)
138 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
139 | PredicateKind::ConstEquate(_, _)
140 | PredicateKind::Ambiguous => true,
141 }
142 }
143}
144
145impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
146 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
147 ty::tls::with(|tcx| {
148 let pred = tcx.short_string(self, path);
149 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
150 })
151 }
152}
153
154impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
155 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
156 ty::tls::with(|tcx| {
157 let clause = tcx.short_string(self, path);
158 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
159 })
160 }
161}
162
163#[derive(Clone, Copy, PartialEq, Eq, Hash, HashStable)]
167#[rustc_pass_by_value]
168pub struct Clause<'tcx>(
169 pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
170);
171
172impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
173 fn as_predicate(self) -> Predicate<'tcx> {
174 self.as_predicate()
175 }
176
177 fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
178 self.instantiate_supertrait(tcx, trait_ref)
179 }
180}
181
182impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> {
183 type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>;
184
185 fn kind(self) -> Self::Kind {
186 self.kind()
187 }
188}
189
190impl<'tcx> Clause<'tcx> {
191 pub fn as_predicate(self) -> Predicate<'tcx> {
192 Predicate(self.0)
193 }
194
195 pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> {
196 self.0.internee.map_bound(|kind| match kind {
197 PredicateKind::Clause(clause) => clause,
198 _ => unreachable!(),
199 })
200 }
201
202 pub fn as_trait_clause(self) -> Option<ty::Binder<'tcx, TraitPredicate<'tcx>>> {
203 let clause = self.kind();
204 if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
205 Some(clause.rebind(trait_clause))
206 } else {
207 None
208 }
209 }
210
211 pub fn as_projection_clause(self) -> Option<ty::Binder<'tcx, ProjectionPredicate<'tcx>>> {
212 let clause = self.kind();
213 if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
214 Some(clause.rebind(projection_clause))
215 } else {
216 None
217 }
218 }
219
220 pub fn as_type_outlives_clause(self) -> Option<ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
221 let clause = self.kind();
222 if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
223 Some(clause.rebind(o))
224 } else {
225 None
226 }
227 }
228
229 pub fn as_region_outlives_clause(
230 self,
231 ) -> Option<ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
232 let clause = self.kind();
233 if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
234 Some(clause.rebind(o))
235 } else {
236 None
237 }
238 }
239}
240
241#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
242impl<'tcx> ExistentialPredicate<'tcx> {
243 fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
246 match (*self, *other) {
247 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
248 (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
249 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
250 }
251 (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
252 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
253 }
254 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
255 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
256 Ordering::Greater
257 }
258 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
259 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
260 }
261 }
262}
263
264pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
265
266impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
267 for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
268{
269 fn principal_def_id(self) -> Option<DefId> {
270 self.principal_def_id()
271 }
272
273 fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
274 self.principal()
275 }
276
277 fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
278 self.auto_traits()
279 }
280
281 fn projection_bounds(
282 self,
283 ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
284 self.projection_bounds()
285 }
286}
287
288impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
289 pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
315 self[0]
316 .map_bound(|this| match this {
317 ExistentialPredicate::Trait(tr) => Some(tr),
318 _ => None,
319 })
320 .transpose()
321 }
322
323 pub fn principal_def_id(&self) -> Option<DefId> {
324 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
325 }
326
327 #[inline]
328 pub fn projection_bounds(
329 &self,
330 ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
331 self.iter().filter_map(|predicate| {
332 predicate
333 .map_bound(|pred| match pred {
334 ExistentialPredicate::Projection(projection) => Some(projection),
335 _ => None,
336 })
337 .transpose()
338 })
339 }
340
341 #[inline]
342 pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
343 self.iter().filter_map(|predicate| match predicate.skip_binder() {
344 ExistentialPredicate::AutoTrait(did) => Some(did),
345 _ => None,
346 })
347 }
348
349 pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
350 self.iter().filter(|predicate| {
351 !matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
352 })
353 }
354}
355
356pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
357pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
358pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
359
360impl<'tcx> Clause<'tcx> {
361 pub fn instantiate_supertrait(
367 self,
368 tcx: TyCtxt<'tcx>,
369 trait_ref: ty::PolyTraitRef<'tcx>,
370 ) -> Clause<'tcx> {
371 let bound_pred = self.kind();
446 let pred_bound_vars = bound_pred.bound_vars();
447 let trait_bound_vars = trait_ref.bound_vars();
448 let shifted_pred =
450 tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
451 let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
453 let bound_vars =
455 tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
456
457 tcx.reuse_or_mk_predicate(
459 self.as_predicate(),
460 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
461 )
462 .expect_clause()
463 }
464}
465
466impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
467 fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
468 ty::Binder::dummy(from).upcast(tcx)
469 }
470}
471
472impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
473 fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
474 tcx.mk_predicate(from)
475 }
476}
477
478impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
479 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
480 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
481 }
482}
483
484impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
485 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
486 tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
487 }
488}
489
490impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
491 fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
492 from.as_predicate()
493 }
494}
495
496impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
497 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
498 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
499 }
500}
501
502impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
503 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
504 tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
505 }
506}
507
508impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
509 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
510 ty::Binder::dummy(from).upcast(tcx)
511 }
512}
513
514impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
515 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
516 let p: Predicate<'tcx> = from.upcast(tcx);
517 p.expect_clause()
518 }
519}
520
521impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
522 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
523 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
524 pred.upcast(tcx)
525 }
526}
527
528impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
529 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
530 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
531 pred.upcast(tcx)
532 }
533}
534
535impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
536 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
537 from.map_bound(|trait_ref| TraitPredicate {
538 trait_ref,
539 polarity: PredicatePolarity::Positive,
540 })
541 }
542}
543
544impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> {
545 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
546 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
547 }
548}
549
550impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> {
551 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
552 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
553 }
554}
555
556impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> {
557 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
558 let p: Predicate<'tcx> = from.upcast(tcx);
559 p.expect_clause()
560 }
561}
562
563impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> {
564 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
565 let p: Predicate<'tcx> = from.upcast(tcx);
566 p.expect_clause()
567 }
568}
569
570impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
571 fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
572 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
573 }
574}
575
576impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
577 fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
578 from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
579 }
580}
581
582impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
583 fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
584 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
585 }
586}
587
588impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
589 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
590 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
591 }
592}
593
594impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> {
595 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
596 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
597 }
598}
599
600impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> {
601 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
602 let p: Predicate<'tcx> = from.upcast(tcx);
603 p.expect_clause()
604 }
605}
606
607impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> {
608 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
609 let p: Predicate<'tcx> = from.upcast(tcx);
610 p.expect_clause()
611 }
612}
613
614impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
615 for Predicate<'tcx>
616{
617 fn upcast_from(
618 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
619 tcx: TyCtxt<'tcx>,
620 ) -> Self {
621 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
622 }
623}
624
625impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
626 for Clause<'tcx>
627{
628 fn upcast_from(
629 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
630 tcx: TyCtxt<'tcx>,
631 ) -> Self {
632 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
633 }
634}
635
636impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
637 fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
638 PredicateKind::NormalizesTo(from).upcast(tcx)
639 }
640}
641
642impl<'tcx> Predicate<'tcx> {
643 pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> {
644 let predicate = self.kind();
645 match predicate.skip_binder() {
646 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
647 PredicateKind::Clause(ClauseKind::Projection(..))
648 | PredicateKind::Clause(ClauseKind::HostEffect(..))
649 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
650 | PredicateKind::NormalizesTo(..)
651 | PredicateKind::AliasRelate(..)
652 | PredicateKind::Subtype(..)
653 | PredicateKind::Coerce(..)
654 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
655 | PredicateKind::Clause(ClauseKind::WellFormed(..))
656 | PredicateKind::DynCompatible(..)
657 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
658 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
659 | PredicateKind::ConstEquate(..)
660 | PredicateKind::Ambiguous => None,
661 }
662 }
663
664 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
665 let predicate = self.kind();
666 match predicate.skip_binder() {
667 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
668 PredicateKind::Clause(ClauseKind::Trait(..))
669 | PredicateKind::Clause(ClauseKind::HostEffect(..))
670 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
671 | PredicateKind::NormalizesTo(..)
672 | PredicateKind::AliasRelate(..)
673 | PredicateKind::Subtype(..)
674 | PredicateKind::Coerce(..)
675 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
676 | PredicateKind::Clause(ClauseKind::WellFormed(..))
677 | PredicateKind::DynCompatible(..)
678 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
679 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
680 | PredicateKind::ConstEquate(..)
681 | PredicateKind::Ambiguous => None,
682 }
683 }
684
685 pub fn as_clause(self) -> Option<Clause<'tcx>> {
687 match self.kind().skip_binder() {
688 PredicateKind::Clause(..) => Some(self.expect_clause()),
689 _ => None,
690 }
691 }
692
693 pub fn expect_clause(self) -> Clause<'tcx> {
695 match self.kind().skip_binder() {
696 PredicateKind::Clause(..) => Clause(self.0),
697 _ => bug!("{self} is not a clause"),
698 }
699 }
700}