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 PredicateKind::Clause(ClauseKind::Projection(..))
642 | PredicateKind::Clause(ClauseKind::HostEffect(..))
643 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
644 | PredicateKind::Clause(ClauseKind::UnstableFeature(_))
645 | PredicateKind::NormalizesTo(..)
646 | PredicateKind::AliasRelate(..)
647 | PredicateKind::Subtype(..)
648 | PredicateKind::Coerce(..)
649 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
650 | PredicateKind::Clause(ClauseKind::WellFormed(..))
651 | PredicateKind::DynCompatible(..)
652 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
653 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
654 | PredicateKind::ConstEquate(..)
655 | PredicateKind::Ambiguous => None,
656 }
657 }
658
659 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
660 let predicate = self.kind();
661 match predicate.skip_binder() {
662 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
663 PredicateKind::Clause(ClauseKind::Trait(..))
664 | PredicateKind::Clause(ClauseKind::HostEffect(..))
665 | PredicateKind::Clause(ClauseKind::ConstArgHasType(..))
666 | PredicateKind::Clause(ClauseKind::UnstableFeature(_))
667 | PredicateKind::NormalizesTo(..)
668 | PredicateKind::AliasRelate(..)
669 | PredicateKind::Subtype(..)
670 | PredicateKind::Coerce(..)
671 | PredicateKind::Clause(ClauseKind::RegionOutlives(..))
672 | PredicateKind::Clause(ClauseKind::WellFormed(..))
673 | PredicateKind::DynCompatible(..)
674 | PredicateKind::Clause(ClauseKind::TypeOutlives(..))
675 | PredicateKind::Clause(ClauseKind::ConstEvaluatable(..))
676 | PredicateKind::ConstEquate(..)
677 | PredicateKind::Ambiguous => None,
678 }
679 }
680
681 pub fn as_clause(self) -> Option<Clause<'tcx>> {
683 match self.kind().skip_binder() {
684 PredicateKind::Clause(..) => Some(self.expect_clause()),
685 _ => None,
686 }
687 }
688
689 pub fn expect_clause(self) -> Clause<'tcx> {
691 match self.kind().skip_binder() {
692 PredicateKind::Clause(..) => Clause(self.0),
693 _ => bug!("{self} is not a clause"),
694 }
695 }
696}
697
698#[cfg(target_pointer_width = "64")]
700mod size_asserts {
701 use rustc_data_structures::static_assert_size;
702
703 use super::*;
704 static_assert_size!(PredicateKind<'_>, 32);
706 static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 56);
707 }