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