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::{self, EarlyBinder, Ty, TyCtxt, TypeFlags, Upcast, UpcastFrom, WithCachedTypeInfo};
9
10pub type TraitRef<'tcx> = ir::TraitRef<TyCtxt<'tcx>>;
11pub type AliasTerm<'tcx> = ir::AliasTerm<TyCtxt<'tcx>>;
12pub type AliasTermKind<'tcx> = ir::AliasTermKind<TyCtxt<'tcx>>;
13pub type ProjectionPredicate<'tcx> = ir::ProjectionPredicate<TyCtxt<'tcx>>;
14pub type ExistentialPredicate<'tcx> = ir::ExistentialPredicate<TyCtxt<'tcx>>;
15pub type ExistentialTraitRef<'tcx> = ir::ExistentialTraitRef<TyCtxt<'tcx>>;
16pub type ExistentialProjection<'tcx> = ir::ExistentialProjection<TyCtxt<'tcx>>;
17pub type TraitPredicate<'tcx> = ir::TraitPredicate<TyCtxt<'tcx>>;
18pub type HostEffectPredicate<'tcx> = ir::HostEffectPredicate<TyCtxt<'tcx>>;
19pub type ClauseKind<'tcx> = ir::ClauseKind<TyCtxt<'tcx>>;
20pub type PredicateKind<'tcx> = ir::PredicateKind<TyCtxt<'tcx>>;
21pub type NormalizesTo<'tcx> = ir::NormalizesTo<TyCtxt<'tcx>>;
22pub type CoercePredicate<'tcx> = ir::CoercePredicate<TyCtxt<'tcx>>;
23pub type SubtypePredicate<'tcx> = ir::SubtypePredicate<TyCtxt<'tcx>>;
24pub type OutlivesPredicate<'tcx, T> = ir::OutlivesPredicate<TyCtxt<'tcx>, T>;
25pub type RegionOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::Region<'tcx>>;
26pub type TypeOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, Ty<'tcx>>;
27pub type ArgOutlivesPredicate<'tcx> = OutlivesPredicate<'tcx, ty::GenericArg<'tcx>>;
28pub type RegionEqPredicate<'tcx> = ir::RegionEqPredicate<TyCtxt<'tcx>>;
29pub type RegionConstraint<'tcx> = ir::RegionConstraint<TyCtxt<'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(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Predicate<'tcx> {
#[inline]
fn clone(&self) -> Predicate<'tcx> {
let _:
::core::clone::AssertParamIsClone<Interned<'tcx,
WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for Predicate<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Predicate<'tcx> {
#[inline]
fn eq(&self, other: &Predicate<'tcx>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Predicate<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<Interned<'tcx,
WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for Predicate<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, const _: () =
{
impl<'tcx, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_middle::ich::StableHashingContext<'__ctx>>
for Predicate<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Predicate(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};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
55impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> {
56 type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>;
57
58 fn kind(self) -> Self::Kind {
59 self.kind()
60 }
61}
62
63impl<'tcx> rustc_type_ir::Flags for Predicate<'tcx> {
64 fn flags(&self) -> TypeFlags {
65 self.0.flags
66 }
67
68 fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
69 self.0.outer_exclusive_binder
70 }
71}
72
73impl<'tcx> Predicate<'tcx> {
74 #[inline]
76 pub fn kind(self) -> ty::Binder<'tcx, PredicateKind<'tcx>> {
77 self.0.internee
78 }
79
80 pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
84 let kind = self
85 .kind()
86 .map_bound(|kind| match kind {
87 PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
88 trait_ref,
89 polarity,
90 })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
91 trait_ref,
92 polarity: polarity.flip(),
93 }))),
94
95 _ => None,
96 })
97 .transpose()?;
98
99 Some(tcx.mk_predicate(kind))
100 }
101
102 #[inline]
108 pub fn allow_normalization(self) -> bool {
109 rustc_type_ir::inherent::Predicate::allow_normalization(self)
110 }
111}
112
113impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
114 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
115 ty::tls::with(|tcx| {
116 let pred = tcx.short_string(self, path);
117 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
118 })
119 }
120}
121
122impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
123 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
124 ty::tls::with(|tcx| {
125 let clause = tcx.short_string(self, path);
126 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
127 })
128 }
129}
130
131#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Clause<'tcx> {
#[inline]
fn clone(&self) -> Clause<'tcx> {
let _:
::core::clone::AssertParamIsClone<Interned<'tcx,
WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>>;
*self
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::marker::Copy for Clause<'tcx> { }Copy, #[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Clause<'tcx> {
#[inline]
fn eq(&self, other: &Clause<'tcx>) -> bool { self.0 == other.0 }
}PartialEq, #[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Clause<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _:
::core::cmp::AssertParamIsEq<Interned<'tcx,
WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>>;
}
}Eq, #[automatically_derived]
impl<'tcx> ::core::hash::Hash for Clause<'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.0, state)
}
}Hash, const _: () =
{
impl<'tcx, '__ctx>
::rustc_data_structures::stable_hasher::HashStable<::rustc_middle::ich::StableHashingContext<'__ctx>>
for Clause<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx: &mut ::rustc_middle::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Clause(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable)]
135#[rustc_pass_by_value]
136pub struct Clause<'tcx>(
137 pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
138);
139
140impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
141 fn as_predicate(self) -> Predicate<'tcx> {
142 self.as_predicate()
143 }
144
145 fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
146 self.instantiate_supertrait(tcx, trait_ref)
147 }
148}
149
150impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> {
151 type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>;
152
153 fn kind(self) -> Self::Kind {
154 self.kind()
155 }
156}
157
158impl<'tcx> Clause<'tcx> {
159 pub fn as_predicate(self) -> Predicate<'tcx> {
160 Predicate(self.0)
161 }
162
163 pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> {
164 self.0.internee.map_bound(|kind| match kind {
165 PredicateKind::Clause(clause) => clause,
166 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
167 })
168 }
169
170 pub fn as_trait_clause(self) -> Option<ty::Binder<'tcx, TraitPredicate<'tcx>>> {
171 let clause = self.kind();
172 if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
173 Some(clause.rebind(trait_clause))
174 } else {
175 None
176 }
177 }
178
179 pub fn as_projection_clause(self) -> Option<ty::Binder<'tcx, ProjectionPredicate<'tcx>>> {
180 let clause = self.kind();
181 if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
182 Some(clause.rebind(projection_clause))
183 } else {
184 None
185 }
186 }
187
188 pub fn as_type_outlives_clause(self) -> Option<ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
189 let clause = self.kind();
190 if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
191 Some(clause.rebind(o))
192 } else {
193 None
194 }
195 }
196
197 pub fn as_region_outlives_clause(
198 self,
199 ) -> Option<ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
200 let clause = self.kind();
201 if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
202 Some(clause.rebind(o))
203 } else {
204 None
205 }
206 }
207}
208
209impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
210
211impl<'tcx> ExistentialPredicateStableCmpExt<'tcx> for
ExistentialPredicate<'tcx> {
#[doc =
" Compares via an ordering that will not change if modules are reordered or other changes are"]
#[doc =
" made to the tree. In particular, this ordering is preserved across incremental compilations."]
fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
match (*self, *other) {
(ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_))
=> Ordering::Equal,
(ExistentialPredicate::Projection(ref a),
ExistentialPredicate::Projection(ref b)) => {
tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
}
(ExistentialPredicate::AutoTrait(ref a),
ExistentialPredicate::AutoTrait(ref b)) => {
tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
}
(ExistentialPredicate::Trait(_), _) => Ordering::Less,
(ExistentialPredicate::Projection(_),
ExistentialPredicate::Trait(_)) => {
Ordering::Greater
}
(ExistentialPredicate::Projection(_), _) => Ordering::Less,
(ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
}
}
}#[extension(pub trait ExistentialPredicateStableCmpExt<'tcx>)]
212impl<'tcx> ExistentialPredicate<'tcx> {
213 fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
216 match (*self, *other) {
217 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
218 (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
219 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
220 }
221 (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
222 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
223 }
224 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
225 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
226 Ordering::Greater
227 }
228 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
229 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
230 }
231 }
232}
233
234pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
235
236impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
237 for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
238{
239 fn principal_def_id(self) -> Option<DefId> {
240 self.principal_def_id()
241 }
242
243 fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
244 self.principal()
245 }
246
247 fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
248 self.auto_traits()
249 }
250
251 fn projection_bounds(
252 self,
253 ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
254 self.projection_bounds()
255 }
256}
257
258impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
259 pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
285 self[0]
286 .map_bound(|this| match this {
287 ExistentialPredicate::Trait(tr) => Some(tr),
288 _ => None,
289 })
290 .transpose()
291 }
292
293 pub fn principal_def_id(&self) -> Option<DefId> {
294 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
295 }
296
297 #[inline]
298 pub fn projection_bounds(
299 &self,
300 ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
301 self.iter().filter_map(|predicate| {
302 predicate
303 .map_bound(|pred| match pred {
304 ExistentialPredicate::Projection(projection) => Some(projection),
305 _ => None,
306 })
307 .transpose()
308 })
309 }
310
311 #[inline]
312 pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
313 self.iter().filter_map(|predicate| match predicate.skip_binder() {
314 ExistentialPredicate::AutoTrait(did) => Some(did),
315 _ => None,
316 })
317 }
318
319 pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
320 self.iter().filter(|predicate| {
321 !#[allow(non_exhaustive_omitted_patterns)] match predicate.as_ref().skip_binder()
{
ExistentialPredicate::AutoTrait(_) => true,
_ => false,
}matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
322 })
323 }
324}
325
326pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
327pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
328pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
329
330impl<'tcx> Clause<'tcx> {
331 pub fn instantiate_supertrait(
337 self,
338 tcx: TyCtxt<'tcx>,
339 trait_ref: ty::PolyTraitRef<'tcx>,
340 ) -> Clause<'tcx> {
341 let bound_pred = self.kind();
416 let pred_bound_vars = bound_pred.bound_vars();
417 let trait_bound_vars = trait_ref.bound_vars();
418 let shifted_pred =
420 tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
421 let new = EarlyBinder::bind(shifted_pred)
423 .instantiate(tcx, trait_ref.skip_binder().args)
424 .skip_norm_wip();
425 let bound_vars =
427 tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
428
429 tcx.reuse_or_mk_predicate(
431 self.as_predicate(),
432 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
433 )
434 .expect_clause()
435 }
436}
437
438impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
439 fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
440 ty::Binder::dummy(from).upcast(tcx)
441 }
442}
443
444impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
445 fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
446 tcx.mk_predicate(from)
447 }
448}
449
450impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
451 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
452 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
453 }
454}
455
456impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
457 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
458 tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
459 }
460}
461
462impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
463 fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
464 from.as_predicate()
465 }
466}
467
468impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
469 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
470 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
471 }
472}
473
474impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
475 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
476 tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
477 }
478}
479
480impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
481 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
482 ty::Binder::dummy(from).upcast(tcx)
483 }
484}
485
486impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
487 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
488 let p: Predicate<'tcx> = from.upcast(tcx);
489 p.expect_clause()
490 }
491}
492
493impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
494 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
495 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
496 pred.upcast(tcx)
497 }
498}
499
500impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
501 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
502 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
503 pred.upcast(tcx)
504 }
505}
506
507impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> {
508 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
509 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
510 }
511}
512
513impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> {
514 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
515 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
516 }
517}
518
519impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> {
520 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
521 let p: Predicate<'tcx> = from.upcast(tcx);
522 p.expect_clause()
523 }
524}
525
526impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> {
527 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
528 let p: Predicate<'tcx> = from.upcast(tcx);
529 p.expect_clause()
530 }
531}
532
533impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
534 fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
535 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
536 }
537}
538
539impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
540 fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
541 from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
542 }
543}
544
545impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
546 fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
547 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
548 }
549}
550
551impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
552 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
553 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
554 }
555}
556
557impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> {
558 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
559 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
560 }
561}
562
563impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> {
564 fn upcast_from(from: ProjectionPredicate<'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>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> {
571 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
572 let p: Predicate<'tcx> = from.upcast(tcx);
573 p.expect_clause()
574 }
575}
576
577impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
578 for Predicate<'tcx>
579{
580 fn upcast_from(
581 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
582 tcx: TyCtxt<'tcx>,
583 ) -> Self {
584 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
585 }
586}
587
588impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
589 for Clause<'tcx>
590{
591 fn upcast_from(
592 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
593 tcx: TyCtxt<'tcx>,
594 ) -> Self {
595 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
596 }
597}
598
599impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
600 fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
601 PredicateKind::NormalizesTo(from).upcast(tcx)
602 }
603}
604
605impl<'tcx> Predicate<'tcx> {
606 pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> {
607 let predicate = self.kind();
608 match predicate.skip_binder() {
609 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
610 _ => None,
611 }
612 }
613
614 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
615 let predicate = self.kind();
616 match predicate.skip_binder() {
617 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
618 _ => None,
619 }
620 }
621
622 pub fn as_clause(self) -> Option<Clause<'tcx>> {
624 match self.kind().skip_binder() {
625 PredicateKind::Clause(..) => Some(self.expect_clause()),
626 _ => None,
627 }
628 }
629
630 pub fn expect_clause(self) -> Clause<'tcx> {
632 match self.kind().skip_binder() {
633 PredicateKind::Clause(..) => Clause(self.0),
634 _ => crate::util::bug::bug_fmt(format_args!("{0} is not a clause", self))bug!("{self} is not a clause"),
635 }
636 }
637}
638
639#[cfg(target_pointer_width = "64")]
641mod size_asserts {
642 use rustc_data_structures::static_assert_size;
643
644 use super::*;
645 const _: [(); 40] = [(); ::std::mem::size_of::<PredicateKind<'_>>()];static_assert_size!(PredicateKind<'_>, 40);
647 const _: [(); 64] =
[(); ::std::mem::size_of::<WithCachedTypeInfo<PredicateKind<'_>>>()];static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 64);
648 }