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