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