hir_ty/next_solver/
predicate.rs

1//! Things related to predicates.
2
3use 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
48/// Compares via an ordering that will not change if modules are reordered or other changes are
49/// made to the tree. In particular, this ordering is preserved across incremental compilations.
50fn stable_cmp_existential_predicate<'db>(
51    a: &ExistentialPredicate<'db>,
52    b: &ExistentialPredicate<'db>,
53) -> Ordering {
54    // FIXME: this is actual unstable - see impl in predicate.rs in `rustc_middle`
55    match (a, b) {
56        (ExistentialPredicate::Trait(_), ExistentialPredicate::Trait(_)) => Ordering::Equal,
57        (ExistentialPredicate::Projection(_a), ExistentialPredicate::Projection(_b)) => {
58            // Should sort by def path hash
59            Ordering::Equal
60        }
61        (ExistentialPredicate::AutoTrait(_a), ExistentialPredicate::AutoTrait(_b)) => {
62            // Should sort by def path hash
63            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        // We need to perform this deduplication as we sometimes generate duplicate projections in `a`.
128        let mut a_v: Vec<_> = a.into_iter().collect();
129        let mut b_v: Vec<_> = b.into_iter().collect();
130        // `skip_binder` here is okay because `stable_cmp` doesn't look at binders
131        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            // SAFETY: The caller already has access to a `Predicate<'db>`, so borrowchecking will
234            // make sure that our returned value is valid for the lifetime `'db`.
235            unsafe { std::mem::transmute(inner) }
236        })
237    }
238
239    /// Flips the polarity of a Predicate.
240    ///
241    /// Given `T: Trait` predicate it returns `T: !Trait` and given `T: !Trait` returns `T: Trait`.
242    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// FIXME: should make a "header" in interned_vec
263
264#[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            // SAFETY: The caller already has access to a `Clauses<'db>`, so borrowchecking will
302            // make sure that our returned value is valid for the lifetime `'db`.
303            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)] // TODO implement Debug by hand
418pub struct Clause<'db>(pub(crate) Predicate<'db>);
419
420// We could cram the reveal into the clauses like rustc does, probably
421#[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    /// Whether this projection can be soundly normalized.
683    ///
684    /// Wf predicates must not be normalized, as normalization
685    /// can remove required bounds which would cause us to
686    /// unsoundly accept some programs. See #91068.
687    fn allow_normalization(self) -> bool {
688        // TODO: this should probably live in rustc_type_ir
689        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    /// Matches a `PredicateKind::Clause` and turns it into a `Clause`, otherwise returns `None`.
728    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    /// Assert that the predicate is a clause.
736    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        // See the rustc impl for a long comment
880        let bound_pred = self.kind();
881        let pred_bound_vars = bound_pred.bound_vars();
882        let trait_bound_vars = trait_ref.bound_vars();
883        // 1) Self: Bar1<'a, '^0.0> -> Self: Bar1<'a, '^0.1>
884        let shifted_pred =
885            cx.shift_bound_var_indices(trait_bound_vars.len(), bound_pred.skip_binder());
886        // 2) Self: Bar1<'a, '^0.1> -> T: Bar1<'^0.0, '^0.1>
887        let new = EarlyBinder::bind(shifted_pred).instantiate(cx, trait_ref.skip_binder().args);
888        // 3) ['x] + ['b] -> ['x, 'b]
889        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}