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