rustc_type_ir/
predicate.rs

1use std::fmt;
2use std::hash::Hash;
3
4use derive_where::derive_where;
5#[cfg(feature = "nightly")]
6use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
7use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
8
9use crate::inherent::*;
10use crate::lift::Lift;
11use crate::upcast::{Upcast, UpcastFrom};
12use crate::visit::TypeVisitableExt as _;
13use crate::{self as ty, Interner};
14
15/// `A: 'region`
16#[derive_where(Clone; I: Interner, A: Clone)]
17#[derive_where(Copy; I: Interner, A: Copy)]
18#[derive_where(Hash; I: Interner, A: Hash)]
19#[derive_where(PartialEq; I: Interner, A: PartialEq)]
20#[derive_where(Eq; I: Interner, A: Eq)]
21#[derive_where(Debug; I: Interner, A: fmt::Debug)]
22#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
23#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
24pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region);
25
26// FIXME: We manually derive `Lift` because the `derive(Lift_Generic)` doesn't
27// understand how to turn `A` to `A::Lifted` in the output `type Lifted`.
28impl<I: Interner, U: Interner, A> Lift<U> for OutlivesPredicate<I, A>
29where
30    A: Lift<U>,
31    I::Region: Lift<U, Lifted = U::Region>,
32{
33    type Lifted = OutlivesPredicate<U, A::Lifted>;
34
35    fn lift_to_interner(self, cx: U) -> Option<Self::Lifted> {
36        Some(OutlivesPredicate(self.0.lift_to_interner(cx)?, self.1.lift_to_interner(cx)?))
37    }
38}
39
40/// A complete reference to a trait. These take numerous guises in syntax,
41/// but perhaps the most recognizable form is in a where-clause:
42/// ```ignore (illustrative)
43/// T: Foo<U>
44/// ```
45/// This would be represented by a trait-reference where the `DefId` is the
46/// `DefId` for the trait `Foo` and the args define `T` as parameter 0,
47/// and `U` as parameter 1.
48///
49/// Trait references also appear in object types like `Foo<U>`, but in
50/// that case the `Self` parameter is absent from the generic parameters.
51#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
52#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
53#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
54pub struct TraitRef<I: Interner> {
55    pub def_id: I::DefId,
56    pub args: I::GenericArgs,
57    /// This field exists to prevent the creation of `TraitRef` without
58    /// calling [`TraitRef::new_from_args`].
59    _use_trait_ref_new_instead: (),
60}
61
62impl<I: Interner> TraitRef<I> {
63    pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
64        interner.debug_assert_args_compatible(trait_def_id, args);
65        Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
66    }
67
68    pub fn new(
69        interner: I,
70        trait_def_id: I::DefId,
71        args: impl IntoIterator<Item: Into<I::GenericArg>>,
72    ) -> Self {
73        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
74        Self::new_from_args(interner, trait_def_id, args)
75    }
76
77    pub fn from_method(interner: I, trait_id: I::DefId, args: I::GenericArgs) -> TraitRef<I> {
78        let generics = interner.generics_of(trait_id);
79        TraitRef::new(interner, trait_id, args.iter().take(generics.count()))
80    }
81
82    /// Returns a `TraitRef` of the form `P0: Foo<P1..Pn>` where `Pi`
83    /// are the parameters defined on trait.
84    pub fn identity(interner: I, def_id: I::DefId) -> TraitRef<I> {
85        TraitRef::new_from_args(
86            interner,
87            def_id,
88            I::GenericArgs::identity_for_item(interner, def_id),
89        )
90    }
91
92    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
93        TraitRef::new(
94            interner,
95            self.def_id,
96            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
97        )
98    }
99
100    #[inline]
101    pub fn self_ty(&self) -> I::Ty {
102        self.args.type_at(0)
103    }
104}
105
106impl<I: Interner> ty::Binder<I, TraitRef<I>> {
107    pub fn self_ty(&self) -> ty::Binder<I, I::Ty> {
108        self.map_bound_ref(|tr| tr.self_ty())
109    }
110
111    pub fn def_id(&self) -> I::DefId {
112        self.skip_binder().def_id
113    }
114
115    pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause {
116        self.map_bound(|trait_ref| {
117            ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
118        })
119        .upcast(cx)
120    }
121}
122
123#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
124#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
125#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
126pub struct TraitPredicate<I: Interner> {
127    pub trait_ref: TraitRef<I>,
128
129    /// If polarity is Positive: we are proving that the trait is implemented.
130    ///
131    /// If polarity is Negative: we are proving that a negative impl of this trait
132    /// exists. (Note that coherence also checks whether negative impls of supertraits
133    /// exist via a series of predicates.)
134    ///
135    /// If polarity is Reserved: that's a bug.
136    pub polarity: PredicatePolarity,
137}
138
139impl<I: Interner> TraitPredicate<I> {
140    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
141        Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), polarity: self.polarity }
142    }
143
144    pub fn def_id(self) -> I::DefId {
145        self.trait_ref.def_id
146    }
147
148    pub fn self_ty(self) -> I::Ty {
149        self.trait_ref.self_ty()
150    }
151}
152
153impl<I: Interner> ty::Binder<I, TraitPredicate<I>> {
154    pub fn def_id(self) -> I::DefId {
155        // Ok to skip binder since trait `DefId` does not care about regions.
156        self.skip_binder().def_id()
157    }
158
159    pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
160        self.map_bound(|trait_ref| trait_ref.self_ty())
161    }
162
163    #[inline]
164    pub fn polarity(self) -> PredicatePolarity {
165        self.skip_binder().polarity
166    }
167}
168
169impl<I: Interner> UpcastFrom<I, TraitRef<I>> for TraitPredicate<I> {
170    fn upcast_from(from: TraitRef<I>, _tcx: I) -> Self {
171        TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive }
172    }
173}
174
175impl<I: Interner> fmt::Debug for TraitPredicate<I> {
176    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
177        write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
178    }
179}
180
181#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
182#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
183pub enum ImplPolarity {
184    /// `impl Trait for Type`
185    Positive,
186    /// `impl !Trait for Type`
187    Negative,
188    /// `#[rustc_reservation_impl] impl Trait for Type`
189    ///
190    /// This is a "stability hack", not a real Rust feature.
191    /// See #64631 for details.
192    Reservation,
193}
194
195impl fmt::Display for ImplPolarity {
196    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
197        match self {
198            Self::Positive => f.write_str("positive"),
199            Self::Negative => f.write_str("negative"),
200            Self::Reservation => f.write_str("reservation"),
201        }
202    }
203}
204
205impl ImplPolarity {
206    /// The polarity marker in front of the impl trait ref if applicable.
207    pub fn as_str(self) -> &'static str {
208        match self {
209            Self::Positive => "",
210            Self::Negative => "!",
211            Self::Reservation => "",
212        }
213    }
214}
215
216/// Polarity for a trait predicate. May either be negative or positive.
217/// Distinguished from [`ImplPolarity`] since we never compute goals with
218/// "reservation" level.
219#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
220#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
221pub enum PredicatePolarity {
222    /// `Type: Trait`
223    Positive,
224    /// `Type: !Trait`
225    Negative,
226}
227
228impl PredicatePolarity {
229    /// Flips polarity by turning `Positive` into `Negative` and `Negative` into `Positive`.
230    pub fn flip(&self) -> PredicatePolarity {
231        match self {
232            PredicatePolarity::Positive => PredicatePolarity::Negative,
233            PredicatePolarity::Negative => PredicatePolarity::Positive,
234        }
235    }
236}
237
238impl fmt::Display for PredicatePolarity {
239    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
240        match self {
241            Self::Positive => f.write_str("positive"),
242            Self::Negative => f.write_str("negative"),
243        }
244    }
245}
246
247#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
248#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
249#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
250pub enum ExistentialPredicate<I: Interner> {
251    /// E.g., `Iterator`.
252    Trait(ExistentialTraitRef<I>),
253    /// E.g., `Iterator::Item = T`.
254    Projection(ExistentialProjection<I>),
255    /// E.g., `Send`.
256    AutoTrait(I::DefId),
257}
258
259impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
260    /// Given an existential predicate like `?Self: PartialEq<u32>` (e.g., derived from `dyn PartialEq<u32>`),
261    /// and a concrete type `self_ty`, returns a full predicate where the existentially quantified variable `?Self`
262    /// has been replaced with `self_ty` (e.g., `self_ty: PartialEq<u32>`, in our example).
263    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
264        match self.skip_binder() {
265            ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx),
266            ExistentialPredicate::Projection(p) => {
267                self.rebind(p.with_self_ty(cx, self_ty)).upcast(cx)
268            }
269            ExistentialPredicate::AutoTrait(did) => {
270                let generics = cx.generics_of(did);
271                let trait_ref = if generics.count() == 1 {
272                    ty::TraitRef::new(cx, did, [self_ty])
273                } else {
274                    // If this is an ill-formed auto trait, then synthesize
275                    // new error args for the missing generics.
276                    let err_args = GenericArgs::extend_with_error(cx, did, &[self_ty.into()]);
277                    ty::TraitRef::new_from_args(cx, did, err_args)
278                };
279                self.rebind(trait_ref).upcast(cx)
280            }
281        }
282    }
283}
284
285/// An existential reference to a trait, where `Self` is erased.
286/// For example, the trait object `Trait<'a, 'b, X, Y>` is:
287/// ```ignore (illustrative)
288/// exists T. T: Trait<'a, 'b, X, Y>
289/// ```
290/// The generic parameters don't include the erased `Self`, only trait
291/// type and lifetime parameters (`[X, Y]` and `['a, 'b]` above).
292#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
293#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
294#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
295pub struct ExistentialTraitRef<I: Interner> {
296    pub def_id: I::DefId,
297    pub args: I::GenericArgs,
298    /// This field exists to prevent the creation of `ExistentialTraitRef` without
299    /// calling [`ExistentialTraitRef::new_from_args`].
300    _use_existential_trait_ref_new_instead: (),
301}
302
303impl<I: Interner> ExistentialTraitRef<I> {
304    pub fn new_from_args(interner: I, trait_def_id: I::DefId, args: I::GenericArgs) -> Self {
305        interner.debug_assert_existential_args_compatible(trait_def_id, args);
306        Self { def_id: trait_def_id, args, _use_existential_trait_ref_new_instead: () }
307    }
308
309    pub fn new(
310        interner: I,
311        trait_def_id: I::DefId,
312        args: impl IntoIterator<Item: Into<I::GenericArg>>,
313    ) -> Self {
314        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
315        Self::new_from_args(interner, trait_def_id, args)
316    }
317
318    pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
319        // Assert there is a Self.
320        trait_ref.args.type_at(0);
321
322        ExistentialTraitRef {
323            def_id: trait_ref.def_id,
324            args: interner.mk_args(&trait_ref.args.as_slice()[1..]),
325            _use_existential_trait_ref_new_instead: (),
326        }
327    }
328
329    /// Object types don't have a self type specified. Therefore, when
330    /// we convert the principal trait-ref into a normal trait-ref,
331    /// you must give *some* self type. A common choice is `mk_err()`
332    /// or some placeholder type.
333    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
334        // otherwise the escaping vars would be captured by the binder
335        // debug_assert!(!self_ty.has_escaping_bound_vars());
336
337        TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
338    }
339}
340
341impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
342    pub fn def_id(&self) -> I::DefId {
343        self.skip_binder().def_id
344    }
345
346    /// Object types don't have a self type specified. Therefore, when
347    /// we convert the principal trait-ref into a normal trait-ref,
348    /// you must give *some* self type. A common choice is `mk_err()`
349    /// or some placeholder type.
350    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
351        self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty))
352    }
353}
354
355/// A `ProjectionPredicate` for an `ExistentialTraitRef`.
356#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
357#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
358#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
359pub struct ExistentialProjection<I: Interner> {
360    pub def_id: I::DefId,
361    pub args: I::GenericArgs,
362    pub term: I::Term,
363
364    /// This field exists to prevent the creation of `ExistentialProjection`
365    /// without using [`ExistentialProjection::new_from_args`].
366    use_existential_projection_new_instead: (),
367}
368
369impl<I: Interner> ExistentialProjection<I> {
370    pub fn new_from_args(
371        interner: I,
372        def_id: I::DefId,
373        args: I::GenericArgs,
374        term: I::Term,
375    ) -> ExistentialProjection<I> {
376        interner.debug_assert_existential_args_compatible(def_id, args);
377        Self { def_id, args, term, use_existential_projection_new_instead: () }
378    }
379
380    pub fn new(
381        interner: I,
382        def_id: I::DefId,
383        args: impl IntoIterator<Item: Into<I::GenericArg>>,
384        term: I::Term,
385    ) -> ExistentialProjection<I> {
386        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
387        Self::new_from_args(interner, def_id, args, term)
388    }
389
390    /// Extracts the underlying existential trait reference from this projection.
391    /// For example, if this is a projection of `exists T. <T as Iterator>::Item == X`,
392    /// then this function would return an `exists T. T: Iterator` existential trait
393    /// reference.
394    pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
395        let def_id = interner.parent(self.def_id);
396        let args_count = interner.generics_of(def_id).count() - 1;
397        let args = interner.mk_args(&self.args.as_slice()[..args_count]);
398        ExistentialTraitRef { def_id, args, _use_existential_trait_ref_new_instead: () }
399    }
400
401    pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
402        // otherwise the escaping regions would be captured by the binders
403        debug_assert!(!self_ty.has_escaping_bound_vars());
404
405        ProjectionPredicate {
406            projection_term: AliasTerm::new(
407                interner,
408                self.def_id,
409                [self_ty.into()].iter().chain(self.args.iter()),
410            ),
411            term: self.term,
412        }
413    }
414
415    pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>) -> Self {
416        // Assert there is a Self.
417        projection_predicate.projection_term.args.type_at(0);
418
419        Self {
420            def_id: projection_predicate.projection_term.def_id,
421            args: interner.mk_args(&projection_predicate.projection_term.args.as_slice()[1..]),
422            term: projection_predicate.term,
423            use_existential_projection_new_instead: (),
424        }
425    }
426}
427
428impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
429    pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
430        self.map_bound(|p| p.with_self_ty(cx, self_ty))
431    }
432
433    pub fn item_def_id(&self) -> I::DefId {
434        self.skip_binder().def_id
435    }
436}
437
438#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
439#[cfg_attr(feature = "nightly", derive(Encodable, Decodable, HashStable_NoContext))]
440pub enum AliasTermKind {
441    /// A projection `<Type as Trait>::AssocType`.
442    /// Can get normalized away if monomorphic enough.
443    ProjectionTy,
444    /// An associated type in an inherent `impl`
445    InherentTy,
446    /// An opaque type (usually from `impl Trait` in type aliases or function return types)
447    /// Can only be normalized away in PostAnalysis mode or its defining scope.
448    OpaqueTy,
449    /// A type alias that actually checks its trait bounds.
450    /// Currently only used if the type alias references opaque types.
451    /// Can always be normalized away.
452    WeakTy,
453    /// An unevaluated const coming from a generic const expression.
454    UnevaluatedConst,
455    /// An unevaluated const coming from an associated const.
456    ProjectionConst,
457}
458
459impl AliasTermKind {
460    pub fn descr(self) -> &'static str {
461        match self {
462            AliasTermKind::ProjectionTy => "associated type",
463            AliasTermKind::ProjectionConst => "associated const",
464            AliasTermKind::InherentTy => "inherent associated type",
465            AliasTermKind::OpaqueTy => "opaque type",
466            AliasTermKind::WeakTy => "type alias",
467            AliasTermKind::UnevaluatedConst => "unevaluated constant",
468        }
469    }
470}
471
472impl From<ty::AliasTyKind> for AliasTermKind {
473    fn from(value: ty::AliasTyKind) -> Self {
474        match value {
475            ty::Projection => AliasTermKind::ProjectionTy,
476            ty::Opaque => AliasTermKind::OpaqueTy,
477            ty::Weak => AliasTermKind::WeakTy,
478            ty::Inherent => AliasTermKind::InherentTy,
479        }
480    }
481}
482
483/// Represents the unprojected term of a projection goal.
484///
485/// * For a projection, this would be `<Ty as Trait<...>>::N<...>`.
486/// * For an inherent projection, this would be `Ty::N<...>`.
487/// * For an opaque type, there is no explicit syntax.
488#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
489#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
490#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
491pub struct AliasTerm<I: Interner> {
492    /// The parameters of the associated or opaque item.
493    ///
494    /// For a projection, these are the generic parameters for the trait and the
495    /// GAT parameters, if there are any.
496    ///
497    /// For an inherent projection, they consist of the self type and the GAT parameters,
498    /// if there are any.
499    ///
500    /// For RPIT the generic parameters are for the generics of the function,
501    /// while for TAIT it is used for the generic parameters of the alias.
502    pub args: I::GenericArgs,
503
504    /// The `DefId` of the `TraitItem` or `ImplItem` for the associated type `N` depending on whether
505    /// this is a projection or an inherent projection or the `DefId` of the `OpaqueType` item if
506    /// this is an opaque.
507    ///
508    /// During codegen, `interner.type_of(def_id)` can be used to get the type of the
509    /// underlying type if the type is an opaque.
510    ///
511    /// Note that if this is an associated type, this is not the `DefId` of the
512    /// `TraitRef` containing this associated type, which is in `interner.associated_item(def_id).container`,
513    /// aka. `interner.parent(def_id)`.
514    pub def_id: I::DefId,
515
516    /// This field exists to prevent the creation of `AliasTerm` without using [`AliasTerm::new_from_args`].
517    #[derive_where(skip(Debug))]
518    _use_alias_term_new_instead: (),
519}
520
521impl<I: Interner> AliasTerm<I> {
522    pub fn new_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTerm<I> {
523        interner.debug_assert_args_compatible(def_id, args);
524        AliasTerm { def_id, args, _use_alias_term_new_instead: () }
525    }
526
527    pub fn new(
528        interner: I,
529        def_id: I::DefId,
530        args: impl IntoIterator<Item: Into<I::GenericArg>>,
531    ) -> AliasTerm<I> {
532        let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
533        Self::new_from_args(interner, def_id, args)
534    }
535
536    pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
537        match self.kind(interner) {
538            AliasTermKind::ProjectionTy
539            | AliasTermKind::InherentTy
540            | AliasTermKind::OpaqueTy
541            | AliasTermKind::WeakTy => {}
542            AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
543                panic!("Cannot turn `UnevaluatedConst` into `AliasTy`")
544            }
545        }
546        ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () }
547    }
548
549    pub fn kind(self, interner: I) -> AliasTermKind {
550        interner.alias_term_kind(self)
551    }
552
553    pub fn to_term(self, interner: I) -> I::Term {
554        match self.kind(interner) {
555            AliasTermKind::ProjectionTy => Ty::new_alias(
556                interner,
557                ty::AliasTyKind::Projection,
558                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
559            )
560            .into(),
561            AliasTermKind::InherentTy => Ty::new_alias(
562                interner,
563                ty::AliasTyKind::Inherent,
564                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
565            )
566            .into(),
567            AliasTermKind::OpaqueTy => Ty::new_alias(
568                interner,
569                ty::AliasTyKind::Opaque,
570                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
571            )
572            .into(),
573            AliasTermKind::WeakTy => Ty::new_alias(
574                interner,
575                ty::AliasTyKind::Weak,
576                ty::AliasTy { def_id: self.def_id, args: self.args, _use_alias_ty_new_instead: () },
577            )
578            .into(),
579            AliasTermKind::UnevaluatedConst | AliasTermKind::ProjectionConst => {
580                I::Const::new_unevaluated(
581                    interner,
582                    ty::UnevaluatedConst::new(self.def_id, self.args),
583                )
584                .into()
585            }
586        }
587    }
588}
589
590/// The following methods work only with (trait) associated type projections.
591impl<I: Interner> AliasTerm<I> {
592    pub fn self_ty(self) -> I::Ty {
593        self.args.type_at(0)
594    }
595
596    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
597        AliasTerm::new(
598            interner,
599            self.def_id,
600            [self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
601        )
602    }
603
604    pub fn trait_def_id(self, interner: I) -> I::DefId {
605        assert!(
606            matches!(
607                self.kind(interner),
608                AliasTermKind::ProjectionTy | AliasTermKind::ProjectionConst
609            ),
610            "expected a projection"
611        );
612        interner.parent(self.def_id)
613    }
614
615    /// Extracts the underlying trait reference and own args from this projection.
616    /// For example, if this is a projection of `<T as StreamingIterator>::Item<'a>`,
617    /// then this function would return a `T: StreamingIterator` trait reference and
618    /// `['a]` as the own args.
619    pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
620        interner.trait_ref_and_own_args_for_alias(self.def_id, self.args)
621    }
622
623    /// Extracts the underlying trait reference from this projection.
624    /// For example, if this is a projection of `<T as Iterator>::Item`,
625    /// then this function would return a `T: Iterator` trait reference.
626    ///
627    /// WARNING: This will drop the args for generic associated types
628    /// consider calling [Self::trait_ref_and_own_args] to get those
629    /// as well.
630    pub fn trait_ref(self, interner: I) -> TraitRef<I> {
631        self.trait_ref_and_own_args(interner).0
632    }
633}
634
635impl<I: Interner> From<ty::AliasTy<I>> for AliasTerm<I> {
636    fn from(ty: ty::AliasTy<I>) -> Self {
637        AliasTerm { args: ty.args, def_id: ty.def_id, _use_alias_term_new_instead: () }
638    }
639}
640
641impl<I: Interner> From<ty::UnevaluatedConst<I>> for AliasTerm<I> {
642    fn from(ct: ty::UnevaluatedConst<I>) -> Self {
643        AliasTerm { args: ct.args, def_id: ct.def, _use_alias_term_new_instead: () }
644    }
645}
646
647/// This kind of predicate has no *direct* correspondent in the
648/// syntax, but it roughly corresponds to the syntactic forms:
649///
650/// 1. `T: TraitRef<..., Item = Type>`
651/// 2. `<T as TraitRef<...>>::Item == Type` (NYI)
652///
653/// In particular, form #1 is "desugared" to the combination of a
654/// normal trait predicate (`T: TraitRef<...>`) and one of these
655/// predicates. Form #2 is a broader form in that it also permits
656/// equality between arbitrary types. Processing an instance of
657/// Form #2 eventually yields one of these `ProjectionPredicate`
658/// instances to normalize the LHS.
659#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
660#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
661#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
662pub struct ProjectionPredicate<I: Interner> {
663    pub projection_term: AliasTerm<I>,
664    pub term: I::Term,
665}
666
667impl<I: Interner> ProjectionPredicate<I> {
668    pub fn self_ty(self) -> I::Ty {
669        self.projection_term.self_ty()
670    }
671
672    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
673        Self { projection_term: self.projection_term.with_self_ty(interner, self_ty), ..self }
674    }
675
676    pub fn trait_def_id(self, interner: I) -> I::DefId {
677        self.projection_term.trait_def_id(interner)
678    }
679
680    pub fn def_id(self) -> I::DefId {
681        self.projection_term.def_id
682    }
683}
684
685impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
686    /// Returns the `DefId` of the trait of the associated item being projected.
687    #[inline]
688    pub fn trait_def_id(&self, cx: I) -> I::DefId {
689        self.skip_binder().projection_term.trait_def_id(cx)
690    }
691
692    pub fn term(&self) -> ty::Binder<I, I::Term> {
693        self.map_bound(|predicate| predicate.term)
694    }
695
696    /// The `DefId` of the `TraitItem` for the associated type.
697    ///
698    /// Note that this is not the `DefId` of the `TraitRef` containing this
699    /// associated type, which is in `tcx.associated_item(projection_def_id()).container`.
700    pub fn item_def_id(&self) -> I::DefId {
701        // Ok to skip binder since trait `DefId` does not care about regions.
702        self.skip_binder().projection_term.def_id
703    }
704}
705
706impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
707    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708        write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term)
709    }
710}
711
712/// Used by the new solver to normalize an alias. This always expects the `term` to
713/// be an unconstrained inference variable which is used as the output.
714#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
715#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
716#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
717pub struct NormalizesTo<I: Interner> {
718    pub alias: AliasTerm<I>,
719    pub term: I::Term,
720}
721
722impl<I: Interner> NormalizesTo<I> {
723    pub fn self_ty(self) -> I::Ty {
724        self.alias.self_ty()
725    }
726
727    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<I> {
728        Self { alias: self.alias.with_self_ty(interner, self_ty), ..self }
729    }
730
731    pub fn trait_def_id(self, interner: I) -> I::DefId {
732        self.alias.trait_def_id(interner)
733    }
734
735    pub fn def_id(self) -> I::DefId {
736        self.alias.def_id
737    }
738}
739
740impl<I: Interner> fmt::Debug for NormalizesTo<I> {
741    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
742        write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
743    }
744}
745
746#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
747#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
748#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
749pub struct HostEffectPredicate<I: Interner> {
750    pub trait_ref: ty::TraitRef<I>,
751    pub constness: BoundConstness,
752}
753
754impl<I: Interner> HostEffectPredicate<I> {
755    pub fn self_ty(self) -> I::Ty {
756        self.trait_ref.self_ty()
757    }
758
759    pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
760        Self { trait_ref: self.trait_ref.with_self_ty(interner, self_ty), ..self }
761    }
762
763    pub fn def_id(self) -> I::DefId {
764        self.trait_ref.def_id
765    }
766}
767
768impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
769    pub fn def_id(self) -> I::DefId {
770        // Ok to skip binder since trait `DefId` does not care about regions.
771        self.skip_binder().def_id()
772    }
773
774    pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
775        self.map_bound(|trait_ref| trait_ref.self_ty())
776    }
777
778    #[inline]
779    pub fn constness(self) -> BoundConstness {
780        self.skip_binder().constness
781    }
782}
783
784/// Encodes that `a` must be a subtype of `b`. The `a_is_expected` flag indicates
785/// whether the `a` type is the type that we should label as "expected" when
786/// presenting user diagnostics.
787#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
788#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
789#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
790pub struct SubtypePredicate<I: Interner> {
791    pub a_is_expected: bool,
792    pub a: I::Ty,
793    pub b: I::Ty,
794}
795
796/// Encodes that we have to coerce *from* the `a` type to the `b` type.
797#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
798#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
799#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
800pub struct CoercePredicate<I: Interner> {
801    pub a: I::Ty,
802    pub b: I::Ty,
803}
804
805#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
806#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
807pub enum BoundConstness {
808    /// `Type: const Trait`
809    ///
810    /// A bound is required to be unconditionally const, even in a runtime function.
811    Const,
812    /// `Type: ~const Trait`
813    ///
814    /// Requires resolving to const only when we are in a const context.
815    Maybe,
816}
817
818impl BoundConstness {
819    pub fn satisfies(self, goal: BoundConstness) -> bool {
820        match (self, goal) {
821            (BoundConstness::Const, BoundConstness::Const | BoundConstness::Maybe) => true,
822            (BoundConstness::Maybe, BoundConstness::Maybe) => true,
823            (BoundConstness::Maybe, BoundConstness::Const) => false,
824        }
825    }
826
827    pub fn as_str(self) -> &'static str {
828        match self {
829            Self::Const => "const",
830            Self::Maybe => "~const",
831        }
832    }
833}
834
835impl fmt::Display for BoundConstness {
836    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
837        match self {
838            Self::Const => f.write_str("const"),
839            Self::Maybe => f.write_str("~const"),
840        }
841    }
842}