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