1use std::fmt;
2use std::hash::Hash;
3
4use derive_where::derive_where;
5#[cfg(feature = "nightly")]
6use rustc_macros::{
7    Decodable, Decodable_NoContext, Encodable, Encodable_NoContext, HashStable_NoContext,
8};
9use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
10
11use crate::inherent::*;
12use crate::lift::Lift;
13use crate::upcast::{Upcast, UpcastFrom};
14use crate::visit::TypeVisitableExt as _;
15use crate::{self as ty, Interner};
16
17#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)]
19#[derive_where(Copy; I: Interner, A: Copy)]
20#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
21#[cfg_attr(
22    feature = "nightly",
23    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
24)]
25pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region);
26
27impl<I: Interner, A: Eq> Eq for OutlivesPredicate<I, A> {}
28
29impl<I: Interner, U: Interner, A> Lift<U> for OutlivesPredicate<I, A>
32where
33    A: Lift<U>,
34    I::Region: Lift<U, Lifted = U::Region>,
35{
36    type Lifted = OutlivesPredicate<U, A::Lifted>;
37
38    fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
39        Some(OutlivesPredicate(self.0.lift_to_interner(cx)?, self.1.lift_to_interner(cx)?))
40    }
41}
42
43#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
55#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
56#[cfg_attr(
57    feature = "nightly",
58    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
59)]
60pub struct TraitRef<I: Interner> {
61    pub def_id: I::TraitId,
62    pub args: I::GenericArgs,
63    _use_trait_ref_new_instead: (),
66}
67
68impl<I: Interner> Eq for TraitRef<I> {}
69
70impl<I: Interner> TraitRef<I> {
71    pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
72        interner.debug_assert_args_compatible(trait_def_id.into(), args);
73        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
74    }
75
76    pub fn new(
77        interner: I,
78        trait_def_id: I::TraitId,
79        args: impl IntoIterator<Item: Into<I::GenericArg>>,
80    ) -> Self {
81        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
82        Self::new_from_args(interner, trait_def_id, args)
83    }
84
85    pub fn from_assoc(interner: I, trait_id: I::TraitId, args: I::GenericArgs) -> TraitRef<I> {
86        let generics = interner.generics_of(trait_id.into());
87        TraitRef::new(interner, trait_id, args.iter().take(generics.count()))
88    }
89
90    pub fn identity(interner: I, def_id: I::TraitId) -> TraitRef<I> {
93        TraitRef::new_from_args(
94            interner,
95            def_id,
96            I::GenericArgs::identity_for_item(interner, def_id.into()),
97        )
98    }
99
100    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
101        TraitRef::new(
102            interner,
103            self.def_id,
104            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
105        )
106    }
107
108    #[inline]
109    pub fn self_ty(&self) -> I::Ty {
110        self.args.type_at(0)
111    }
112}
113
114impl<I: Interner> ty::Binder<I, TraitRef<I>> {
115    pub fn self_ty(&self) -> ty::Binder<I, I::Ty> {
116        self.map_bound_ref(|tr| tr.self_ty())
117    }
118
119    pub fn def_id(&self) -> I::TraitId {
120        self.skip_binder().def_id
121    }
122
123    pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause {
124        self.map_bound(|trait_ref| {
125            ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
126        })
127        .upcast(cx)
128    }
129}
130
131#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
132#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
133#[cfg_attr(
134    feature = "nightly",
135    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
136)]
137pub struct TraitPredicate<I: Interner> {
138    pub trait_ref: TraitRef<I>,
139
140    pub polarity: PredicatePolarity,
146}
147
148impl<I: Interner> Eq for TraitPredicate<I> {}
149
150impl<I: Interner> TraitPredicate<I> {
151    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
152        Self {
153            trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty),
154            polarity: self.polarity,
155        }
156    }
157
158    pub fn def_id(self) -> I::TraitId {
159        self.trait_ref.def_id
160    }
161
162    pub fn self_ty(self) -> I::Ty {
163        self.trait_ref.self_ty()
164    }
165}
166
167impl<I: Interner> ty::Binder<I, TraitPredicate<I>> {
168    pub fn def_id(self) -> I::TraitId {
169        self.skip_binder().def_id()
171    }
172
173    pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
174        self.map_bound(|trait_ref| trait_ref.self_ty())
175    }
176
177    #[inline]
178    pub fn polarity(self) -> PredicatePolarity {
179        self.skip_binder().polarity
180    }
181}
182
183impl<I: Interner> UpcastFrom<I, TraitRef<I>> for TraitPredicate<I> {
184    fn upcast_from(from: TraitRef<I>, _tcx: I) -> Self {
185        TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive }
186    }
187}
188
189impl<I: Interner> UpcastFrom<I, ty::Binder<I, TraitRef<I>>> for ty::Binder<I, TraitPredicate<I>> {
190    fn upcast_from(from: ty::Binder<I, TraitRef<I>>, _tcx: I) -> Self {
191        from.map_bound(|trait_ref| TraitPredicate {
192            trait_ref,
193            polarity: PredicatePolarity::Positive,
194        })
195    }
196}
197
198impl<I: Interner> fmt::Debug for TraitPredicate<I> {
199    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
200        write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
201    }
202}
203
204#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
205#[cfg_attr(
206    feature = "nightly",
207    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
208)]
209pub enum ImplPolarity {
210    Positive,
212    Negative,
214    Reservation,
219}
220
221impl fmt::Display for ImplPolarity {
222    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
223        match self {
224            Self::Positive => f.write_str("positive"),
225            Self::Negative => f.write_str("negative"),
226            Self::Reservation => f.write_str("reservation"),
227        }
228    }
229}
230
231impl ImplPolarity {
232    pub fn as_str(self) -> &'static str {
234        match self {
235            Self::Positive => "",
236            Self::Negative => "!",
237            Self::Reservation => "",
238        }
239    }
240}
241
242#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
246#[cfg_attr(
247    feature = "nightly",
248    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
249)]
250pub enum PredicatePolarity {
251    Positive,
253    Negative,
255}
256
257impl PredicatePolarity {
258    pub fn flip(&self) -> PredicatePolarity {
260        match self {
261            PredicatePolarity::Positive => PredicatePolarity::Negative,
262            PredicatePolarity::Negative => PredicatePolarity::Positive,
263        }
264    }
265}
266
267impl fmt::Display for PredicatePolarity {
268    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269        match self {
270            Self::Positive => f.write_str("positive"),
271            Self::Negative => f.write_str("negative"),
272        }
273    }
274}
275
276#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
277#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
278#[cfg_attr(
279    feature = "nightly",
280    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
281)]
282pub enum ExistentialPredicate<I: Interner> {
283    Trait(ExistentialTraitRef<I>),
285    Projection(ExistentialProjection<I>),
287    AutoTrait(I::TraitId),
289}
290
291impl<I: Interner> Eq for ExistentialPredicate<I> {}
292
293impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
294    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
298        match self.skip_binder() {
299            ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx),
300            ExistentialPredicate::Projection(p) => {
301                self.rebind(p.with_self_ty(cx, self_ty)).upcast(cx)
302            }
303            ExistentialPredicate::AutoTrait(did) => {
304                let generics = cx.generics_of(did.into());
305                let trait_ref = if generics.count() == 1 {
306                    ty::TraitRef::new(cx, did, [self_ty])
307                } else {
308                    let err_args =
311                        GenericArgs::extend_with_error(cx, did.into(), &[self_ty.into()]);
312                    ty::TraitRef::new_from_args(cx, did, err_args)
313                };
314                self.rebind(trait_ref).upcast(cx)
315            }
316        }
317    }
318}
319
320#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
328#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
329#[cfg_attr(
330    feature = "nightly",
331    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
332)]
333pub struct ExistentialTraitRef<I: Interner> {
334    pub def_id: I::TraitId,
335    pub args: I::GenericArgs,
336    _use_existential_trait_ref_new_instead: (),
339}
340
341impl<I: Interner> Eq for ExistentialTraitRef<I> {}
342
343impl<I: Interner> ExistentialTraitRef<I> {
344    pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
345        interner.debug_assert_existential_args_compatible(trait_def_id.into(), args);
346        Self { def_id: trait_def_id, args, _use_existential_trait_ref_new_instead: () }
347    }
348
349    pub fn new(
350        interner: I,
351        trait_def_id: I::TraitId,
352        args: impl IntoIterator<Item: Into<I::GenericArg>>,
353    ) -> Self {
354        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
355        Self::new_from_args(interner, trait_def_id, args)
356    }
357
358    pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
359        trait_ref.args.type_at(0);
361
362        ExistentialTraitRef {
363            def_id: trait_ref.def_id,
364            args: interner.mk_args(&trait_ref.args.as_slice()[1..]),
365            _use_existential_trait_ref_new_instead: (),
366        }
367    }
368
369    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
374        TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
378    }
379}
380
381impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
382    pub fn def_id(&self) -> I::TraitId {
383        self.skip_binder().def_id
384    }
385
386    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
391        self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty))
392    }
393}
394
395#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
397#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
398#[cfg_attr(
399    feature = "nightly",
400    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
401)]
402pub struct ExistentialProjection<I: Interner> {
403    pub def_id: I::DefId,
404    pub args: I::GenericArgs,
405    pub term: I::Term,
406
407    use_existential_projection_new_instead: (),
410}
411
412impl<I: Interner> Eq for ExistentialProjection<I> {}
413
414impl<I: Interner> ExistentialProjection<I> {
415    pub fn new_from_args(
416        interner: I,
417        def_id: I::DefId,
418        args: I::GenericArgs,
419        term: I::Term,
420    ) -> ExistentialProjection<I> {
421        interner.debug_assert_existential_args_compatible(def_id, args);
422        Self { def_id, args, term, use_existential_projection_new_instead: () }
423    }
424
425    pub fn new(
426        interner: I,
427        def_id: I::DefId,
428        args: impl IntoIterator<Item: Into<I::GenericArg>>,
429        term: I::Term,
430    ) -> ExistentialProjection<I> {
431        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
432        Self::new_from_args(interner, def_id, args, term)
433    }
434
435    pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
440        let def_id = interner.parent(self.def_id);
441        let args_count = interner.generics_of(def_id).count() - 1;
442        let args = interner.mk_args(&self.args.as_slice()[..args_count]);
443        ExistentialTraitRef::new_from_args(interner, def_id.try_into().unwrap(), args)
444    }
445
446    pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
447        debug_assert!(!self_ty.has_escaping_bound_vars());
449
450        ProjectionPredicate {
451            projection_term: AliasTerm::new(
452                interner,
453                self.def_id,
454                [self_ty.into()].iter().chain(self.args.iter()),
455            ),
456            term: self.term,
457        }
458    }
459
460    pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>) -> Self {
461        projection_predicate.projection_term.args.type_at(0);
463
464        Self {
465            def_id: projection_predicate.projection_term.def_id,
466            args: interner.mk_args(&projection_predicate.projection_term.args.as_slice()[1..]),
467            term: projection_predicate.term,
468            use_existential_projection_new_instead: (),
469        }
470    }
471}
472
473impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
474    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
475        self.map_bound(|p| p.with_self_ty(cx, self_ty))
476    }
477
478    pub fn item_def_id(&self) -> I::DefId {
479        self.skip_binder().def_id
480    }
481}
482
483#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
484#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
485pub enum AliasTermKind {
486    ProjectionTy,
489    InherentTy,
491    OpaqueTy,
494    FreeTy,
498
499    UnevaluatedConst,
501    ProjectionConst,
503    FreeConst,
505    InherentConst,
507}
508
509impl AliasTermKind {
510    pub fn descr(self) -> &'static str {
511        match self {
512            AliasTermKind::ProjectionTy => "associated type",
513            AliasTermKind::ProjectionConst => "associated const",
514            AliasTermKind::InherentTy => "inherent associated type",
515            AliasTermKind::InherentConst => "inherent associated const",
516            AliasTermKind::OpaqueTy => "opaque type",
517            AliasTermKind::FreeTy => "type alias",
518            AliasTermKind::FreeConst => "unevaluated constant",
519            AliasTermKind::UnevaluatedConst => "unevaluated constant",
520        }
521    }
522
523    pub fn is_type(self) -> bool {
524        match self {
525            AliasTermKind::ProjectionTy
526            | AliasTermKind::InherentTy
527            | AliasTermKind::OpaqueTy
528            | AliasTermKind::FreeTy => true,
529
530            AliasTermKind::UnevaluatedConst
531            | AliasTermKind::ProjectionConst
532            | AliasTermKind::InherentConst
533            | AliasTermKind::FreeConst => false,
534        }
535    }
536}
537
538impl From<ty::AliasTyKind> for AliasTermKind {
539    fn from(value: ty::AliasTyKind) -> Self {
540        match value {
541            ty::Projection => AliasTermKind::ProjectionTy,
542            ty::Opaque => AliasTermKind::OpaqueTy,
543            ty::Free => AliasTermKind::FreeTy,
544            ty::Inherent => AliasTermKind::InherentTy,
545        }
546    }
547}
548
549#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
555#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
556#[cfg_attr(
557    feature = "nightly",
558    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
559)]
560pub struct AliasTerm<I: Interner> {
561    pub args: I::GenericArgs,
572
573    pub def_id: I::DefId,
584
585    #[derive_where(skip(Debug))]
587    _use_alias_term_new_instead: (),
588}
589
590impl<I: Interner> Eq for AliasTerm<I> {}
591
592impl<I: Interner> AliasTerm<I> {
593    pub fn new_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTerm<I> {
594        interner.debug_assert_args_compatible(def_id, args);
595        AliasTerm { def_id, args, _use_alias_term_new_instead: () }
596    }
597
598    pub fn new(
599        interner: I,
600        def_id: I::DefId,
601        args: impl IntoIterator<Item: Into<I::GenericArg>>,
602    ) -> AliasTerm<I> {
603        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
604        Self::new_from_args(interner, def_id, args)
605    }
606
607    pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
608        match self.kind(interner) {
609            AliasTermKind::ProjectionTy
610            | AliasTermKind::InherentTy
611            | AliasTermKind::OpaqueTy
612            | AliasTermKind::FreeTy => {}
613            AliasTermKind::InherentConst
614            | AliasTermKind::FreeConst
615            | AliasTermKind::UnevaluatedConst
616            | AliasTermKind::ProjectionConst => {
617                panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
618            }
619        }
620        ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
621    }
622
623    pub fn kind(self, interner: I) -> AliasTermKind {
624        interner.alias_term_kind(self)
625    }
626
627    pub fn to_term(self, interner: I) -> I::Term {
628        match self.kind(interner) {
629            AliasTermKind::ProjectionTy => Ty::new_alias(
630                interner,
631                ty::AliasTyKind::Projection,
632                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
633            )
634            .into(),
635            AliasTermKind::InherentTy => Ty::new_alias(
636                interner,
637                ty::AliasTyKind::Inherent,
638                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
639            )
640            .into(),
641            AliasTermKind::OpaqueTy => Ty::new_alias(
642                interner,
643                ty::AliasTyKind::Opaque,
644                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
645            )
646            .into(),
647            AliasTermKind::FreeTy => Ty::new_alias(
648                interner,
649                ty::AliasTyKind::Free,
650                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
651            )
652            .into(),
653            AliasTermKind::FreeConst
654            | AliasTermKind::InherentConst
655            | AliasTermKind::UnevaluatedConst
656            | AliasTermKind::ProjectionConst => I::Const::new_unevaluated(
657                interner,
658                ty::UnevaluatedConst::new(self.def_id, self.args),
659            )
660            .into(),
661        }
662    }
663}
664
665impl<I: Interner> AliasTerm<I> {
667    pub fn self_ty(self) -> I::Ty {
668        self.args.type_at(0)
669    }
670
671    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
672        AliasTerm::new(
673            interner,
674            self.def_id,
675            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
676        )
677    }
678
679    pub fn trait_def_id(self, interner: I) -> I::TraitId {
680        assert!(
681            matches!(
682                self.kind(interner),
683                AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
684            ),
685            "expected a projection"
686        );
687        interner.parent(self.def_id).try_into().unwrap()
688    }
689
690    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
695        interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
696    }
697
698    pub fn trait_ref(self, interner: I) -> TraitRef<I> {
706        self.trait_ref_and_own_args(interner).0
707    }
708
709    pub fn own_args(self, interner: I) -> I::GenericArgsSlice {
713        self.trait_ref_and_own_args(interner).1
714    }
715}
716
717impl<I: Interner> AliasTerm<I> {
719    pub fn rebase_inherent_args_onto_impl(
730        self,
731        impl_args: I::GenericArgs,
732        interner: I,
733    ) -> I::GenericArgs {
734        debug_assert!(matches!(
735            self.kind(interner),
736            AliasTermKind::InherentTy | AliasTermKind::InherentConst
737        ));
738        interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1)))
739    }
740}
741
742impl<I: Interner> From<ty::AliasTy<I>> for AliasTerm<I> {
743    fn from(ty: ty::AliasTy<I>) -> Self {
744        AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
745    }
746}
747
748impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> {
749    fn from(ct: ty::UnevaluatedConst<I>) -> Self {
750        AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
751    }
752}
753
754#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
767#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
768#[cfg_attr(
769    feature = "nightly",
770    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
771)]
772pub struct ProjectionPredicate<I: Interner> {
773    pub projection_term: AliasTerm<I>,
774    pub term: I::Term,
775}
776
777impl<I: Interner> Eq for ProjectionPredicate<I> {}
778
779impl<I: Interner> ProjectionPredicate<I> {
780    pub fn self_ty(self) -> I::Ty {
781        self.projection_term.self_ty()
782    }
783
784    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
785        Self {
786            projection_term: self.projection_term.with_replaced_self_ty(interner, self_ty),
787            ..self
788        }
789    }
790
791    pub fn trait_def_id(self, interner: I) -> I::TraitId {
792        self.projection_term.trait_def_id(interner)
793    }
794
795    pub fn def_id(self) -> I::DefId {
796        self.projection_term.def_id
797    }
798}
799
800impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
801    #[inline]
803    pub fn trait_def_id(&self, cx: I) -> I::TraitId {
804        self.skip_binder().projection_term.trait_def_id(cx)
805    }
806
807    pub fn term(&self) -> ty::Binder<I, I::Term> {
808        self.map_bound(|predicate| predicate.term)
809    }
810
811    pub fn item_def_id(&self) -> I::DefId {
816        self.skip_binder().projection_term.def_id
818    }
819}
820
821impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
822    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
823        write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term)
824    }
825}
826
827#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
830#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
831#[cfg_attr(
832    feature = "nightly",
833    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
834)]
835pub struct NormalizesTo<I: Interner> {
836    pub alias: AliasTerm<I>,
837    pub term: I::Term,
838}
839
840impl<I: Interner> Eq for NormalizesTo<I> {}
841
842impl<I: Interner> NormalizesTo<I> {
843    pub fn self_ty(self) -> I::Ty {
844        self.alias.self_ty()
845    }
846
847    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<I> {
848        Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self }
849    }
850
851    pub fn trait_def_id(self, interner: I) -> I::TraitId {
852        self.alias.trait_def_id(interner)
853    }
854
855    pub fn def_id(self) -> I::DefId {
856        self.alias.def_id
857    }
858}
859
860impl<I: Interner> fmt::Debug for NormalizesTo<I> {
861    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
862        write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
863    }
864}
865
866#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
867#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
868#[cfg_attr(
869    feature = "nightly",
870    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
871)]
872pub struct HostEffectPredicate<I: Interner> {
873    pub trait_ref: ty::TraitRef<I>,
874    pub constness: BoundConstness,
875}
876
877impl<I: Interner> Eq for HostEffectPredicate<I> {}
878
879impl<I: Interner> HostEffectPredicate<I> {
880    pub fn self_ty(self) -> I::Ty {
881        self.trait_ref.self_ty()
882    }
883
884    pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
885        Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self }
886    }
887
888    pub fn def_id(self) -> I::TraitId {
889        self.trait_ref.def_id
890    }
891}
892
893impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
894    pub fn def_id(self) -> I::TraitId {
895        self.skip_binder().def_id()
897    }
898
899    pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
900        self.map_bound(|trait_ref| trait_ref.self_ty())
901    }
902
903    #[inline]
904    pub fn constness(self) -> BoundConstness {
905        self.skip_binder().constness
906    }
907}
908
909#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
913#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
914#[cfg_attr(
915    feature = "nightly",
916    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
917)]
918pub struct SubtypePredicate<I: Interner> {
919    pub a_is_expected: bool,
920    pub a: I::Ty,
921    pub b: I::Ty,
922}
923
924impl<I: Interner> Eq for SubtypePredicate<I> {}
925
926#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
928#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
929#[cfg_attr(
930    feature = "nightly",
931    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
932)]
933pub struct CoercePredicate<I: Interner> {
934    pub a: I::Ty,
935    pub b: I::Ty,
936}
937
938impl<I: Interner> Eq for CoercePredicate<I> {}
939
940#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
941#[cfg_attr(
942    feature = "nightly",
943    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
944)]
945pub enum BoundConstness {
946    Const,
950    Maybe,
954}
955
956impl BoundConstness {
957    pub fn satisfies(self, goal: BoundConstness) -> bool {
958        match (self, goal) {
959            (BoundConstness::Const, BoundConstness::Const | BoundConstness::Maybe) => true,
960            (BoundConstness::Maybe, BoundConstness::Maybe) => true,
961            (BoundConstness::Maybe, BoundConstness::Const) => false,
962        }
963    }
964
965    pub fn as_str(self) -> &'static str {
966        match self {
967            Self::Const => "const",
968            Self::Maybe => "[const]",
969        }
970    }
971}
972
973impl fmt::Display for BoundConstness {
974    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
975        match self {
976            Self::Const => f.write_str("const"),
977            Self::Maybe => f.write_str("[const]"),
978        }
979    }
980}