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