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