Skip to content

Commit

Permalink
Move some files around
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Oct 20, 2023
1 parent 5ceda6b commit c3fd438
Show file tree
Hide file tree
Showing 12 changed files with 1,548 additions and 1,520 deletions.
258 changes: 258 additions & 0 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,258 @@
use rustc_data_structures::stable_hasher::HashStable;
use rustc_serialize::{Decodable, Decoder, Encodable};
use std::cmp::Ordering;
use std::fmt;
use std::hash;

use crate::{
DebruijnIndex, DebugWithInfcx, HashStableContext, InferCtxtLike, Interner, OptWithInfcx,
TyDecoder, TyEncoder,
};

use self::ConstKind::*;

/// Represents a constant in Rust.
// #[derive(derive_more::From)]
pub enum ConstKind<I: Interner> {
/// A const generic parameter.
Param(I::ParamConst),

/// Infer the value of the const.
Infer(I::InferConst),

/// Bound const variable, used only when preparing a trait query.
Bound(DebruijnIndex, I::BoundConst),

/// A placeholder const - universally quantified higher-ranked const.
Placeholder(I::PlaceholderConst),

/// An unnormalized const item such as an anon const or assoc const or free const item.
/// Right now anything other than anon consts does not actually work properly but this
/// should
Unevaluated(I::AliasConst),

/// Used to hold computed value.
Value(I::ValueConst),

/// A placeholder for a const which could not be computed; this is
/// propagated to avoid useless error messages.
Error(I::ErrorGuaranteed),

/// Unevaluated non-const-item, used by `feature(generic_const_exprs)` to represent
/// const arguments such as `N + 1` or `foo(N)`
Expr(I::ExprConst),
}

const fn const_kind_discriminant<I: Interner>(value: &ConstKind<I>) -> usize {
match value {
Param(_) => 0,
Infer(_) => 1,
Bound(_, _) => 2,
Placeholder(_) => 3,
Unevaluated(_) => 4,
Value(_) => 5,
Error(_) => 6,
Expr(_) => 7,
}
}

impl<I: Interner> hash::Hash for ConstKind<I> {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
const_kind_discriminant(self).hash(state);
match self {
Param(p) => p.hash(state),
Infer(i) => i.hash(state),
Bound(d, b) => {
d.hash(state);
b.hash(state);
}
Placeholder(p) => p.hash(state),
Unevaluated(u) => u.hash(state),
Value(v) => v.hash(state),
Error(e) => e.hash(state),
Expr(e) => e.hash(state),
}
}
}

impl<CTX: HashStableContext, I: Interner> HashStable<CTX> for ConstKind<I>
where
I::ParamConst: HashStable<CTX>,
I::InferConst: HashStable<CTX>,
I::BoundConst: HashStable<CTX>,
I::PlaceholderConst: HashStable<CTX>,
I::AliasConst: HashStable<CTX>,
I::ValueConst: HashStable<CTX>,
I::ErrorGuaranteed: HashStable<CTX>,
I::ExprConst: HashStable<CTX>,
{
fn hash_stable(
&self,
hcx: &mut CTX,
hasher: &mut rustc_data_structures::stable_hasher::StableHasher,
) {
const_kind_discriminant(self).hash_stable(hcx, hasher);
match self {
Param(p) => p.hash_stable(hcx, hasher),
Infer(i) => i.hash_stable(hcx, hasher),
Bound(d, b) => {
d.hash_stable(hcx, hasher);
b.hash_stable(hcx, hasher);
}
Placeholder(p) => p.hash_stable(hcx, hasher),
Unevaluated(u) => u.hash_stable(hcx, hasher),
Value(v) => v.hash_stable(hcx, hasher),
Error(e) => e.hash_stable(hcx, hasher),
Expr(e) => e.hash_stable(hcx, hasher),
}
}
}

impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ConstKind<I>
where
I::ParamConst: Decodable<D>,
I::InferConst: Decodable<D>,
I::BoundConst: Decodable<D>,
I::PlaceholderConst: Decodable<D>,
I::AliasConst: Decodable<D>,
I::ValueConst: Decodable<D>,
I::ErrorGuaranteed: Decodable<D>,
I::ExprConst: Decodable<D>,
{
fn decode(d: &mut D) -> Self {
match Decoder::read_usize(d) {
0 => Param(Decodable::decode(d)),
1 => Infer(Decodable::decode(d)),
2 => Bound(Decodable::decode(d), Decodable::decode(d)),
3 => Placeholder(Decodable::decode(d)),
4 => Unevaluated(Decodable::decode(d)),
5 => Value(Decodable::decode(d)),
6 => Error(Decodable::decode(d)),
7 => Expr(Decodable::decode(d)),
_ => panic!(
"{}",
format!(
"invalid enum variant tag while decoding `{}`, expected 0..{}",
"ConstKind", 8,
)
),
}
}
}

impl<I: Interner, E: TyEncoder<I = I>> Encodable<E> for ConstKind<I>
where
I::ParamConst: Encodable<E>,
I::InferConst: Encodable<E>,
I::BoundConst: Encodable<E>,
I::PlaceholderConst: Encodable<E>,
I::AliasConst: Encodable<E>,
I::ValueConst: Encodable<E>,
I::ErrorGuaranteed: Encodable<E>,
I::ExprConst: Encodable<E>,
{
fn encode(&self, e: &mut E) {
let disc = const_kind_discriminant(self);
match self {
Param(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
Infer(i) => e.emit_enum_variant(disc, |e| i.encode(e)),
Bound(d, b) => e.emit_enum_variant(disc, |e| {
d.encode(e);
b.encode(e);
}),
Placeholder(p) => e.emit_enum_variant(disc, |e| p.encode(e)),
Unevaluated(u) => e.emit_enum_variant(disc, |e| u.encode(e)),
Value(v) => e.emit_enum_variant(disc, |e| v.encode(e)),
Error(er) => e.emit_enum_variant(disc, |e| er.encode(e)),
Expr(ex) => e.emit_enum_variant(disc, |e| ex.encode(e)),
}
}
}

impl<I: Interner> PartialOrd for ConstKind<I> {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl<I: Interner> Ord for ConstKind<I> {
fn cmp(&self, other: &Self) -> Ordering {
const_kind_discriminant(self)
.cmp(&const_kind_discriminant(other))
.then_with(|| match (self, other) {
(Param(p1), Param(p2)) => p1.cmp(p2),
(Infer(i1), Infer(i2)) => i1.cmp(i2),
(Bound(d1, b1), Bound(d2, b2)) => d1.cmp(d2).then_with(|| b1.cmp(b2)),
(Placeholder(p1), Placeholder(p2)) => p1.cmp(p2),
(Unevaluated(u1), Unevaluated(u2)) => u1.cmp(u2),
(Value(v1), Value(v2)) => v1.cmp(v2),
(Error(e1), Error(e2)) => e1.cmp(e2),
(Expr(e1), Expr(e2)) => e1.cmp(e2),
_ => {
debug_assert!(false, "This branch must be unreachable, maybe the match is missing an arm? self = {self:?}, other = {other:?}");
Ordering::Equal
}
})
}
}

impl<I: Interner> PartialEq for ConstKind<I> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Param(l0), Param(r0)) => l0 == r0,
(Infer(l0), Infer(r0)) => l0 == r0,
(Bound(l0, l1), Bound(r0, r1)) => l0 == r0 && l1 == r1,
(Placeholder(l0), Placeholder(r0)) => l0 == r0,
(Unevaluated(l0), Unevaluated(r0)) => l0 == r0,
(Value(l0), Value(r0)) => l0 == r0,
(Error(l0), Error(r0)) => l0 == r0,
(Expr(l0), Expr(r0)) => l0 == r0,
_ => false,
}
}
}

