rustc_type_ir/
predicate_kind.rs

1use std::fmt;
2
3use derive_where::derive_where;
4#[cfg(feature = "nightly")]
5use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
6use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
7
8use crate::{self as ty, Interner};
9
10/// A clause is something that can appear in where bounds or be inferred
11/// by implied bounds.
12#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
13#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
14#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
15pub enum ClauseKind<I: Interner> {
16    /// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
17    /// the `Self` type of the trait reference and `A`, `B`, and `C`
18    /// would be the type parameters.
19    Trait(ty::TraitPredicate<I>),
20
21    /// `where 'a: 'r`
22    RegionOutlives(ty::OutlivesPredicate<I, I::Region>),
23
24    /// `where T: 'r`
25    TypeOutlives(ty::OutlivesPredicate<I, I::Ty>),
26
27    /// `where <T as TraitRef>::Name == X`, approximately.
28    /// See the `ProjectionPredicate` struct for details.
29    Projection(ty::ProjectionPredicate<I>),
30
31    /// Ensures that a const generic argument to a parameter `const N: u8`
32    /// is of type `u8`.
33    ConstArgHasType(I::Const, I::Ty),
34
35    /// No syntax: `T` well-formed.
36    WellFormed(I::GenericArg),
37
38    /// Constant initializer must evaluate successfully.
39    ConstEvaluatable(I::Const),
40
41    /// Enforces the constness of the predicate we're calling. Like a projection
42    /// goal from a where clause, it's always going to be paired with a
43    /// corresponding trait clause; this just enforces the *constness* of that
44    /// implementation.
45    HostEffect(ty::HostEffectPredicate<I>),
46}
47
48#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
49#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
50#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
51pub enum PredicateKind<I: Interner> {
52    /// Prove a clause
53    Clause(ClauseKind<I>),
54
55    /// Trait must be dyn-compatible.
56    DynCompatible(I::DefId),
57
58    /// `T1 <: T2`
59    ///
60    /// This obligation is created most often when we have two
61    /// unresolved type variables and hence don't have enough
62    /// information to process the subtyping obligation yet.
63    Subtype(ty::SubtypePredicate<I>),
64
65    /// `T1` coerced to `T2`
66    ///
67    /// Like a subtyping obligation, this is created most often
68    /// when we have two unresolved type variables and hence
69    /// don't have enough information to process the coercion
70    /// obligation yet. At the moment, we actually process coercions
71    /// very much like subtyping and don't handle the full coercion
72    /// logic.
73    Coerce(ty::CoercePredicate<I>),
74
75    /// Constants must be equal. The first component is the const that is expected.
76    ConstEquate(I::Const, I::Const),
77
78    /// A marker predicate that is always ambiguous.
79    /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous.
80    Ambiguous,
81
82    /// This should only be used inside of the new solver for `AliasRelate` and expects
83    /// the `term` to be always be an unconstrained inference variable. It is used to
84    /// normalize `alias` as much as possible. In case the alias is rigid - i.e. it cannot
85    /// be normalized in the current environment - this constrains `term` to be equal to
86    /// the alias itself.
87    ///
88    /// It is likely more useful to think of this as a function `normalizes_to(alias)`,
89    /// whose return value is written into `term`.
90    NormalizesTo(ty::NormalizesTo<I>),
91
92    /// Separate from `ClauseKind::Projection` which is used for normalization in new solver.
93    /// This predicate requires two terms to be equal to eachother.
94    ///
95    /// Only used for new solver.
96    AliasRelate(I::Term, I::Term, AliasRelationDirection),
97}
98
99#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
100#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))]
101pub enum AliasRelationDirection {
102    Equate,
103    Subtype,
104}
105
106impl std::fmt::Display for AliasRelationDirection {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        match self {
109            AliasRelationDirection::Equate => write!(f, "=="),
110            AliasRelationDirection::Subtype => write!(f, "<:"),
111        }
112    }
113}
114
115impl<I: Interner> fmt::Debug for ClauseKind<I> {
116    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
117        match self {
118            ClauseKind::ConstArgHasType(ct, ty) => write!(f, "ConstArgHasType({ct:?}, {ty:?})"),
119            ClauseKind::HostEffect(data) => data.fmt(f),
120            ClauseKind::Trait(a) => a.fmt(f),
121            ClauseKind::RegionOutlives(pair) => pair.fmt(f),
122            ClauseKind::TypeOutlives(pair) => pair.fmt(f),
123            ClauseKind::Projection(pair) => pair.fmt(f),
124            ClauseKind::WellFormed(data) => write!(f, "WellFormed({data:?})"),
125            ClauseKind::ConstEvaluatable(ct) => {
126                write!(f, "ConstEvaluatable({ct:?})")
127            }
128        }
129    }
130}
131
132impl<I: Interner> fmt::Debug for PredicateKind<I> {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        match self {
135            PredicateKind::Clause(a) => a.fmt(f),
136            PredicateKind::Subtype(pair) => pair.fmt(f),
137            PredicateKind::Coerce(pair) => pair.fmt(f),
138            PredicateKind::DynCompatible(trait_def_id) => {
139                write!(f, "DynCompatible({trait_def_id:?})")
140            }
141            PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({c1:?}, {c2:?})"),
142            PredicateKind::Ambiguous => write!(f, "Ambiguous"),
143            PredicateKind::NormalizesTo(p) => p.fmt(f),
144            PredicateKind::AliasRelate(t1, t2, dir) => {
145                write!(f, "AliasRelate({t1:?}, {dir:?}, {t2:?})")
146            }
147        }
148    }
149}