1use std::cmp::Ordering;
2
3use rustc_data_structures::intern::Interned;
4use rustc_hir::def_id::DefId;
5use rustc_macros::{StableHash, 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 ProjectionClause<'tcx> = ir::ProjectionClause<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 TraitClause<'tcx> = ir::TraitClause<TyCtxt<'tcx>>;
18pub type HostEffectClause<'tcx> = ir::HostEffectClause<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 OutlivesClause<'tcx, T> = ir::OutlivesClause<TyCtxt<'tcx>, T>;
25pub type RegionOutlivesClause<'tcx> = OutlivesClause<'tcx, ty::Region<'tcx>>;
26pub type TypeOutlivesClause<'tcx> = OutlivesClause<'tcx, Ty<'tcx>>;
27pub type ArgOutlivesClause<'tcx> = OutlivesClause<'tcx, ty::GenericArg<'tcx>>;
28pub type RegionEqPredicate<'tcx> = ir::RegionEqPredicate<TyCtxt<'tcx>>;
29pub type RegionConstraint<'tcx> = ir::RegionConstraint<TyCtxt<'tcx>>;
30pub type PolyTraitClause<'tcx> = ty::Binder<'tcx, TraitClause<'tcx>>;
31pub type PolyRegionOutlivesClause<'tcx> = ty::Binder<'tcx, RegionOutlivesClause<'tcx>>;
32pub type PolyTypeOutlivesClause<'tcx> = ty::Binder<'tcx, TypeOutlivesClause<'tcx>>;
33pub type PolySubtypePredicate<'tcx> = ty::Binder<'tcx, SubtypePredicate<'tcx>>;
34pub type PolyCoercePredicate<'tcx> = ty::Binder<'tcx, CoercePredicate<'tcx>>;
35pub type PolyProjectionClause<'tcx> = ty::Binder<'tcx, ProjectionClause<'tcx>>;
36
37#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for Predicate<'tcx> { }
#[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::marker::StructuralPartialEq for Predicate<'tcx> { }
#[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> ::rustc_data_structures::stable_hash::StableHash for
Predicate<'tcx> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
Predicate(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
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(TraitClause { trait_ref, polarity })) => {
88 Some(PredicateKind::Clause(ClauseKind::Trait(TraitClause {
89 trait_ref,
90 polarity: polarity.flip(),
91 })))
92 }
93
94 _ => None,
95 })
96 .transpose()?;
97
98 Some(tcx.mk_predicate(kind))
99 }
100
101 #[inline]
107 pub fn allow_normalization(self) -> bool {
108 rustc_type_ir::inherent::Predicate::allow_normalization(self)
109 }
110}
111
112impl<'tcx> rustc_errors::IntoDiagArg for Predicate<'tcx> {
113 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
114 ty::tls::with(|tcx| {
115 let pred = tcx.short_string(tcx.lift(self), path);
116 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(pred))
117 })
118 }
119}
120
121impl<'tcx> rustc_errors::IntoDiagArg for Clause<'tcx> {
122 fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> rustc_errors::DiagArgValue {
123 ty::tls::with(|tcx| {
124 let clause = tcx.short_string(tcx.lift(self), path);
125 rustc_errors::DiagArgValue::Str(std::borrow::Cow::Owned(clause))
126 })
127 }
128}
129
130#[derive(#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for Clause<'tcx> { }
#[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::marker::StructuralPartialEq for Clause<'tcx> { }
#[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> ::rustc_data_structures::stable_hash::StableHash for
Clause<'tcx> {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
Clause(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};StableHash)]
134#[rustc_pass_by_value]
135pub struct Clause<'tcx>(
136 pub(super) Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>,
137);
138
139impl<'tcx> rustc_type_ir::inherent::Clause<TyCtxt<'tcx>> for Clause<'tcx> {
140 fn as_predicate(self) -> Predicate<'tcx> {
141 self.as_predicate()
142 }
143
144 fn instantiate_supertrait(self, tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>) -> Self {
145 self.instantiate_supertrait(tcx, trait_ref)
146 }
147}
148
149impl<'tcx> rustc_type_ir::inherent::IntoKind for Clause<'tcx> {
150 type Kind = ty::Binder<'tcx, ClauseKind<'tcx>>;
151
152 fn kind(self) -> Self::Kind {
153 self.kind()
154 }
155}
156
157impl<'tcx> rustc_type_ir::Flags for Clause<'tcx> {
158 fn flags(&self) -> TypeFlags {
159 self.0.flags
160 }
161
162 fn outer_exclusive_binder(&self) -> ty::DebruijnIndex {
163 self.0.outer_exclusive_binder
164 }
165}
166
167impl<'tcx> Clause<'tcx> {
168 pub fn as_predicate(self) -> Predicate<'tcx> {
169 Predicate(self.0)
170 }
171
172 pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> {
173 self.0.internee.map_bound(|kind| match kind {
174 PredicateKind::Clause(clause) => clause,
175 _ => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
176 })
177 }
178
179 pub fn as_trait_clause(self) -> Option<ty::Binder<'tcx, TraitClause<'tcx>>> {
180 let clause = self.kind();
181 if let ty::ClauseKind::Trait(trait_clause) = clause.skip_binder() {
182 Some(clause.rebind(trait_clause))
183 } else {
184 None
185 }
186 }
187
188 pub fn as_projection_clause(self) -> Option<ty::Binder<'tcx, ProjectionClause<'tcx>>> {
189 let clause = self.kind();
190 if let ty::ClauseKind::Projection(projection_clause) = clause.skip_binder() {
191 Some(clause.rebind(projection_clause))
192 } else {
193 None
194 }
195 }
196
197 pub fn as_type_outlives_clause(self) -> Option<ty::Binder<'tcx, TypeOutlivesClause<'tcx>>> {
198 let clause = self.kind();
199 if let ty::ClauseKind::TypeOutlives(o) = clause.skip_binder() {
200 Some(clause.rebind(o))
201 } else {
202 None
203 }
204 }
205
206 pub fn as_region_outlives_clause(self) -> Option<ty::Binder<'tcx, RegionOutlivesClause<'tcx>>> {
207 let clause = self.kind();
208 if let ty::ClauseKind::RegionOutlives(o) = clause.skip_binder() {
209 Some(clause.rebind(o))
210 } else {
211 None
212 }
213 }
214}
215
216impl<'tcx> rustc_type_ir::inherent::Clauses<TyCtxt<'tcx>> for ty::Clauses<'tcx> {}
217
218pub trait ExistentialPredicateStableCmpExt<'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;
}
impl<'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>)]
219impl<'tcx> ExistentialPredicate<'tcx> {
220 fn stable_cmp(&self, tcx: TyCtxt<'tcx>, other: &Self) -> Ordering {
223 match (*self, *other) {
224 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
225 (ExistentialPredicate::Projection(ref a), ExistentialPredicate::Projection(ref b)) => {
226 tcx.def_path_hash(a.def_id).cmp(&tcx.def_path_hash(b.def_id))
227 }
228 (ExistentialPredicate::AutoTrait(ref a), ExistentialPredicate::AutoTrait(ref b)) => {
229 tcx.def_path_hash(*a).cmp(&tcx.def_path_hash(*b))
230 }
231 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
232 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => {
233 Ordering::Greater
234 }
235 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
236 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
237 }
238 }
239}
240
241pub type PolyExistentialPredicate<'tcx> = ty::Binder<'tcx, ExistentialPredicate<'tcx>>;
242
243impl<'tcx> rustc_type_ir::inherent::BoundExistentialPredicates<TyCtxt<'tcx>>
244 for &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>
245{
246 fn principal_def_id(self) -> Option<DefId> {
247 self.principal_def_id()
248 }
249
250 fn principal(self) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
251 self.principal()
252 }
253
254 fn auto_traits(self) -> impl IntoIterator<Item = DefId> {
255 self.auto_traits()
256 }
257
258 fn projection_bounds(
259 self,
260 ) -> impl IntoIterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
261 self.projection_bounds()
262 }
263}
264
265impl<'tcx> ty::List<ty::PolyExistentialPredicate<'tcx>> {
266 pub fn principal(&self) -> Option<ty::Binder<'tcx, ExistentialTraitRef<'tcx>>> {
292 self[0]
293 .map_bound(|this| match this {
294 ExistentialPredicate::Trait(tr) => Some(tr),
295 _ => None,
296 })
297 .transpose()
298 }
299
300 pub fn principal_def_id(&self) -> Option<DefId> {
301 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
302 }
303
304 #[inline]
305 pub fn projection_bounds(
306 &self,
307 ) -> impl Iterator<Item = ty::Binder<'tcx, ExistentialProjection<'tcx>>> {
308 self.iter().filter_map(|predicate| {
309 predicate
310 .map_bound(|pred| match pred {
311 ExistentialPredicate::Projection(projection) => Some(projection),
312 _ => None,
313 })
314 .transpose()
315 })
316 }
317
318 #[inline]
319 pub fn auto_traits(&self) -> impl Iterator<Item = DefId> {
320 self.iter().filter_map(|predicate| match predicate.skip_binder() {
321 ExistentialPredicate::AutoTrait(did) => Some(did),
322 _ => None,
323 })
324 }
325
326 pub fn without_auto_traits(&self) -> impl Iterator<Item = ty::PolyExistentialPredicate<'tcx>> {
327 self.iter().filter(|predicate| {
328 !#[allow(non_exhaustive_omitted_patterns)] match predicate.as_ref().skip_binder()
{
ExistentialPredicate::AutoTrait(_) => true,
_ => false,
}matches!(predicate.as_ref().skip_binder(), ExistentialPredicate::AutoTrait(_))
329 })
330 }
331}
332
333pub type PolyTraitRef<'tcx> = ty::Binder<'tcx, TraitRef<'tcx>>;
334pub type PolyExistentialTraitRef<'tcx> = ty::Binder<'tcx, ExistentialTraitRef<'tcx>>;
335pub type PolyExistentialProjection<'tcx> = ty::Binder<'tcx, ExistentialProjection<'tcx>>;
336
337impl<'tcx> Clause<'tcx> {
338 pub fn instantiate_supertrait(
344 self,
345 tcx: TyCtxt<'tcx>,
346 trait_ref: ty::PolyTraitRef<'tcx>,
347 ) -> Clause<'tcx> {
348 let bound_pred = self.kind();
423 let pred_bound_vars = bound_pred.bound_vars();
424 let trait_bound_vars = trait_ref.bound_vars();
425 let shifted_pred =
427 tcx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
428 let new = EarlyBinder::bind(tcx, shifted_pred)
430 .instantiate(tcx, trait_ref.skip_binder().args)
431 .skip_norm_wip();
432 let bound_vars =
434 tcx.mk_bound_variable_kinds_from_iter(trait_bound_vars.iter().chain(pred_bound_vars));
435
436 tcx.reuse_or_mk_predicate(
438 self.as_predicate(),
439 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars),
440 )
441 .expect_clause()
442 }
443}
444
445impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PredicateKind<'tcx>> for Predicate<'tcx> {
446 fn upcast_from(from: PredicateKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
447 ty::Binder::dummy(from).upcast(tcx)
448 }
449}
450
451impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, PredicateKind<'tcx>>> for Predicate<'tcx> {
452 fn upcast_from(from: ty::Binder<'tcx, PredicateKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
453 tcx.mk_predicate(from)
454 }
455}
456
457impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Predicate<'tcx> {
458 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
459 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from)))
460 }
461}
462
463impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Predicate<'tcx> {
464 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
465 tcx.mk_predicate(from.map_bound(PredicateKind::Clause))
466 }
467}
468
469impl<'tcx> UpcastFrom<TyCtxt<'tcx>, Clause<'tcx>> for Predicate<'tcx> {
470 fn upcast_from(from: Clause<'tcx>, _tcx: TyCtxt<'tcx>) -> Self {
471 from.as_predicate()
472 }
473}
474
475impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ClauseKind<'tcx>> for Clause<'tcx> {
476 fn upcast_from(from: ClauseKind<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
477 tcx.mk_predicate(ty::Binder::dummy(PredicateKind::Clause(from))).expect_clause()
478 }
479}
480
481impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ClauseKind<'tcx>>> for Clause<'tcx> {
482 fn upcast_from(from: ty::Binder<'tcx, ClauseKind<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
483 tcx.mk_predicate(from.map_bound(|clause| PredicateKind::Clause(clause))).expect_clause()
484 }
485}
486
487impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Predicate<'tcx> {
488 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
489 ty::Binder::dummy(from).upcast(tcx)
490 }
491}
492
493impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitRef<'tcx>> for Clause<'tcx> {
494 fn upcast_from(from: TraitRef<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
495 let p: Predicate<'tcx> = from.upcast(tcx);
496 p.expect_clause()
497 }
498}
499
500impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Predicate<'tcx> {
501 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
502 let pred: PolyTraitClause<'tcx> = from.upcast(tcx);
503 pred.upcast(tcx)
504 }
505}
506
507impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, TraitRef<'tcx>>> for Clause<'tcx> {
508 fn upcast_from(from: ty::Binder<'tcx, TraitRef<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
509 let pred: PolyTraitClause<'tcx> = from.upcast(tcx);
510 pred.upcast(tcx)
511 }
512}
513
514impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitClause<'tcx>> for Predicate<'tcx> {
515 fn upcast_from(from: TraitClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
516 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(tcx)
517 }
518}
519
520impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyTraitClause<'tcx>> for Predicate<'tcx> {
521 fn upcast_from(from: PolyTraitClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
522 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx)
523 }
524}
525
526impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TraitClause<'tcx>> for Clause<'tcx> {
527 fn upcast_from(from: TraitClause<'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>, PolyTraitClause<'tcx>> for Clause<'tcx> {
534 fn upcast_from(from: PolyTraitClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
535 let p: Predicate<'tcx> = from.upcast(tcx);
536 p.expect_clause()
537 }
538}
539
540impl<'tcx> UpcastFrom<TyCtxt<'tcx>, RegionOutlivesClause<'tcx>> for Predicate<'tcx> {
541 fn upcast_from(from: RegionOutlivesClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
542 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::RegionOutlives(from))).upcast(tcx)
543 }
544}
545
546impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyRegionOutlivesClause<'tcx>> for Predicate<'tcx> {
547 fn upcast_from(from: PolyRegionOutlivesClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
548 from.map_bound(|c| PredicateKind::Clause(ClauseKind::RegionOutlives(c))).upcast(tcx)
549 }
550}
551
552impl<'tcx> UpcastFrom<TyCtxt<'tcx>, TypeOutlivesClause<'tcx>> for Predicate<'tcx> {
553 fn upcast_from(from: TypeOutlivesClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
554 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::TypeOutlives(from))).upcast(tcx)
555 }
556}
557
558impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionClause<'tcx>> for Predicate<'tcx> {
559 fn upcast_from(from: ProjectionClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
560 ty::Binder::dummy(PredicateKind::Clause(ClauseKind::Projection(from))).upcast(tcx)
561 }
562}
563
564impl<'tcx> UpcastFrom<TyCtxt<'tcx>, PolyProjectionClause<'tcx>> for Predicate<'tcx> {
565 fn upcast_from(from: PolyProjectionClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
566 from.map_bound(|p| PredicateKind::Clause(ClauseKind::Projection(p))).upcast(tcx)
567 }
568}
569
570impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ProjectionClause<'tcx>> for Clause<'tcx> {
571 fn upcast_from(from: ProjectionClause<'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>, PolyProjectionClause<'tcx>> for Clause<'tcx> {
578 fn upcast_from(from: PolyProjectionClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
579 let p: Predicate<'tcx> = from.upcast(tcx);
580 p.expect_clause()
581 }
582}
583
584impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectClause<'tcx>>>
585 for Predicate<'tcx>
586{
587 fn upcast_from(from: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
588 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
589 }
590}
591
592impl<'tcx> UpcastFrom<TyCtxt<'tcx>, ty::Binder<'tcx, ty::HostEffectClause<'tcx>>> for Clause<'tcx> {
593 fn upcast_from(from: ty::Binder<'tcx, ty::HostEffectClause<'tcx>>, tcx: TyCtxt<'tcx>) -> Self {
594 from.map_bound(ty::ClauseKind::HostEffect).upcast(tcx)
595 }
596}
597
598impl<'tcx> UpcastFrom<TyCtxt<'tcx>, NormalizesTo<'tcx>> for Predicate<'tcx> {
599 fn upcast_from(from: NormalizesTo<'tcx>, tcx: TyCtxt<'tcx>) -> Self {
600 PredicateKind::NormalizesTo(from).upcast(tcx)
601 }
602}
603
604impl<'tcx> Predicate<'tcx> {
605 pub fn as_trait_clause(self) -> Option<PolyTraitClause<'tcx>> {
606 let predicate = self.kind();
607 match predicate.skip_binder() {
608 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
609 _ => None,
610 }
611 }
612
613 pub fn as_projection_clause(self) -> Option<PolyProjectionClause<'tcx>> {
614 let predicate = self.kind();
615 match predicate.skip_binder() {
616 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
617 _ => None,
618 }
619 }
620
621 pub fn as_clause(self) -> Option<Clause<'tcx>> {
623 match self.kind().skip_binder() {
624 PredicateKind::Clause(..) => Some(self.expect_clause()),
625 _ => None,
626 }
627 }
628
629 pub fn expect_clause(self) -> Clause<'tcx> {
631 match self.kind().skip_binder() {
632 PredicateKind::Clause(..) => Clause(self.0),
633 _ => crate::util::bug::bug_fmt(format_args!("{0} is not a clause", self))bug!("{self} is not a clause"),
634 }
635 }
636}
637
638#[cfg(target_pointer_width = "64")]
640mod size_asserts {
641 use rustc_data_structures::static_assert_size;
642
643 use super::*;
644 const _: [(); 40] = [(); ::std::mem::size_of::<PredicateKind<'_>>()];static_assert_size!(PredicateKind<'_>, 40);
646 const _: [(); 48] =
[(); ::std::mem::size_of::<WithCachedTypeInfo<PredicateKind<'_>>>()];static_assert_size!(WithCachedTypeInfo<PredicateKind<'_>>, 48);
647 }