use std::fmt;
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
#[cfg(feature = "nightly")]
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
use crate::{self as ty, DebruijnIndex, Interner};
#[derive_where(Clone, Copy, Hash, PartialEq, Eq; I: Interner)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
pub enum ConstKind<I: Interner> {
Param(I::ParamConst),
Infer(InferConst),
Bound(DebruijnIndex, I::BoundConst),
Placeholder(I::PlaceholderConst),
Unevaluated(ty::UnevaluatedConst<I>),
Value(I::Ty, I::ValueConst),
Error(I::ErrorGuaranteed),
Expr(I::ExprConst),
}
impl<I: Interner> fmt::Debug for ConstKind<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
use ConstKind::*;
match self {
Param(param) => write!(f, "{param:?}"),
Infer(var) => write!(f, "{var:?}"),
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var),
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
Unevaluated(uv) => write!(f, "{uv:?}"),
Value(ty, valtree) => write!(f, "({valtree:?}: {ty:?})"),
Error(_) => write!(f, "{{const error}}"),
Expr(expr) => write!(f, "{expr:?}"),
}
}
}
#[derive_where(Clone, Copy, Debug, Hash, PartialEq, Eq; I: Interner)]
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
pub struct UnevaluatedConst<I: Interner> {
pub def: I::DefId,
pub args: I::GenericArgs,
}
impl<I: Interner> UnevaluatedConst<I> {
#[inline]
pub fn new(def: I::DefId, args: I::GenericArgs) -> UnevaluatedConst<I> {
UnevaluatedConst { def, args }
}
}
rustc_index::newtype_index! {
#[encodable]
#[orderable]
#[debug_format = "?{}c"]
#[gate_rustc_only]
pub struct ConstVid {}
}
rustc_index::newtype_index! {
#[encodable]
#[orderable]
#[debug_format = "?{}e"]
#[gate_rustc_only]
pub struct EffectVid {}
}
#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
pub enum InferConst {
Var(ConstVid),
EffectVar(EffectVid),
Fresh(u32),
}
impl fmt::Debug for InferConst {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
InferConst::Var(var) => write!(f, "{var:?}"),
InferConst::EffectVar(var) => write!(f, "{var:?}"),
InferConst::Fresh(var) => write!(f, "Fresh({var:?})"),
}
}
}
#[cfg(feature = "nightly")]
impl<CTX> HashStable<CTX> for InferConst {
fn hash_stable(&self, hcx: &mut CTX, hasher: &mut StableHasher) {
match self {
InferConst::Var(_) | InferConst::EffectVar(_) => {
panic!("const variables should not be hashed: {self:?}")
}
InferConst::Fresh(i) => i.hash_stable(hcx, hasher),
}
}
}