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(#[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_receiver_is_total_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_query_system::ich::StableHashingContext<'__ctx>>
for Predicate<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Predicate(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};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
54impl<'tcx> rustc_type_ir::inherent::IntoKind for Predicate<'tcx> {
55 type Kind = ty::Binder<'tcx, ty::PredicateKind<'tcx>>;
56
57 fn kind(self) -> Self::Kind {
58 self.kind()
59 }
60}
61
62impl<'tcx> rustc_type_ir::Flags for Predicate<'tcx> {
63 fn flags(&self) -> TypeFlags {
64 self.0.flags
65 }
66
67 fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
68 self.0.outer_exclusive_binder
69 }
70}
71
72impl<'tcx> Predicate<'tcx> {
73 #[inline]
75 pub fn kind(self) -> ty::Binder<'tcx, PredicateKind<'tcx>> {
76 self.0.internee
77 }
78
79 #[inline(always)]
81 pub fn flags(self) -> TypeFlags {
82 self.0.flags
83 }
84
85 #[inline(always)]
87 pub fn outer_exclusive_binder(self) -> DebruijnIndex {
88 self.0.outer_exclusive_binder
89 }
90
91 pub fn flip_polarity(self, tcx: TyCtxt<'tcx>) -> Option<Predicate<'tcx>> {
95 let kind = self
96 .kind()
97 .map_bound(|kind| match kind {
98 PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
99 trait_ref,
100 polarity,
101 })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
102 trait_ref,
103 polarity: polarity.flip(),
104 }))),
105
106 _ => None,
107 })
108 .transpose()?;
109
110 Some(tcx.mk_predicate(kind))
111 }
112
113 #[inline]
119 pub fn allow_normalization(self) -> bool {
120 rustc_type_ir::inherent::Predicate::allow_normalization(self)
121 }
122}
123
124impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
125 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
126 ty::tls::with(|tcx| {
127 let pred = tcx.short_string(self, path);
128 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
129 })
130 }
131}
132
133impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
134 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
135 ty::tls::with(|tcx| {
136 let clause = tcx.short_string(self, path);
137 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
138 })
139 }
140}
141
142#[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_receiver_is_total_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_query_system::ich::StableHashingContext<'__ctx>>
for Clause<'tcx> {
#[inline]
fn hash_stable(&self,
__hcx:
&mut ::rustc_query_system::ich::StableHashingContext<'__ctx>,
__hasher:
&mut ::rustc_data_structures::stable_hasher::StableHasher) {
match *self {
Clause(ref __binding_0) => {
{ __binding_0.hash_stable(__hcx, __hasher); }
}
}
}
}
};HashStable)]
146#[rustc_pass_by_value]
147pub struct Clause<'tcx>(
148 pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
149);
150
151impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
152 fn as_predicate(self) -> Predicate<'tcx> {
153 self.as_predicate()
154 }
155
156 fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
157 self.instantiate_supertrait(tcx, trait_ref)
158 }
159}
160
161impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> {
162 type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>;
163
164 fn kind(self) -> Self::Kind {
165 self.kind()
166 }
167}
168
169impl<'tcx> Clause<'tcx> {
170 pub fn as_predicate(self) -> Predicate<'tcx> {
171 Predicate(self.0)
172 }
173
174 pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> {
175 self.0.internee.map_bound(|kind| match kind {
176 PredicateKind::Clause(clause) => clause,
177 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
178 })
179 }
180
181 pub fn as_trait_clause(self) -> Option<ty::Binder<'tcx, TraitPredicate<'tcx>>> {
182 let clause = self.kind();
183 if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
184 Some(clause.rebind(trait_clause))
185 } else {
186 None
187 }
188 }
189
190 pub fn as_projection_clause(self) -> Option<ty::Binder<'tcx, ProjectionPredicate<'tcx>>> {
191 let clause = self.kind();
192 if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
193 Some(clause.rebind(projection_clause))
194 } else {
195 None
196 }
197 }
198
199 pub fn as_type_outlives_clause(self) -> Option<ty::Binder<'tcx, TypeOutlivesPredicate<'tcx>>> {
200 let clause = self.kind();
201 if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
202 Some(clause.rebind(o))
203 } else {
204 None
205 }
206 }
207
208 pub fn as_region_outlives_clause(
209 self,
210 ) -> Option<ty::Binder<'tcx, RegionOutlivesPredicate<'tcx>>> {
211 let clause = self.kind();
212 if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
213 Some(clause.rebind(o))
214 } else {
215 None
216 }
217 }
218}
219
220impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
221
222impl<'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>)]
223impl<'tcx> ExistentialPredicate<'tcx> {
224 fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
227 match (*self, *other) {
228 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
229 (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
230 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
231 }
232 (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
233 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
234 }
235 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
236 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
237 Ordering::Greater
238 }
239 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
240 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
241 }
242 }
243}
244
245pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
246
247impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
248 for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
249{
250 fn principal_def_id(self) -> Option<DefId> {
251 self.principal_def_id()
252 }
253
254 fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
255 self.principal()
256 }
257
258 fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
259 self.auto_traits()
260 }
261
262 fn projection_bounds(
263 self,
264 ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
265 self.projection_bounds()
266 }
267}
268
269impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
270 pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
296 self[0]
297 .map_bound(|this| match this {
298 ExistentialPredicate::Trait(tr) => Some(tr),
299 _ => None,
300 })
301 .transpose()
302 }
303
304 pub fn principal_def_id(&self) -> Option<DefId> {
305 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
306 }
307
308 #[inline]
309 pub fn projection_bounds(
310 &self,
311 ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
312 self.iter().filter_map(|predicate| {
313 predicate
314 .map_bound(|pred| match pred {
315 ExistentialPredicate::Projection(projection) => Some(projection),
316 _ => None,
317 })
318 .transpose()
319 })
320 }
321
322 #[inline]
323 pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
324 self.iter().filter_map(|predicate| match predicate.skip_binder() {
325 ExistentialPredicate::AutoTrait(did) => Some(did),
326 _ => None,
327 })
328 }
329
330 pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
331 self.iter().filter(|predicate| {
332 !#[allow(non_exhaustive_omitted_patterns)] match predicate.as_ref().skip_binder()
{
ExistentialPredicate::AutoTrait(_) => true,
_ => false,
}matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
333 })
334 }
335}
336
337pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
338pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
339pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
340
341impl<'tcx> Clause<'tcx> {
342 pub fn instantiate_supertrait(
348 self,
349 tcx: TyCtxt<'tcx>,
350 trait_ref: ty::PolyTraitRef<'tcx>,
351 ) -> Clause<'tcx> {
352 let bound_pred = self.kind();
427 let pred_bound_vars = bound_pred.bound_vars();
428 let trait_bound_vars = trait_ref.bound_vars();
429 let shifted_pred =
431 tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
432 let new = EarlyBinder::bind(shifted_pred).instantiate(tcx, trait_ref.skip_binder().args);
434 let bound_vars =
436 tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
437
438 tcx.reuse_or_mk_predicate(
440 self.as_predicate(),
441 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
442 )
443 .expect_clause()
444 }
445}
446
447impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
448 fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
449 ty::Binder::dummy(from).upcast(tcx)
450 }
451}
452
453impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
454 fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
455 tcx.mk_predicate(from)
456 }
457}
458
459impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
460 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
461 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
462 }
463}
464
465impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
466 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
467 tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
468 }
469}
470
471impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
472 fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
473 from.as_predicate()
474 }
475}
476
477impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
478 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
479 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
480 }
481}
482
483impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
484 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
485 tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
486 }
487}
488
489impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
490 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
491 ty::Binder::dummy(from).upcast(tcx)
492 }
493}
494
495impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
496 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
497 let p: Predicate<'tcx> = from.upcast(tcx);
498 p.expect_clause()
499 }
500}
501
502impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
503 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
504 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
505 pred.upcast(tcx)
506 }
507}
508
509impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
510 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
511 let pred: PolyTraitPredicate<'tcx> = from.upcast(tcx);
512 pred.upcast(tcx)
513 }
514}
515
516impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Predicate<'tcx> {
517 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
518 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
519 }
520}
521
522impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Predicate<'tcx> {
523 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
524 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
525 }
526}
527
528impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitPredicate<'tcx>> for Clause<'tcx> {
529 fn upcast_from(from: TraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
530 let p: Predicate<'tcx> = from.upcast(tcx);
531 p.expect_clause()
532 }
533}
534
535impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitPredicate<'tcx>> for Clause<'tcx> {
536 fn upcast_from(from: PolyTraitPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
537 let p: Predicate<'tcx> = from.upcast(tcx);
538 p.expect_clause()
539 }
540}
541
542impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
543 fn upcast_from(from: RegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
544 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
545 }
546}
547
548impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesPredicate<'tcx>> for Predicate<'tcx> {
549 fn upcast_from(from: PolyRegionOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
550 from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
551 }
552}
553
554impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesPredicate<'tcx>> for Predicate<'tcx> {
555 fn upcast_from(from: TypeOutlivesPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
556 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
557 }
558}
559
560impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Predicate<'tcx> {
561 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
562 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
563 }
564}
565
566impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Predicate<'tcx> {
567 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
568 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
569 }
570}
571
572impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionPredicate<'tcx>> for Clause<'tcx> {
573 fn upcast_from(from: ProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
574 let p: Predicate<'tcx> = from.upcast(tcx);
575 p.expect_clause()
576 }
577}
578
579impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionPredicate<'tcx>> for Clause<'tcx> {
580 fn upcast_from(from: PolyProjectionPredicate<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
581 let p: Predicate<'tcx> = from.upcast(tcx);
582 p.expect_clause()
583 }
584}
585
586impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
587 for Predicate<'tcx>
588{
589 fn upcast_from(
590 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
591 tcx: TyCtxt<'tcx>,
592 ) -> Self {
593 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
594 }
595}
596
597impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>>
598 for Clause<'tcx>
599{
600 fn upcast_from(
601 from: ty::Binder<'tcx, ty::HostEffectPredicate<'tcx>>,
602 tcx: TyCtxt<'tcx>,
603 ) -> Self {
604 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
605 }
606}
607
608impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
609 fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
610 PredicateKind::NormalizesTo(from).upcast(tcx)
611 }
612}
613
614impl<'tcx> Predicate<'tcx> {
615 pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'tcx>> {
616 let predicate = self.kind();
617 match predicate.skip_binder() {
618 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
619 _ => None,
620 }
621 }
622
623 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'tcx>> {
624 let predicate = self.kind();
625 match predicate.skip_binder() {
626 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
627 _ => None,
628 }
629 }
630
631 pub fn as_clause(self) -> Option<Clause<'tcx>> {
633 match self.kind().skip_binder() {
634 PredicateKind::Clause(..) => Some(self.expect_clause()),
635 _ => None,
636 }
637 }
638
639 pub fn expect_clause(self) -> Clause<'tcx> {
641 match self.kind().skip_binder() {
642 PredicateKind::Clause(..) => Clause(self.0),
643 _ => crate::util::bug::bug_fmt(format_args!("{0} is not a clause", self))bug!("{self} is not a clause"),
644 }
645 }
646}
647
648#[cfg(target_pointer_width = "64")]
650mod size_asserts {
651 use rustc_data_structures::static_assert_size;
652
653 use super::*;
654 const _: [(); 32] = [(); ::std::mem::size_of::<PredicateKind<'_>>()];static_assert_size!(PredicateKind<'_>, 32);
656 const _: [(); 56] =
[(); ::std::mem::size_of::<WithCachedTypeInfo<PredicateKind<'_>>>()];static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 56);
657 }