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::{
9 GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic,
10};
11
12use crate::{self as ty, BoundVarIndexKind, Interner};
13
14#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
16#[derive(GenericTypeVisitable)]
17#[cfg_attr(
18 feature = "nightly",
19 derive(Encodable_NoContext, Decodable_NoContext, HashStable_NoContext)
20)]
21pub enum ConstKind<I: Interner> {
22 Param(I::ParamConst),
24
25 Infer(InferConst),
27
28 Bound(BoundVarIndexKind, I::BoundConst),
30
31 Placeholder(I::PlaceholderConst),
33
34 Unevaluated(ty::UnevaluatedConst<I>),
38
39 Value(I::ValueConst),
41
42 Error(I::ErrorGuaranteed),
45
46 Expr(I::ExprConst),
49}
50
51impl<I: Interner> Eq for ConstKind<I> {}
52
53impl<I: Interner> fmt::Debug for ConstKind<I> {
54 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
55 use ConstKind::*;
56
57 match self {
58 Param(param) => write!(f, "{param:?}"),
59 Infer(var) => write!(f, "{var:?}"),
60 Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
61 Placeholder(placeholder) => write!(f, "{placeholder:?}"),
62 Unevaluated(uv) => write!(f, "{uv:?}"),
63 Value(val) => write!(f, "{val:?}"),
64 Error(_) => write!(f, "{{const error}}"),
65 Expr(expr) => write!(f, "{expr:?}"),
66 }
67 }
68}
69
70#[derive_where(Clone, Copy, Debug, Hash, PartialEq; I: Interner)]
72#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
73#[cfg_attr(
74 feature = "nightly",
75 derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
76)]
77pub struct UnevaluatedConst<I: Interner> {
78 pub def: I::UnevaluatedConstId,
79 pub args: I::GenericArgs,
80}
81
82impl<I: Interner> Eq for UnevaluatedConst<I> {}
83
84impl<I: Interner> UnevaluatedConst<I> {
85 #[inline]
86 pub fn new(def: I::UnevaluatedConstId, args: I::GenericArgs) -> UnevaluatedConst<I> {
87 UnevaluatedConst { def, args }
88 }
89}
90
91rustc_index::newtype_index! {
92 #[encodable]
94 #[orderable]
95 #[debug_format = "?{}c"]
96 #[gate_rustc_only]
97 pub struct ConstVid {}
98}
99
100#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
102#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext))]
103pub enum InferConst {
104 Var(ConstVid),
106 Fresh(u32),
108}
109
110impl fmt::Debug for InferConst {
111 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112 match self {
113 InferConst::Var(var) => write!(f, "{var:?}"),
114 InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
115 }
116 }
117}
118
119#[cfg(feature = "nightly")]
120impl<CTX> HashStable<CTX> for InferConst {
121 fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
122 match self {
123 InferConst::Var(_) => {
124 panic!("const variables should not be hashed: {self:?}")
125 }
126 InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
127 }
128 }
129}
130
131#[derive_where(Clone, Debug, Hash, Eq, PartialEq; I: Interner)]
144#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
145#[cfg_attr(
146 feature = "nightly",
147 derive(Decodable_NoContext, Encodable_NoContext, HashStable_NoContext)
148)]
149pub enum ValTreeKind<I: Interner> {
150 Leaf(I::ScalarInt),
154
155 Branch(Box<[I::Const]>),
164}
165
166impl<I: Interner> ValTreeKind<I> {
167 #[inline]
170 pub fn to_leaf(&self) -> I::ScalarInt {
171 match self {
172 ValTreeKind::Leaf(s) => *s,
173 ValTreeKind::Branch(..) => panic!("expected leaf, got {:?}", self),
174 }
175 }
176
177 #[inline]
180 pub fn to_branch(&self) -> &[I::Const] {
181 match self {
182 ValTreeKind::Branch(branch) => &**branch,
183 ValTreeKind::Leaf(..) => panic!("expected branch, got {:?}", self),
184 }
185 }
186
187 pub fn try_to_leaf(&self) -> Option<I::ScalarInt> {
189 match self {
190 ValTreeKind::Leaf(s) => Some(*s),
191 ValTreeKind::Branch(_) => None,
192 }
193 }
194
195 pub fn try_to_branch(&self) -> Option<&[I::Const]> {
197 match self {
198 ValTreeKind::Branch(branch) => Some(&**branch),
199 ValTreeKind::Leaf(_) => None,
200 }
201 }
202}