rustc_type_ir/
const_kind.rs

1use std::fmt;
2
3use derive_where::derive_where;
4#[cfg(feature = "nightly")]
5use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
6#[cfg(feature = "nightly")]
7use rustc_macros::{Decodable_NoContext, Encodable_NoContext, HashStable_NoContext};
8use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
9
10use crate::{self as ty, DebruijnIndex, Interner};
11
12/// Represents a constant in Rust.
13#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
14#[cfg_attr(
15    feature = "nightly",
16    derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
17)]
18pub enum ConstKind<I: Interner> {
19    /// A const generic parameter.
20    Param(I::ParamConst),
21
22    /// Infer the value of the const.
23    Infer(InferConst),
24
25    /// Bound const variable, used only when preparing a trait query.
26    Bound(DebruijnIndex, I::BoundConst),
27
28    /// A placeholder const - universally quantified higher-ranked const.
29    Placeholder(I::PlaceholderConst),
30
31    /// An unnormalized const item such as an anon const or assoc const or free const item.
32    /// Right now anything other than anon consts does not actually work properly but this
33    /// should
34    Unevaluated(ty::UnevaluatedConst<I>),
35
36    /// Used to hold computed value.
37    Value(I::ValueConst),
38
39    /// A placeholder for a const which could not be computed; this is
40    /// propagated to avoid useless error messages.
41    Error(I::ErrorGuaranteed),
42
43    /// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
44    /// const arguments such as `N + 1` or `foo(N)`
45    Expr(I::ExprConst),
46}
47
48impl<I: Interner> fmt::Debug for ConstKind<I> {
49    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
50        use ConstKind::*;
51
52        match self {
53            Param(param) => write!(f, "{param:?}"),
54            Infer(var) => write!(f, "{var:?}"),
55            Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
56            Placeholder(placeholder) => write!(f, "{placeholder:?}"),
57            Unevaluated(uv) => write!(f, "{uv:?}"),
58            Value(val) => write!(f, "{val:?}"),
59            Error(_) => write!(f, "{{const error}}"),
60            Expr(expr) => write!(f, "{expr:?}"),
61        }
62    }
63}
64
65/// An unevaluated (potentially generic) constant used in the type-system.
66#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
67#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
68#[cfg_attr(
69    feature = "nightly",
70    derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
71)]
72pub struct UnevaluatedConst<I: Interner> {
73    pub def: I::DefId,
74    pub args: I::GenericArgs,
75}
76
77impl<I: Interner> UnevaluatedConst<I> {
78    #[inline]
79    pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
80        UnevaluatedConst { def, args }
81    }
82}
83
84rustc_index::newtype_index! {
85    /// A **`const`** **v**ariable **ID**.
86    #[encodable]
87    #[orderable]
88    #[debug_format = "?{}c"]
89    #[gate_rustc_only]
90    pub struct ConstVid {}
91}
92
93/// An inference variable for a const, for use in const generics.
94#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
95#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))]
96pub enum InferConst {
97    /// Infer the value of the const.
98    Var(ConstVid),
99    /// A fresh const variable. See `infer::freshen` for more details.
100    Fresh(u32),
101}
102
103impl fmt::Debug for InferConst {
104    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        match self {
106            InferConst::Var(var) => write!(f, "{var:?}"),
107            InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
108        }
109    }
110}
111
112#[cfg(feature = "nightly")]
113impl<CTX> HashStable<CTX> for InferConst {
114    fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
115        match self {
116            InferConst::Var(_) => {
117                panic!("const variables should not be hashed: {self:?}")
118            }
119            InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
120        }
121    }
122}