impl<I: Interner> Eq for ConstKind<I> {}

impl<I: Interner> Clone for ConstKind<I> {
fn clone(&self) -> Self {
match self {
Param(arg0) => Param(arg0.clone()),
Infer(arg0) => Infer(arg0.clone()),
Bound(arg0, arg1) => Bound(arg0.clone(), arg1.clone()),
Placeholder(arg0) => Placeholder(arg0.clone()),
Unevaluated(arg0) => Unevaluated(arg0.clone()),
Value(arg0) => Value(arg0.clone()),
Error(arg0) => Error(arg0.clone()),
Expr(arg0) => Expr(arg0.clone()),
}
}
}

impl<I: Interner> fmt::Debug for ConstKind<I> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
OptWithInfcx::new_no_ctx(self).fmt(f)
}
}

impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
fn fmt<InfCtx: InferCtxtLike<I>>(
this: OptWithInfcx<'_, I, InfCtx, &Self>,
f: &mut core::fmt::Formatter<'_>,
) -> core::fmt::Result {
use ConstKind::*;

match this.data {
Param(param) => write!(f, "{param:?}"),
Infer(var) => write!(f, "{:?}", &this.wrap(var)),
Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
Placeholder(placeholder) => write!(f, "{placeholder:?}"),
Unevaluated(uv) => {
write!(f, "{:?}", &this.wrap(uv))
}
Value(valtree) => write!(f, "{valtree:?}"),
Error(_) => write!(f, "{{const error}}"),
Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
}
}
}
117 changes: 117 additions & 0 deletions compiler/rustc_type_ir/src/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
use crate::{Interner, UniverseIndex};

use core::fmt;
use std::marker::PhantomData;

pub trait InferCtxtLike<I: Interner> {
fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;

fn universe_of_lt(&self, lt: I::InferRegion) -> Option<UniverseIndex>;

fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
}

impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
match *self {}
}

fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
match *self {}
}

fn universe_of_lt(&self, _lt: <I as Interner>::InferRegion) -> Option<UniverseIndex> {
match *self {}
}
}

pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
fn fmt<InfCtx: InferCtxtLike<I>>(
this: OptWithInfcx<'_, I, InfCtx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result;
}

impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
fn fmt<InfCtx: InferCtxtLike<I>>(
this: OptWithInfcx<'_, I, InfCtx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
<T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
}
}

impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
fn fmt<InfCtx: InferCtxtLike<I>>(
this: OptWithInfcx<'_, I, InfCtx, &Self>,
f: &mut fmt::Formatter<'_>,
) -> fmt::Result {
match f.alternate() {
true => {
write!(f, "[\n")?;
for element in this.data.iter() {
write!(f, "{:?},\n", &this.wrap(element))?;
}
write!(f, "]")
}
false => {
write!(f, "[")?;
if this.data.len() > 0 {
for element in &this.data[..(this.data.len() - 1)] {
write!(f, "{:?}, ", &this.wrap(element))?;
}
if let Some(element) = this.data.last() {
write!(f, "{:?}", &this.wrap(element))?;
}
}
write!(f, "]")
}
}
}
}

pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
pub data: T,
pub infcx: Option<&'a InfCtx>,
_interner: PhantomData<I>,
}

impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}

impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
fn clone(&self) -> Self {
Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
}
}

impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
pub fn new_no_ctx(data: T) -> Self {
Self { data, infcx: None, _interner: PhantomData }
}
}

impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
pub fn new(data: T, infcx: &'a InfCtx) -> Self {
Self { data, infcx: Some(infcx), _interner: PhantomData }
}

pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
}

pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
}

pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
}
}

impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
for OptWithInfcx<'_, I, InfCtx, T>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
DebugWithInfcx::fmt(self.as_ref(), f)
}
}
Loading

0 comments on commit c3fd438

Please sign in to comment.