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