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