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() {
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::DynCompatible(_)
135 | PredicateKind::Subtype(_)
136 | PredicateKind::Coerce(_)
137 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(_))
138 | PredicateKind::ConstEquate(_, _)
139 | PredicateKind::NormalizesTo(..)
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
241impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
242
243#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
244impl<'tcx> ExistentialPredicate<'tcx> {
245 fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
248 match (*self, *other) {
249 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
250 (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
251 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
252 }
253 (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
254 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
255 }
256 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
257 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
258 Ordering::Greater
259 }
260 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
261 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
262 }
263 }
264}
265
266pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
267
268impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
269 for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
270{
271 fn principal_def_id(self) -> Option<DefId> {
272 self.principal_def_id()
273 }
274
275 fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
276 self.principal()
277 }
278
279 fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
280 self.auto_traits()
281 }
282
283 fn projection_bounds(
284 self,
285 ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
286 self.projection_bounds()
287 }
288}
289
290impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
291 pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
317 self[0]
318 .map_bound(|this| match this {
319 ExistentialPredicate::Trait(tr) => Some(tr),
320 _ => None,
321 })
322 .transpose()
323 }
324
325 pub fn principal_def_id(&self) -> Option<DefId> {
326 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
327 }
328
329 #[inline]
330 pub fn projection_bounds(
331 &self,
332 ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
333 self.iter().filter_map(|predicate| {
334 predicate
335 .map_bound(|pred| match pred {
336 ExistentialPredicate::Projection(projection) => Some(projection),
337 _ => None,
338 })
339 .transpose()
340 })
341 }
342
343 #[inline]
344 pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
345 self.iter().filter_map(|predicate| match predicate.skip_binder() {
346 ExistentialPredicate::AutoTrait(did) => Some(did),
347 _ => None,
348 })
349 }
350
351 pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
352 self.iter().filter(|predicate| {
353 !matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
354 })
355 }
356}
357
358pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
359pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
360pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
361
362impl<'tcx> Clause<'tcx> {
363 pub fn instantiate_supertrait(
369 self,
370 tcx: TyCtxt<'tcx>,
371 trait_ref: ty::PolyTraitRef<'tcx>,
372 ) -> Clause<'tcx> {
373 let bound_pred = self.kind();
448 let pred_bound_vars = bound_pred.bound_vars();
449 let trait_bound_vars = trait_ref.bound_vars();
450 let shifted_pred =
452 tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
453 let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
455 let bound_vars =
457 tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
458
459 tcx.reuse_or_mk_predicate(
461 self.as_predicate(),
462 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
463 )
464 .expect_clause()
465 }
466}
467
468impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
469 fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
470 ty::Binder::dummy(from).upcast(tcx)
471 }
472}
473
474impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
475 fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
476 tcx.mk_predicate(from)
477 }
478}
479
480impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
481 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
482 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
483 }
484}
485
486impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
487 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
488 tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
489 }
490}
491
492impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
493 fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
494 from.as_predicate()
495 }
496}
497
498impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
499 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
500 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
501 }
502}
503
504impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
505 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
506 tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
507 }
508}
509
510impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
511 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
512 ty::Binder::dummy(from).upcast(tcx)
513 }
514}
515
516impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
517 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
518 let p: Predicate<'tcx> = from.upcast(tcx);
519 p.expect_clause()
520 }
521}
522
523impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
524 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
525 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
526 pred.upcast(tcx)
527 }
528}
529
530impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
531 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
532 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
533 pred.upcast(tcx)
534 }
535}
536
537impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for PolyTraitPredicate<'tcx> {
538 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, _tcx: TyCtxt<'tcx>) -> Self {
539 from.map_bound(|trait_ref| TraitPredicate {
540 trait_ref,
541 polarity: PredicatePolarity::Positive,
542 })
543 }
544}
545
546impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> {
547 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
548 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
549 }
550}
551
552impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> {
553 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
554 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
555 }
556}
557
558impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> {
559 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
560 let p: Predicate<'tcx> = from.upcast(tcx);
561 p.expect_clause()
562 }
563}
564
565impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> {
566 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
567 let p: Predicate<'tcx> = from.upcast(tcx);
568 p.expect_clause()
569 }
570}
571
572impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
573 fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
574 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
575 }
576}
577
578impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
579 fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
580 from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
581 }
582}
583
584impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
585 fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
586 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
587 }
588}
589
590impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
591 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
592 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
593 }
594}
595
596impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> {
597 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
598 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
599 }
600}
601
602impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> {
603 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
604 let p: Predicate<'tcx> = from.upcast(tcx);
605 p.expect_clause()
606 }
607}
608
609impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> {
610 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
611 let p: Predicate<'tcx> = from.upcast(tcx);
612 p.expect_clause()
613 }
614}
615
616impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
617 for Predicate<'tcx>
618{
619 fn upcast_from(
620 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
621 tcx: TyCtxt<'tcx>,
622 ) -> Self {
623 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
624 }
625}
626
627impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
628 for Clause<'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>, NormalizesTo<'tcx>> for Predicate<'tcx> {
639 fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
640 PredicateKind::NormalizesTo(from).upcast(tcx)
641 }
642}
643
644impl<'tcx> Predicate<'tcx> {
645 pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> {
646 let predicate = self.kind();
647 match predicate.skip_binder() {
648 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
649 PredicateKind::Clause(ClauseKind::Projection(..))
650 | PredicateKind::Clause(ClauseKind::HostEffect(..))
651 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
652 | PredicateKind::NormalizesTo(..)
653 | PredicateKind::AliasRelate(..)
654 | PredicateKind::Subtype(..)
655 | PredicateKind::Coerce(..)
656 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
657 | PredicateKind::Clause(ClauseKind::WellFormed(..))
658 | PredicateKind::DynCompatible(..)
659 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
660 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
661 | PredicateKind::ConstEquate(..)
662 | PredicateKind::Ambiguous => None,
663 }
664 }
665
666 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
667 let predicate = self.kind();
668 match predicate.skip_binder() {
669 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
670 PredicateKind::Clause(ClauseKind::Trait(..))
671 | PredicateKind::Clause(ClauseKind::HostEffect(..))
672 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
673 | PredicateKind::NormalizesTo(..)
674 | PredicateKind::AliasRelate(..)
675 | PredicateKind::Subtype(..)
676 | PredicateKind::Coerce(..)
677 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
678 | PredicateKind::Clause(ClauseKind::WellFormed(..))
679 | PredicateKind::DynCompatible(..)
680 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
681 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
682 | PredicateKind::ConstEquate(..)
683 | PredicateKind::Ambiguous => None,
684 }
685 }
686
687 pub fn as_clause(self) -> Option<Clause<'tcx>> {
689 match self.kind().skip_binder() {
690 PredicateKind::Clause(..) => Some(self.expect_clause()),
691 _ => None,
692 }
693 }
694
695 pub fn expect_clause(self) -> Clause<'tcx> {
697 match self.kind().skip_binder() {
698 PredicateKind::Clause(..) => Clause(self.0),
699 _ => bug!("{self} is not a clause"),
700 }
701 }
702}