1use std::cmp::Ordering;
4
5use intern::{
6 Interned, InternedRef, InternedSlice, InternedSliceRef, impl_internable, impl_slice_internable,
7};
8use macros::{GenericTypeVisitable, TypeFoldable, TypeVisitable};
9use rustc_type_ir::{
10 self as ty, CollectAndApply, EarlyBinder, FlagComputation, Flags, GenericTypeVisitable,
11 PredicatePolarity, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, Upcast,
12 UpcastFrom, WithCachedTypeInfo,
13 elaborate::Elaboratable,
14 error::{ExpectedFound, TypeError},
15 inherent::{IntoKind, SliceLike},
16};
17
18use crate::next_solver::{
19 GenericArg, TraitIdWrapper, default_types, impl_foldable_for_interned_slice,
20 impl_stored_interned_slice, interned_slice,
21};
22
23use super::{Binder, BoundVarKinds, DbInterner, Region, Ty};
24
25pub type BoundExistentialPredicate<'db> = Binder<'db, ExistentialPredicate<'db>>;
26
27pub type TraitRef<'db> = ty::TraitRef<DbInterner<'db>>;
28pub type AliasTerm<'db> = ty::AliasTerm<DbInterner<'db>>;
29pub type ProjectionPredicate<'db> = ty::ProjectionPredicate<DbInterner<'db>>;
30pub type ExistentialPredicate<'db> = ty::ExistentialPredicate<DbInterner<'db>>;
31pub type ExistentialTraitRef<'db> = ty::ExistentialTraitRef<DbInterner<'db>>;
32pub type ExistentialProjection<'db> = ty::ExistentialProjection<DbInterner<'db>>;
33pub type TraitPredicate<'db> = ty::TraitPredicate<DbInterner<'db>>;
34pub type HostEffectPredicate<'db> = ty::HostEffectPredicate<DbInterner<'db>>;
35pub type ClauseKind<'db> = ty::ClauseKind<DbInterner<'db>>;
36pub type PredicateKind<'db> = ty::PredicateKind<DbInterner<'db>>;
37pub type NormalizesTo<'db> = ty::NormalizesTo<DbInterner<'db>>;
38pub type CoercePredicate<'db> = ty::CoercePredicate<DbInterner<'db>>;
39pub type SubtypePredicate<'db> = ty::SubtypePredicate<DbInterner<'db>>;
40pub type OutlivesPredicate<'db, T> = ty::OutlivesPredicate<DbInterner<'db>, T>;
41pub type RegionOutlivesPredicate<'db> = OutlivesPredicate<'db, Region<'db>>;
42pub type TypeOutlivesPredicate<'db> = OutlivesPredicate<'db, Ty<'db>>;
43pub type PolyTraitPredicate<'db> = Binder<'db, TraitPredicate<'db>>;
44pub type PolyRegionOutlivesPredicate<'db> = Binder<'db, RegionOutlivesPredicate<'db>>;
45pub type PolyTypeOutlivesPredicate<'db> = Binder<'db, TypeOutlivesPredicate<'db>>;
46pub type PolySubtypePredicate<'db> = Binder<'db, SubtypePredicate<'db>>;
47pub type PolyCoercePredicate<'db> = Binder<'db, CoercePredicate<'db>>;
48pub type PolyProjectionPredicate<'db> = Binder<'db, ProjectionPredicate<'db>>;
49pub type PolyTraitRef<'db> = Binder<'db, TraitRef<'db>>;
50pub type PolyExistentialTraitRef<'db> = Binder<'db, ExistentialTraitRef<'db>>;
51pub type PolyExistentialProjection<'db> = Binder<'db, ExistentialProjection<'db>>;
52pub type ArgOutlivesPredicate<'db> = OutlivesPredicate<'db, GenericArg<'db>>;
53
54fn stable_cmp_existential_predicate<'db>(
57 a: &ExistentialPredicate<'db>,
58 b: &ExistentialPredicate<'db>,
59) -> Ordering {
60 match (a, b) {
62 (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
63 (ExistentialPredicate::Projection(_a), ExistentialPredicate::Projection(_b)) => {
64 Ordering::Equal
66 }
67 (ExistentialPredicate::AutoTrait(_a), ExistentialPredicate::AutoTrait(_b)) => {
68 Ordering::Equal
70 }
71 (ExistentialPredicate::Trait(_), _) => Ordering::Less,
72 (ExistentialPredicate::Projection(_), ExistentialPredicate::Trait(_)) => Ordering::Greater,
73 (ExistentialPredicate::Projection(_), _) => Ordering::Less,
74 (ExistentialPredicate::AutoTrait(_), _) => Ordering::Greater,
75 }
76}
77interned_slice!(
78 BoundExistentialPredicatesStorage,
79 BoundExistentialPredicates,
80 StoredBoundExistentialPredicates,
81 bound_existential_predicates,
82 BoundExistentialPredicate<'db>,
83 BoundExistentialPredicate<'static>,
84);
85impl_foldable_for_interned_slice!(BoundExistentialPredicates);
86
87impl<'db> rustc_type_ir::inherent::BoundExistentialPredicates<DbInterner<'db>>
88 for BoundExistentialPredicates<'db>
89{
90 fn principal_def_id(self) -> Option<TraitIdWrapper> {
91 self.principal().map(|trait_ref| trait_ref.skip_binder().def_id)
92 }
93
94 fn principal(
95 self,
96 ) -> Option<
97 rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::ExistentialTraitRef<DbInterner<'db>>>,
98 > {
99 self[0]
100 .map_bound(|this| match this {
101 ExistentialPredicate::Trait(tr) => Some(tr),
102 _ => None,
103 })
104 .transpose()
105 }
106
107 fn auto_traits(self) -> impl IntoIterator<Item = TraitIdWrapper> {
108 self.iter().filter_map(|predicate| match predicate.skip_binder() {
109 ExistentialPredicate::AutoTrait(did) => Some(did),
110 _ => None,
111 })
112 }
113
114 fn projection_bounds(
115 self,
116 ) -> impl IntoIterator<
117 Item = rustc_type_ir::Binder<
118 DbInterner<'db>,
119 rustc_type_ir::ExistentialProjection<DbInterner<'db>>,
120 >,
121 > {
122 self.iter().filter_map(|predicate| {
123 predicate
124 .map_bound(|pred| match pred {
125 ExistentialPredicate::Projection(projection) => Some(projection),
126 _ => None,
127 })
128 .transpose()
129 })
130 }
131}
132
133impl<'db> rustc_type_ir::relate::Relate<DbInterner<'db>> for BoundExistentialPredicates<'db> {
134 fn relate<R: rustc_type_ir::relate::TypeRelation<DbInterner<'db>>>(
135 relation: &mut R,
136 a: Self,
137 b: Self,
138 ) -> rustc_type_ir::relate::RelateResult<DbInterner<'db>, Self> {
139 let mut a_v: Vec<_> = a.into_iter().collect();
141 let mut b_v: Vec<_> = b.into_iter().collect();
142 a_v.sort_by(|a, b| {
144 stable_cmp_existential_predicate(a.as_ref().skip_binder(), b.as_ref().skip_binder())
145 });
146 a_v.dedup();
147 b_v.sort_by(|a, b| {
148 stable_cmp_existential_predicate(a.as_ref().skip_binder(), b.as_ref().skip_binder())
149 });
150 b_v.dedup();
151 if a_v.len() != b_v.len() {
152 return Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b)));
153 }
154
155 let v = std::iter::zip(a_v, b_v).map(
156 |(ep_a, ep_b): (
157 Binder<'_, ty::ExistentialPredicate<_>>,
158 Binder<'_, ty::ExistentialPredicate<_>>,
159 )| {
160 match (ep_a.skip_binder(), ep_b.skip_binder()) {
161 (ty::ExistentialPredicate::Trait(a), ty::ExistentialPredicate::Trait(b)) => {
162 Ok(ep_a.rebind(ty::ExistentialPredicate::Trait(
163 relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
164 )))
165 }
166 (
167 ty::ExistentialPredicate::Projection(a),
168 ty::ExistentialPredicate::Projection(b),
169 ) => Ok(ep_a.rebind(ty::ExistentialPredicate::Projection(
170 relation.relate(ep_a.rebind(a), ep_b.rebind(b))?.skip_binder(),
171 ))),
172 (
173 ty::ExistentialPredicate::AutoTrait(a),
174 ty::ExistentialPredicate::AutoTrait(b),
175 ) if a == b => Ok(ep_a.rebind(ty::ExistentialPredicate::AutoTrait(a))),
176 _ => Err(TypeError::ExistentialMismatch(ExpectedFound::new(a, b))),
177 }
178 },
179 );
180
181 BoundExistentialPredicates::new_from_iter(v)
182 }
183}
184
185#[derive(Clone, Copy, PartialEq, Eq, Hash)]
186pub struct Predicate<'db> {
187 interned: InternedRef<'db, PredicateInterned>,
188}
189
190#[derive(PartialEq, Eq, Hash, GenericTypeVisitable)]
191pub(super) struct PredicateInterned(WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>);
192
193impl_internable!(gc; PredicateInterned);
194
195const _: () = {
196 const fn is_copy<T: Copy>() {}
197 is_copy::<Predicate<'static>>();
198};
199
200impl<'db> Predicate<'db> {
201 pub fn new(_interner: DbInterner<'db>, kind: Binder<'db, PredicateKind<'db>>) -> Self {
202 let kind = unsafe {
203 std::mem::transmute::<
204 Binder<'db, PredicateKind<'db>>,
205 Binder<'static, PredicateKind<'static>>,
206 >(kind)
207 };
208 let flags = FlagComputation::for_predicate(kind);
209 let cached = WithCachedTypeInfo {
210 internee: kind,
211 flags: flags.flags,
212 outer_exclusive_binder: flags.outer_exclusive_binder,
213 };
214 Self { interned: Interned::new_gc(PredicateInterned(cached)) }
215 }
216
217 pub fn inner(&self) -> &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>> {
218 let inner = &self.interned.0;
219 unsafe {
220 std::mem::transmute::<
221 &WithCachedTypeInfo<Binder<'static, PredicateKind<'static>>>,
222 &WithCachedTypeInfo<Binder<'db, PredicateKind<'db>>>,
223 >(inner)
224 }
225 }
226
227 pub fn flip_polarity(self, interner: DbInterner<'db>) -> Option<Predicate<'db>> {
231 let kind = self
232 .kind()
233 .map_bound(|kind| match kind {
234 PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
235 trait_ref,
236 polarity,
237 })) => Some(PredicateKind::Clause(ClauseKind::Trait(TraitPredicate {
238 trait_ref,
239 polarity: polarity.flip(),
240 }))),
241
242 _ => None,
243 })
244 .transpose()?;
245
246 Some(Predicate::new(interner, kind))
247 }
248}
249
250impl<'db> std::fmt::Debug for Predicate<'db> {
251 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
252 self.kind().fmt(f)
253 }
254}
255
256#[derive(Clone, Copy, PartialEq, Eq, Hash, GenericTypeVisitable)]
257pub struct ClausesCachedTypeInfo(WithCachedTypeInfo<()>);
258
259impl_slice_internable!(gc; ClausesStorage, ClausesCachedTypeInfo, Clause<'static>);
260impl_stored_interned_slice!(ClausesStorage, Clauses, StoredClauses);
261
262#[derive(Clone, Copy, PartialEq, Eq, Hash)]
263pub struct Clauses<'db> {
264 interned: InternedSliceRef<'db, ClausesStorage>,
265}
266
267impl<'db> std::fmt::Debug for Clauses<'db> {
268 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
269 self.as_slice().fmt(fmt)
270 }
271}
272
273impl<'db> Clauses<'db> {
274 #[inline]
275 pub fn empty() -> Self {
276 default_types().empty.clauses
277 }
278
279 #[inline]
280 pub fn new_from_slice(slice: &[Clause<'db>]) -> Self {
281 if slice.is_empty() {
282 Self::empty()
284 } else {
285 Self::new_from_slice_no_empty_check(slice)
286 }
287 }
288
289 #[inline]
292 pub(crate) fn new_from_slice_no_empty_check(slice: &[Clause<'db>]) -> Self {
293 let slice = unsafe { ::std::mem::transmute::<&[Clause<'db>], &[Clause<'static>]>(slice) };
294 let flags = FlagComputation::<DbInterner<'db>>::for_clauses(slice);
295 let flags = ClausesCachedTypeInfo(WithCachedTypeInfo {
296 internee: (),
297 flags: flags.flags,
298 outer_exclusive_binder: flags.outer_exclusive_binder,
299 });
300 Self { interned: InternedSlice::from_header_and_slice(flags, slice) }
301 }
302
303 #[inline]
304 pub fn new_from_iter<I, T>(args: I) -> T::Output
305 where
306 I: IntoIterator<Item = T>,
307 T: CollectAndApply<Clause<'db>, Self>,
308 {
309 CollectAndApply::collect_and_apply(args.into_iter(), Self::new_from_slice)
310 }
311
312 #[inline]
313 pub fn as_slice(self) -> &'db [Clause<'db>] {
314 let slice = &self.interned.get().slice;
315 unsafe { ::std::mem::transmute::<&[Clause<'static>], &[Clause<'db>]>(slice) }
316 }
317
318 #[inline]
319 pub fn iter(self) -> ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>> {
320 self.as_slice().iter().copied()
321 }
322
323 #[inline]
324 pub fn len(self) -> usize {
325 self.as_slice().len()
326 }
327
328 #[inline]
329 pub fn is_empty(self) -> bool {
330 self.as_slice().is_empty()
331 }
332}
333
334impl Default for Clauses<'_> {
335 #[inline]
336 fn default() -> Self {
337 Self::empty()
338 }
339}
340
341impl<'db> IntoIterator for Clauses<'db> {
342 type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>;
343 type Item = Clause<'db>;
344 #[inline]
345 fn into_iter(self) -> Self::IntoIter {
346 self.iter()
347 }
348}
349
350impl<'db> std::ops::Deref for Clauses<'db> {
351 type Target = [Clause<'db>];
352
353 #[inline]
354 fn deref(&self) -> &Self::Target {
355 (*self).as_slice()
356 }
357}
358
359impl<'db> rustc_type_ir::inherent::SliceLike for Clauses<'db> {
360 type Item = Clause<'db>;
361
362 type IntoIter = ::std::iter::Copied<::std::slice::Iter<'db, Clause<'db>>>;
363
364 #[inline]
365 fn iter(self) -> Self::IntoIter {
366 self.iter()
367 }
368
369 #[inline]
370 fn as_slice(&self) -> &[Self::Item] {
371 (*self).as_slice()
372 }
373}
374
375impl<'db> rustc_type_ir::inherent::Clauses<DbInterner<'db>> for Clauses<'db> {}
376
377impl<'db> rustc_type_ir::TypeSuperFoldable<DbInterner<'db>> for Clauses<'db> {
378 fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
379 self,
380 folder: &mut F,
381 ) -> Result<Self, F::Error> {
382 Clauses::new_from_iter(self.iter().map(|clause| clause.try_fold_with(folder)))
383 }
384
385 fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
386 self,
387 folder: &mut F,
388 ) -> Self {
389 Clauses::new_from_iter(self.iter().map(|clause| clause.fold_with(folder)))
390 }
391}
392
393impl<'db> rustc_type_ir::TypeFoldable<DbInterner<'db>> for Clauses<'db> {
394 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
395 self,
396 folder: &mut F,
397 ) -> Result<Self, F::Error> {
398 self.try_super_fold_with(folder)
399 }
400 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
401 self.super_fold_with(folder)
402 }
403}
404
405impl<'db> rustc_type_ir::TypeVisitable<DbInterner<'db>> for Clauses<'db> {
406 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
407 &self,
408 visitor: &mut V,
409 ) -> V::Result {
410 use rustc_ast_ir::visit::VisitorResult;
411 rustc_ast_ir::walk_visitable_list!(visitor, self.iter());
412 V::Result::output()
413 }
414}
415
416impl<'db, V: super::WorldExposer> rustc_type_ir::GenericTypeVisitable<V> for Clauses<'db> {
417 fn generic_visit_with(&self, visitor: &mut V) {
418 if visitor.on_interned_slice(self.interned).is_continue() {
419 self.as_slice().iter().for_each(|it| it.generic_visit_with(visitor));
420 }
421 }
422}
423
424impl<'db> rustc_type_ir::Flags for Clauses<'db> {
425 #[inline]
426 fn flags(&self) -> rustc_type_ir::TypeFlags {
427 self.interned.header.header.0.flags
428 }
429
430 #[inline]
431 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
432 self.interned.header.header.0.outer_exclusive_binder
433 }
434}
435
436impl<'db> rustc_type_ir::TypeSuperVisitable<DbInterner<'db>> for Clauses<'db> {
437 fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
438 &self,
439 visitor: &mut V,
440 ) -> V::Result {
441 self.as_slice().visit_with(visitor)
442 }
443}
444
445#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, GenericTypeVisitable)] pub struct Clause<'db>(pub(crate) Predicate<'db>);
447
448#[derive(
450 Copy, Clone, Debug, Hash, PartialEq, Eq, TypeVisitable, TypeFoldable, GenericTypeVisitable,
451)]
452pub struct ParamEnv<'db> {
453 pub(crate) clauses: Clauses<'db>,
454}
455
456impl<'db> ParamEnv<'db> {
457 #[inline]
458 pub fn empty() -> Self {
459 ParamEnv { clauses: Clauses::empty() }
460 }
461
462 pub fn clauses(self) -> Clauses<'db> {
463 self.clauses
464 }
465}
466
467impl<'db> rustc_type_ir::inherent::ParamEnv<DbInterner<'db>> for ParamEnv<'db> {
468 fn caller_bounds(self) -> impl rustc_type_ir::inherent::SliceLike<Item = Clause<'db>> {
469 self.clauses
470 }
471}
472
473#[derive(Clone, Debug, PartialEq, Eq, Hash)]
474pub struct ParamEnvAnd<'db, T> {
475 pub param_env: ParamEnv<'db>,
476 pub value: T,
477}
478
479impl<'db, T> ParamEnvAnd<'db, T> {
480 pub fn into_parts(self) -> (ParamEnv<'db>, T) {
481 (self.param_env, self.value)
482 }
483}
484
485impl<'db> TypeVisitable<DbInterner<'db>> for Predicate<'db> {
486 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
487 &self,
488 visitor: &mut V,
489 ) -> V::Result {
490 visitor.visit_predicate(*self)
491 }
492}
493
494impl<'db, V: super::WorldExposer> GenericTypeVisitable<V> for Predicate<'db> {
495 fn generic_visit_with(&self, visitor: &mut V) {
496 if visitor.on_interned(self.interned).is_continue() {
497 self.kind().generic_visit_with(visitor);
498 }
499 }
500}
501
502impl<'db> TypeSuperVisitable<DbInterner<'db>> for Predicate<'db> {
503 fn super_visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
504 &self,
505 visitor: &mut V,
506 ) -> V::Result {
507 (*self).kind().visit_with(visitor)
508 }
509}
510
511impl<'db> TypeFoldable<DbInterner<'db>> for Predicate<'db> {
512 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
513 self,
514 folder: &mut F,
515 ) -> Result<Self, F::Error> {
516 folder.try_fold_predicate(self)
517 }
518 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
519 folder.fold_predicate(self)
520 }
521}
522
523impl<'db> TypeSuperFoldable<DbInterner<'db>> for Predicate<'db> {
524 fn try_super_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
525 self,
526 folder: &mut F,
527 ) -> Result<Self, F::Error> {
528 let new = self.kind().try_fold_with(folder)?;
529 Ok(Predicate::new(folder.cx(), new))
530 }
531 fn super_fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(
532 self,
533 folder: &mut F,
534 ) -> Self {
535 let new = self.kind().fold_with(folder);
536 Predicate::new(folder.cx(), new)
537 }
538}
539
540impl<'db> Elaboratable<DbInterner<'db>> for Predicate<'db> {
541 fn predicate(&self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
542 *self
543 }
544
545 fn child(&self, clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause) -> Self {
546 clause.as_predicate()
547 }
548
549 fn child_with_derived_cause(
550 &self,
551 clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause,
552 _span: <DbInterner<'db> as rustc_type_ir::Interner>::Span,
553 _parent_trait_pred: rustc_type_ir::Binder<
554 DbInterner<'db>,
555 rustc_type_ir::TraitPredicate<DbInterner<'db>>,
556 >,
557 _index: usize,
558 ) -> Self {
559 clause.as_predicate()
560 }
561}
562
563impl<'db> Flags for Predicate<'db> {
564 fn flags(&self) -> rustc_type_ir::TypeFlags {
565 self.inner().flags
566 }
567
568 fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex {
569 self.inner().outer_exclusive_binder
570 }
571}
572
573impl<'db> IntoKind for Predicate<'db> {
574 type Kind = Binder<'db, PredicateKind<'db>>;
575
576 fn kind(self) -> Self::Kind {
577 self.inner().internee
578 }
579}
580
581impl<'db> UpcastFrom<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>> for Predicate<'db> {
582 fn upcast_from(from: ty::PredicateKind<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
583 Binder::dummy(from).upcast(interner)
584 }
585}
586impl<'db>
587 UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>>>
588 for Predicate<'db>
589{
590 fn upcast_from(
591 from: ty::Binder<DbInterner<'db>, ty::PredicateKind<DbInterner<'db>>>,
592 interner: DbInterner<'db>,
593 ) -> Self {
594 Predicate::new(interner, from)
595 }
596}
597impl<'db> UpcastFrom<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>> for Predicate<'db> {
598 fn upcast_from(from: ty::ClauseKind<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
599 Binder::dummy(PredicateKind::Clause(from)).upcast(interner)
600 }
601}
602impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>>
603 for Predicate<'db>
604{
605 fn upcast_from(
606 from: ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>,
607 interner: DbInterner<'db>,
608 ) -> Self {
609 from.map_bound(PredicateKind::Clause).upcast(interner)
610 }
611}
612impl<'db> UpcastFrom<DbInterner<'db>, Clause<'db>> for Predicate<'db> {
613 fn upcast_from(from: Clause<'db>, _interner: DbInterner<'db>) -> Self {
614 from.0
615 }
616}
617impl<'db> UpcastFrom<DbInterner<'db>, ty::NormalizesTo<DbInterner<'db>>> for Predicate<'db> {
618 fn upcast_from(from: ty::NormalizesTo<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
619 PredicateKind::NormalizesTo(from).upcast(interner)
620 }
621}
622impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>> for Predicate<'db> {
623 fn upcast_from(from: ty::TraitRef<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
624 Binder::dummy(from).upcast(interner)
625 }
626}
627impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>>
628 for Predicate<'db>
629{
630 fn upcast_from(
631 from: ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>,
632 interner: DbInterner<'db>,
633 ) -> Self {
634 from.map_bound(|trait_ref| TraitPredicate {
635 trait_ref,
636 polarity: PredicatePolarity::Positive,
637 })
638 .upcast(interner)
639 }
640}
641impl<'db> UpcastFrom<DbInterner<'db>, Binder<'db, ty::TraitPredicate<DbInterner<'db>>>>
642 for Predicate<'db>
643{
644 fn upcast_from(
645 from: Binder<'db, ty::TraitPredicate<DbInterner<'db>>>,
646 interner: DbInterner<'db>,
647 ) -> Self {
648 from.map_bound(|it| PredicateKind::Clause(ClauseKind::Trait(it))).upcast(interner)
649 }
650}
651impl<'db> UpcastFrom<DbInterner<'db>, Binder<'db, ProjectionPredicate<'db>>> for Predicate<'db> {
652 fn upcast_from(from: Binder<'db, ProjectionPredicate<'db>>, interner: DbInterner<'db>) -> Self {
653 from.map_bound(|it| PredicateKind::Clause(ClauseKind::Projection(it))).upcast(interner)
654 }
655}
656impl<'db> UpcastFrom<DbInterner<'db>, ProjectionPredicate<'db>> for Predicate<'db> {
657 fn upcast_from(from: ProjectionPredicate<'db>, interner: DbInterner<'db>) -> Self {
658 PredicateKind::Clause(ClauseKind::Projection(from)).upcast(interner)
659 }
660}
661impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>> for Predicate<'db> {
662 fn upcast_from(from: ty::TraitPredicate<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
663 PredicateKind::Clause(ClauseKind::Trait(from)).upcast(interner)
664 }
665}
666impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>>
667 for Predicate<'db>
668{
669 fn upcast_from(
670 from: ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>,
671 interner: DbInterner<'db>,
672 ) -> Self {
673 PredicateKind::Clause(ClauseKind::TypeOutlives(from)).upcast(interner)
674 }
675}
676impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>>
677 for Predicate<'db>
678{
679 fn upcast_from(
680 from: ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>,
681 interner: DbInterner<'db>,
682 ) -> Self {
683 PredicateKind::Clause(ClauseKind::RegionOutlives(from)).upcast(interner)
684 }
685}
686impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>>
687 for Clause<'db>
688{
689 fn upcast_from(
690 from: ty::OutlivesPredicate<DbInterner<'db>, Ty<'db>>,
691 interner: DbInterner<'db>,
692 ) -> Self {
693 Clause(from.upcast(interner))
694 }
695}
696impl<'db> UpcastFrom<DbInterner<'db>, ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>>
697 for Clause<'db>
698{
699 fn upcast_from(
700 from: ty::OutlivesPredicate<DbInterner<'db>, Region<'db>>,
701 interner: DbInterner<'db>,
702 ) -> Self {
703 Clause(from.upcast(interner))
704 }
705}
706
707impl<'db> UpcastFrom<DbInterner<'db>, PolyRegionOutlivesPredicate<'db>> for Predicate<'db> {
708 fn upcast_from(from: PolyRegionOutlivesPredicate<'db>, tcx: DbInterner<'db>) -> Self {
709 from.map_bound(|p| PredicateKind::Clause(ClauseKind::RegionOutlives(p))).upcast(tcx)
710 }
711}
712
713impl<'db> rustc_type_ir::inherent::Predicate<DbInterner<'db>> for Predicate<'db> {
714 fn as_clause(self) -> Option<<DbInterner<'db> as rustc_type_ir::Interner>::Clause> {
715 match self.kind().skip_binder() {
716 PredicateKind::Clause(..) => Some(self.expect_clause()),
717 _ => None,
718 }
719 }
720}
721
722impl<'db> Predicate<'db> {
723 pub fn as_trait_clause(self) -> Option<PolyTraitPredicate<'db>> {
724 let predicate = self.kind();
725 match predicate.skip_binder() {
726 PredicateKind::Clause(ClauseKind::Trait(t)) => Some(predicate.rebind(t)),
727 _ => None,
728 }
729 }
730
731 pub fn as_projection_clause(self) -> Option<PolyProjectionPredicate<'db>> {
732 let predicate = self.kind();
733 match predicate.skip_binder() {
734 PredicateKind::Clause(ClauseKind::Projection(t)) => Some(predicate.rebind(t)),
735 _ => None,
736 }
737 }
738
739 pub fn as_clause(self) -> Option<Clause<'db>> {
741 match self.kind().skip_binder() {
742 PredicateKind::Clause(..) => Some(self.expect_clause()),
743 _ => None,
744 }
745 }
746
747 pub fn expect_clause(self) -> Clause<'db> {
749 match self.kind().skip_binder() {
750 PredicateKind::Clause(..) => Clause(self),
751 _ => panic!("{self:?} is not a clause"),
752 }
753 }
754}
755
756impl<'db> TypeVisitable<DbInterner<'db>> for Clause<'db> {
757 fn visit_with<V: rustc_type_ir::TypeVisitor<DbInterner<'db>>>(
758 &self,
759 visitor: &mut V,
760 ) -> V::Result {
761 visitor.visit_predicate((*self).as_predicate())
762 }
763}
764
765impl<'db> TypeFoldable<DbInterner<'db>> for Clause<'db> {
766 fn try_fold_with<F: rustc_type_ir::FallibleTypeFolder<DbInterner<'db>>>(
767 self,
768 folder: &mut F,
769 ) -> Result<Self, F::Error> {
770 Ok(folder.try_fold_predicate(self.as_predicate())?.expect_clause())
771 }
772 fn fold_with<F: rustc_type_ir::TypeFolder<DbInterner<'db>>>(self, folder: &mut F) -> Self {
773 folder.fold_predicate(self.as_predicate()).expect_clause()
774 }
775}
776
777impl<'db> IntoKind for Clause<'db> {
778 type Kind = Binder<'db, ClauseKind<'db>>;
779
780 fn kind(self) -> Self::Kind {
781 self.0.kind().map_bound(|pk| match pk {
782 PredicateKind::Clause(kind) => kind,
783 _ => unreachable!(),
784 })
785 }
786}
787
788impl<'db> Clause<'db> {
789 pub fn as_predicate(self) -> Predicate<'db> {
790 self.0
791 }
792}
793
794impl<'db> Elaboratable<DbInterner<'db>> for Clause<'db> {
795 fn predicate(&self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
796 self.0
797 }
798
799 fn child(&self, clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause) -> Self {
800 clause
801 }
802
803 fn child_with_derived_cause(
804 &self,
805 clause: <DbInterner<'db> as rustc_type_ir::Interner>::Clause,
806 _span: <DbInterner<'db> as rustc_type_ir::Interner>::Span,
807 _parent_trait_pred: rustc_type_ir::Binder<
808 DbInterner<'db>,
809 rustc_type_ir::TraitPredicate<DbInterner<'db>>,
810 >,
811 _index: usize,
812 ) -> Self {
813 clause
814 }
815}
816
817impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>>
818 for Clause<'db>
819{
820 fn upcast_from(
821 from: ty::Binder<DbInterner<'db>, ty::ClauseKind<DbInterner<'db>>>,
822 interner: DbInterner<'db>,
823 ) -> Self {
824 Clause(from.map_bound(PredicateKind::Clause).upcast(interner))
825 }
826}
827impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>> for Clause<'db> {
828 fn upcast_from(from: ty::TraitRef<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
829 Clause(from.upcast(interner))
830 }
831}
832impl<'db> UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>>
833 for Clause<'db>
834{
835 fn upcast_from(
836 from: ty::Binder<DbInterner<'db>, ty::TraitRef<DbInterner<'db>>>,
837 interner: DbInterner<'db>,
838 ) -> Self {
839 Clause(from.upcast(interner))
840 }
841}
842impl<'db> UpcastFrom<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>> for Clause<'db> {
843 fn upcast_from(from: ty::TraitPredicate<DbInterner<'db>>, interner: DbInterner<'db>) -> Self {
844 Clause(from.upcast(interner))
845 }
846}
847impl<'db>
848 UpcastFrom<DbInterner<'db>, ty::Binder<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>>>
849 for Clause<'db>
850{
851 fn upcast_from(
852 from: ty::Binder<DbInterner<'db>, ty::TraitPredicate<DbInterner<'db>>>,
853 interner: DbInterner<'db>,
854 ) -> Self {
855 Clause(from.upcast(interner))
856 }
857}
858impl<'db> UpcastFrom<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>> for Clause<'db> {
859 fn upcast_from(
860 from: ty::ProjectionPredicate<DbInterner<'db>>,
861 interner: DbInterner<'db>,
862 ) -> Self {
863 Clause(from.upcast(interner))
864 }
865}
866impl<'db>
867 UpcastFrom<
868 DbInterner<'db>,
869 ty::Binder<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>>,
870 > for Clause<'db>
871{
872 fn upcast_from(
873 from: ty::Binder<DbInterner<'db>, ty::ProjectionPredicate<DbInterner<'db>>>,
874 interner: DbInterner<'db>,
875 ) -> Self {
876 Clause(from.upcast(interner))
877 }
878}
879
880impl<'db> rustc_type_ir::inherent::Clause<DbInterner<'db>> for Clause<'db> {
881 fn as_predicate(self) -> <DbInterner<'db> as rustc_type_ir::Interner>::Predicate {
882 self.0
883 }
884
885 fn instantiate_supertrait(
886 self,
887 cx: DbInterner<'db>,
888 trait_ref: rustc_type_ir::Binder<DbInterner<'db>, rustc_type_ir::TraitRef<DbInterner<'db>>>,
889 ) -> Self {
890 tracing::debug!(?self, ?trait_ref);
891 let bound_pred = self.kind();
893 let pred_bound_vars = bound_pred.bound_vars();
894 let trait_bound_vars = trait_ref.bound_vars();
895 let shifted_pred =
897 cx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
898 let new = EarlyBinder::bind(shifted_pred)
900 .instantiate(cx, trait_ref.skip_binder().args)
901 .skip_norm_wip();
902 let bound_vars =
904 BoundVarKinds::new_from_iter(trait_bound_vars.iter().chain(pred_bound_vars.iter()));
905
906 let predicate: Predicate<'db> =
907 ty::Binder::bind_with_vars(PredicateKind::Clause(new), bound_vars).upcast(cx);
908 predicate.expect_clause()
909 }
910}