Make it possible to derive Lift/TypeVisitable/TypeFoldable in rustc_type_ir
This commit is contained in:
parent
78a7751270
commit
d5797e938a
11
Cargo.lock
11
Cargo.lock
@ -4837,9 +4837,20 @@ dependencies = [
|
||||
"rustc_macros",
|
||||
"rustc_serialize",
|
||||
"rustc_span",
|
||||
"rustc_type_ir_macros",
|
||||
"smallvec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_type_ir_macros"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.62",
|
||||
"synstructure",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc_version"
|
||||
version = "0.4.0"
|
||||
|
@ -11,6 +11,7 @@ rustc_ast_ir = { path = "../rustc_ast_ir" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures", optional = true }
|
||||
rustc_index = { path = "../rustc_index", default-features = false }
|
||||
rustc_macros = { path = "../rustc_macros", optional = true }
|
||||
rustc_type_ir_macros = { path = "../rustc_type_ir_macros" }
|
||||
rustc_serialize = { path = "../rustc_serialize", optional = true }
|
||||
rustc_span = { path = "../rustc_span", optional = true }
|
||||
smallvec = { version = "1.8.1" }
|
||||
|
@ -1,20 +1,25 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
use std::hash::Hash;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::inherent::*;
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::{Interner, UniverseIndex};
|
||||
|
||||
/// A "canonicalized" type `V` is one where all free inference
|
||||
/// variables have been rewritten to "canonical vars". These are
|
||||
/// numbered starting from 0 in order of first appearance.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = "V: Clone"), Hash(bound = "V: Hash"))]
|
||||
#[derivative(
|
||||
Clone(bound = "V: Clone"),
|
||||
Hash(bound = "V: Hash"),
|
||||
PartialEq(bound = "V: PartialEq"),
|
||||
Eq(bound = "V: Eq"),
|
||||
Debug(bound = "V: fmt::Debug"),
|
||||
Copy(bound = "V: Copy")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub struct Canonical<I: Interner, V> {
|
||||
pub value: V,
|
||||
@ -64,18 +69,6 @@ impl<I: Interner, V> Canonical<I, V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: Eq> Eq for Canonical<I, V> {}
|
||||
|
||||
impl<I: Interner, V: PartialEq> PartialEq for Canonical<I, V> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
*value == other.value
|
||||
&& *max_universe == other.max_universe
|
||||
&& *variables == other.variables
|
||||
&& *defining_opaque_types == other.defining_opaque_types
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
@ -86,84 +79,25 @@ impl<I: Interner, V: fmt::Display> fmt::Display for Canonical<I, V> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: fmt::Debug> fmt::Debug for Canonical<I, V> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
f.debug_struct("Canonical")
|
||||
.field("value", &value)
|
||||
.field("max_universe", &max_universe)
|
||||
.field("variables", &variables)
|
||||
.field("defining_opaque_types", &defining_opaque_types)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: Copy> Copy for Canonical<I, V> where I::CanonicalVars: Copy {}
|
||||
|
||||
impl<I: Interner, V: TypeFoldable<I>> TypeFoldable<I> for Canonical<I, V>
|
||||
where
|
||||
I::CanonicalVars: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(Canonical {
|
||||
value: self.value.try_fold_with(folder)?,
|
||||
max_universe: self.max_universe.try_fold_with(folder)?,
|
||||
variables: self.variables.try_fold_with(folder)?,
|
||||
defining_opaque_types: self.defining_opaque_types,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner, V: TypeVisitable<I>> TypeVisitable<I> for Canonical<I, V>
|
||||
where
|
||||
I::CanonicalVars: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<F: TypeVisitor<I>>(&self, folder: &mut F) -> F::Result {
|
||||
let Self { value, max_universe, variables, defining_opaque_types } = self;
|
||||
try_visit!(value.visit_with(folder));
|
||||
try_visit!(max_universe.visit_with(folder));
|
||||
try_visit!(defining_opaque_types.visit_with(folder));
|
||||
variables.visit_with(folder)
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about a canonical variable that is included with the
|
||||
/// canonical value. This is sufficient information for code to create
|
||||
/// a copy of the canonical value in some other inference context,
|
||||
/// with fresh inference variables replacing the canonical values.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
Copy(bound = ""),
|
||||
Hash(bound = ""),
|
||||
Debug(bound = ""),
|
||||
Eq(bound = ""),
|
||||
PartialEq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct CanonicalVarInfo<I: Interner> {
|
||||
pub kind: CanonicalVarKind<I>,
|
||||
}
|
||||
|
||||
impl<I: Interner> PartialEq for CanonicalVarInfo<I> {
|
||||
fn eq(&self, other: &Self) -> bool {
|
||||
self.kind == other.kind
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for CanonicalVarInfo<I> {}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for CanonicalVarInfo<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.kind.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for CanonicalVarInfo<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(CanonicalVarInfo { kind: self.kind.try_fold_with(folder)? })
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarInfo<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
self.kind.universe()
|
||||
@ -216,6 +150,7 @@ impl<I: Interner> CanonicalVarInfo<I> {
|
||||
/// that analyzes type-like values.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Debug(bound = ""))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum CanonicalVarKind<I: Interner> {
|
||||
/// Some kind of type inference variable.
|
||||
@ -258,51 +193,6 @@ impl<I: Interner> PartialEq for CanonicalVarKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for CanonicalVarKind<I> {}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for CanonicalVarKind<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
CanonicalVarKind::Ty(_)
|
||||
| CanonicalVarKind::PlaceholderTy(_)
|
||||
| CanonicalVarKind::Region(_)
|
||||
| CanonicalVarKind::PlaceholderRegion(_)
|
||||
| CanonicalVarKind::Effect => V::Result::output(),
|
||||
CanonicalVarKind::Const(_, ty) | CanonicalVarKind::PlaceholderConst(_, ty) => {
|
||||
ty.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for CanonicalVarKind<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
CanonicalVarKind::Ty(kind) => CanonicalVarKind::Ty(kind),
|
||||
CanonicalVarKind::Region(kind) => CanonicalVarKind::Region(kind),
|
||||
CanonicalVarKind::Const(kind, ty) => {
|
||||
CanonicalVarKind::Const(kind, ty.try_fold_with(folder)?)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderTy(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderTy(placeholder)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder) => {
|
||||
CanonicalVarKind::PlaceholderRegion(placeholder)
|
||||
}
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
|
||||
CanonicalVarKind::PlaceholderConst(placeholder, ty.try_fold_with(folder)?)
|
||||
}
|
||||
CanonicalVarKind::Effect => CanonicalVarKind::Effect,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> CanonicalVarKind<I> {
|
||||
pub fn universe(self) -> UniverseIndex {
|
||||
match self {
|
||||
@ -355,6 +245,7 @@ impl<I: Interner> CanonicalVarKind<I> {
|
||||
/// usize or f32). In order to faithfully reproduce a type, we need to
|
||||
/// know what set of types a given type variable can be unified with.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub enum CanonicalTyVarKind {
|
||||
/// General type variable `?T` that can be unified with arbitrary types.
|
||||
|
@ -10,7 +10,7 @@ use self::ConstKind::*;
|
||||
|
||||
/// Represents a constant in Rust.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ConstKind<I: Interner> {
|
||||
/// A const generic parameter.
|
||||
@ -58,8 +58,6 @@ impl<I: Interner> PartialEq for ConstKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for ConstKind<I> {}
|
||||
|
||||
impl<I: Interner> fmt::Debug for ConstKind<I> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
WithInfcx::with_no_infcx(self).fmt(f)
|
||||
|
@ -1,17 +1,15 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
use rustc_ast_ir::visit::VisitorResult;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
|
||||
/// A clause is something that can appear in where bounds or be inferred
|
||||
/// by implied bounds.
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum ClauseKind<I: Interner> {
|
||||
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
|
||||
@ -55,61 +53,6 @@ impl<I: Interner> PartialEq for ClauseKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> Eq for ClauseKind<I> {}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for ClauseKind<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
I::Const: TypeFoldable<I>,
|
||||
I::GenericArg: TypeFoldable<I>,
|
||||
I::TraitPredicate: TypeFoldable<I>,
|
||||
I::ProjectionPredicate: TypeFoldable<I>,
|
||||
I::TypeOutlivesPredicate: TypeFoldable<I>,
|
||||
I::RegionOutlivesPredicate: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
ClauseKind::Trait(p) => ClauseKind::Trait(p.try_fold_with(folder)?),
|
||||
ClauseKind::RegionOutlives(p) => ClauseKind::RegionOutlives(p.try_fold_with(folder)?),
|
||||
ClauseKind::TypeOutlives(p) => ClauseKind::TypeOutlives(p.try_fold_with(folder)?),
|
||||
ClauseKind::Projection(p) => ClauseKind::Projection(p.try_fold_with(folder)?),
|
||||
ClauseKind::ConstArgHasType(c, t) => {
|
||||
ClauseKind::ConstArgHasType(c.try_fold_with(folder)?, t.try_fold_with(folder)?)
|
||||
}
|
||||
ClauseKind::WellFormed(p) => ClauseKind::WellFormed(p.try_fold_with(folder)?),
|
||||
ClauseKind::ConstEvaluatable(p) => {
|
||||
ClauseKind::ConstEvaluatable(p.try_fold_with(folder)?)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for ClauseKind<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
I::Const: TypeVisitable<I>,
|
||||
I::GenericArg: TypeVisitable<I>,
|
||||
I::TraitPredicate: TypeVisitable<I>,
|
||||
I::ProjectionPredicate: TypeVisitable<I>,
|
||||
I::TypeOutlivesPredicate: TypeVisitable<I>,
|
||||
I::RegionOutlivesPredicate: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
ClauseKind::Trait(p) => p.visit_with(visitor),
|
||||
ClauseKind::RegionOutlives(p) => p.visit_with(visitor),
|
||||
ClauseKind::TypeOutlives(p) => p.visit_with(visitor),
|
||||
ClauseKind::Projection(p) => p.visit_with(visitor),
|
||||
ClauseKind::ConstArgHasType(c, t) => {
|
||||
try_visit!(c.visit_with(visitor));
|
||||
t.visit_with(visitor)
|
||||
}
|
||||
ClauseKind::WellFormed(p) => p.visit_with(visitor),
|
||||
ClauseKind::ConstEvaluatable(p) => p.visit_with(visitor),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(
|
||||
Clone(bound = ""),
|
||||
@ -118,6 +61,7 @@ where
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum PredicateKind<I: Interner> {
|
||||
/// Prove a clause
|
||||
@ -167,69 +111,6 @@ pub enum PredicateKind<I: Interner> {
|
||||
AliasRelate(I::Term, I::Term, AliasRelationDirection),
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for PredicateKind<I>
|
||||
where
|
||||
I::DefId: TypeFoldable<I>,
|
||||
I::Const: TypeFoldable<I>,
|
||||
I::GenericArgs: TypeFoldable<I>,
|
||||
I::Term: TypeFoldable<I>,
|
||||
I::CoercePredicate: TypeFoldable<I>,
|
||||
I::SubtypePredicate: TypeFoldable<I>,
|
||||
I::NormalizesTo: TypeFoldable<I>,
|
||||
ClauseKind<I>: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(match self {
|
||||
PredicateKind::Clause(c) => PredicateKind::Clause(c.try_fold_with(folder)?),
|
||||
PredicateKind::ObjectSafe(d) => PredicateKind::ObjectSafe(d.try_fold_with(folder)?),
|
||||
PredicateKind::Subtype(s) => PredicateKind::Subtype(s.try_fold_with(folder)?),
|
||||
PredicateKind::Coerce(s) => PredicateKind::Coerce(s.try_fold_with(folder)?),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
PredicateKind::ConstEquate(a.try_fold_with(folder)?, b.try_fold_with(folder)?)
|
||||
}
|
||||
PredicateKind::Ambiguous => PredicateKind::Ambiguous,
|
||||
PredicateKind::NormalizesTo(p) => PredicateKind::NormalizesTo(p.try_fold_with(folder)?),
|
||||
PredicateKind::AliasRelate(a, b, d) => PredicateKind::AliasRelate(
|
||||
a.try_fold_with(folder)?,
|
||||
b.try_fold_with(folder)?,
|
||||
d.try_fold_with(folder)?,
|
||||
),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for PredicateKind<I>
|
||||
where
|
||||
I::DefId: TypeVisitable<I>,
|
||||
I::Const: TypeVisitable<I>,
|
||||
I::GenericArgs: TypeVisitable<I>,
|
||||
I::Term: TypeVisitable<I>,
|
||||
I::CoercePredicate: TypeVisitable<I>,
|
||||
I::SubtypePredicate: TypeVisitable<I>,
|
||||
I::NormalizesTo: TypeVisitable<I>,
|
||||
ClauseKind<I>: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
match self {
|
||||
PredicateKind::Clause(p) => p.visit_with(visitor),
|
||||
PredicateKind::ObjectSafe(d) => d.visit_with(visitor),
|
||||
PredicateKind::Subtype(s) => s.visit_with(visitor),
|
||||
PredicateKind::Coerce(s) => s.visit_with(visitor),
|
||||
PredicateKind::ConstEquate(a, b) => {
|
||||
try_visit!(a.visit_with(visitor));
|
||||
b.visit_with(visitor)
|
||||
}
|
||||
PredicateKind::Ambiguous => V::Result::output(),
|
||||
PredicateKind::NormalizesTo(p) => p.visit_with(visitor),
|
||||
PredicateKind::AliasRelate(a, b, d) => {
|
||||
try_visit!(a.visit_with(visitor));
|
||||
try_visit!(b.visit_with(visitor));
|
||||
d.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
|
||||
#[cfg_attr(feature = "nightly", derive(HashStable_NoContext, Encodable, Decodable))]
|
||||
pub enum AliasRelationDirection {
|
||||
|
@ -115,7 +115,7 @@ use self::RegionKind::*;
|
||||
/// [2]: https://smallcultfollowing.com/babysteps/blog/2013/11/04/intermingled-parameter-lists/
|
||||
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/traits/hrtb.html
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable))]
|
||||
pub enum RegionKind<I: Interner> {
|
||||
/// A region parameter; for example `'a` in `impl<'a> Trait for &'a ()`.
|
||||
@ -208,9 +208,6 @@ impl<I: Interner> PartialEq for RegionKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Eq`
|
||||
impl<I: Interner> Eq for RegionKind<I> {}
|
||||
|
||||
impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
|
||||
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
|
@ -1,9 +1,7 @@
|
||||
use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::inherent::*;
|
||||
use crate::lift::Lift;
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
|
||||
/// A complete reference to a trait. These take numerous guises in syntax,
|
||||
@ -25,6 +23,7 @@ use crate::Interner;
|
||||
PartialEq(bound = ""),
|
||||
Eq(bound = "")
|
||||
)]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic, Lift_Generic)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
|
||||
pub struct TraitRef<I: Interner> {
|
||||
pub def_id: I::DefId,
|
||||
@ -68,42 +67,3 @@ impl<I: Interner> TraitRef<I> {
|
||||
self.args.type_at(0)
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME(compiler-errors): Make this into a `Lift_Generic` impl.
|
||||
impl<I: Interner, U: Interner> Lift<U> for TraitRef<I>
|
||||
where
|
||||
I::DefId: Lift<U, Lifted = U::DefId>,
|
||||
I::GenericArgs: Lift<U, Lifted = U::GenericArgs>,
|
||||
{
|
||||
type Lifted = TraitRef<U>;
|
||||
|
||||
fn lift_to_tcx(self, tcx: U) -> Option<Self::Lifted> {
|
||||
Some(TraitRef {
|
||||
def_id: self.def_id.lift_to_tcx(tcx)?,
|
||||
args: self.args.lift_to_tcx(tcx)?,
|
||||
_use_trait_ref_new_instead: (),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for TraitRef<I>
|
||||
where
|
||||
I::GenericArgs: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
self.args.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for TraitRef<I>
|
||||
where
|
||||
I::GenericArgs: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(TraitRef {
|
||||
def_id: self.def_id,
|
||||
args: self.args.try_fold_with(folder)?,
|
||||
_use_trait_ref_new_instead: (),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -1,14 +1,12 @@
|
||||
use rustc_ast_ir::try_visit;
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_data_structures::unify::{EqUnifyValue, UnifyKey};
|
||||
#[cfg(feature = "nightly")]
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_NoContext, TyDecodable, TyEncodable};
|
||||
use rustc_type_ir_macros::{TypeFoldable_Generic, TypeVisitable_Generic};
|
||||
use std::fmt;
|
||||
|
||||
use crate::fold::{FallibleTypeFolder, TypeFoldable};
|
||||
use crate::visit::{TypeVisitable, TypeVisitor};
|
||||
use crate::Interner;
|
||||
use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, WithInfcx};
|
||||
|
||||
@ -65,7 +63,7 @@ impl AliasKind {
|
||||
/// converted to this representation using `<dyn HirTyLowerer>::lower_ty`.
|
||||
#[cfg_attr(feature = "nightly", rustc_diagnostic_item = "IrTyKind")]
|
||||
#[derive(derivative::Derivative)]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""))]
|
||||
#[derivative(Clone(bound = ""), Copy(bound = ""), Hash(bound = ""), Eq(bound = ""))]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
pub enum TyKind<I: Interner> {
|
||||
/// The primitive boolean type. Written as `bool`.
|
||||
@ -341,9 +339,6 @@ impl<I: Interner> PartialEq for TyKind<I> {
|
||||
}
|
||||
}
|
||||
|
||||
// This is manually implemented because a derive would require `I: Eq`
|
||||
impl<I: Interner> Eq for TyKind<I> {}
|
||||
|
||||
impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
|
||||
fn fmt<Infcx: InferCtxtLike<Interner = I>>(
|
||||
this: WithInfcx<'_, Infcx, &Self>,
|
||||
@ -804,29 +799,8 @@ impl<I: Interner> DebugWithInfcx<I> for InferTy {
|
||||
Debug(bound = "")
|
||||
)]
|
||||
#[cfg_attr(feature = "nightly", derive(TyEncodable, TyDecodable, HashStable_NoContext))]
|
||||
#[derive(TypeVisitable_Generic, TypeFoldable_Generic)]
|
||||
pub struct TypeAndMut<I: Interner> {
|
||||
pub ty: I::Ty,
|
||||
pub mutbl: Mutability,
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeFoldable<I> for TypeAndMut<I>
|
||||
where
|
||||
I::Ty: TypeFoldable<I>,
|
||||
{
|
||||
fn try_fold_with<F: FallibleTypeFolder<I>>(self, folder: &mut F) -> Result<Self, F::Error> {
|
||||
Ok(TypeAndMut {
|
||||
ty: self.ty.try_fold_with(folder)?,
|
||||
mutbl: self.mutbl.try_fold_with(folder)?,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl<I: Interner> TypeVisitable<I> for TypeAndMut<I>
|
||||
where
|
||||
I::Ty: TypeVisitable<I>,
|
||||
{
|
||||
fn visit_with<V: TypeVisitor<I>>(&self, visitor: &mut V) -> V::Result {
|
||||
try_visit!(self.ty.visit_with(visitor));
|
||||
self.mutbl.visit_with(visitor)
|
||||
}
|
||||
}
|
||||
|
15
compiler/rustc_type_ir_macros/Cargo.toml
Normal file
15
compiler/rustc_type_ir_macros/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "rustc_type_ir_macros"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[lib]
|
||||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
proc-macro2 = "1"
|
||||
quote = "1"
|
||||
syn = { version = "2.0.9", features = ["full"] }
|
||||
synstructure = "0.13.0"
|
||||
# tidy-alphabetical-end
|
159
compiler/rustc_type_ir_macros/src/lib.rs
Normal file
159
compiler/rustc_type_ir_macros/src/lib.rs
Normal file
@ -0,0 +1,159 @@
|
||||
use synstructure::decl_derive;
|
||||
use quote::quote;
|
||||
use syn::{parse_quote, visit_mut::VisitMut};
|
||||
|
||||
decl_derive!(
|
||||
[TypeFoldable_Generic] => type_foldable_derive
|
||||
);
|
||||
decl_derive!(
|
||||
[TypeVisitable_Generic] => type_visitable_derive
|
||||
);
|
||||
decl_derive!(
|
||||
[Lift_Generic] => lift_derive
|
||||
);
|
||||
|
||||
fn type_foldable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_bounds(synstructure::AddBounds::Fields);
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
let body_fold = s.each_variant(|vi| {
|
||||
let bindings = vi.bindings();
|
||||
vi.construct(|_, index| {
|
||||
let bind = &bindings[index];
|
||||
quote! {
|
||||
::rustc_type_ir::fold::TypeFoldable::try_fold_with(#bind, __folder)?
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::fold::TypeFoldable<I>),
|
||||
quote! {
|
||||
fn try_fold_with<__F: ::rustc_type_ir::fold::FallibleTypeFolder<I>>(
|
||||
self,
|
||||
__folder: &mut __F
|
||||
) -> Result<Self, __F::Error> {
|
||||
Ok(match self { #body_fold })
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_bounds(synstructure::AddBounds::None);
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_impl_generic(parse_quote! { J });
|
||||
s.add_where_predicate(parse_quote! { J: Interner });
|
||||
|
||||
let mut wc = vec![];
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
let body_fold = s.each_variant(|vi| {
|
||||
let bindings = vi.bindings();
|
||||
vi.construct(|field, index| {
|
||||
let ty = field.ty.clone();
|
||||
let lifted_ty = lift(ty.clone());
|
||||
wc.push(parse_quote! { #ty: ::rustc_type_ir::lift::Lift<J, Lifted = #lifted_ty> });
|
||||
let bind = &bindings[index];
|
||||
quote! {
|
||||
#bind.lift_to_tcx(interner)?
|
||||
}
|
||||
})
|
||||
});
|
||||
for wc in wc {
|
||||
s.add_where_predicate(wc);
|
||||
}
|
||||
|
||||
let (_, ty_generics, _) = s.ast().generics.split_for_impl();
|
||||
let name = s.ast().ident.clone();
|
||||
let self_ty: syn::Type = parse_quote! { #name #ty_generics };
|
||||
let lifted_ty = lift(self_ty);
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::lift::Lift<J>),
|
||||
quote! {
|
||||
type Lifted = #lifted_ty;
|
||||
|
||||
fn lift_to_tcx(
|
||||
self,
|
||||
interner: J,
|
||||
) -> Option<Self::Lifted> {
|
||||
Some(match self { #body_fold })
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
fn lift(mut ty: syn::Type) -> syn::Type {
|
||||
struct ItoJ;
|
||||
impl VisitMut for ItoJ {
|
||||
fn visit_type_path_mut(&mut self, i: &mut syn::TypePath) {
|
||||
if i.qself.is_none() {
|
||||
if let Some(first) = i.path.segments.first_mut() {
|
||||
if first.ident == "I" {
|
||||
*first = parse_quote! { J };
|
||||
}
|
||||
}
|
||||
}
|
||||
syn::visit_mut::visit_type_path_mut(self, i);
|
||||
}
|
||||
}
|
||||
|
||||
ItoJ.visit_type_mut(&mut ty);
|
||||
|
||||
ty
|
||||
}
|
||||
|
||||
fn type_visitable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
|
||||
if let syn::Data::Union(_) = s.ast().data {
|
||||
panic!("cannot derive on union")
|
||||
}
|
||||
|
||||
if !s.ast().generics.type_params().any(|ty| ty.ident == "I") {
|
||||
s.add_impl_generic(parse_quote! { I });
|
||||
}
|
||||
|
||||
s.add_where_predicate(parse_quote! { I: Interner });
|
||||
s.add_bounds(synstructure::AddBounds::Fields);
|
||||
let body_visit = s.each(|bind| {
|
||||
quote! {
|
||||
match ::rustc_ast_ir::visit::VisitorResult::branch(
|
||||
::rustc_type_ir::visit::TypeVisitable::visit_with(#bind, __visitor)
|
||||
) {
|
||||
::core::ops::ControlFlow::Continue(()) => {},
|
||||
::core::ops::ControlFlow::Break(r) => {
|
||||
return ::rustc_ast_ir::visit::VisitorResult::from_residual(r);
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
s.bind_with(|_| synstructure::BindStyle::Move);
|
||||
|
||||
s.bound_impl(
|
||||
quote!(::rustc_type_ir::visit::TypeVisitable<I>),
|
||||
quote! {
|
||||
fn visit_with<__V: ::rustc_type_ir::visit::TypeVisitor<I>>(
|
||||
&self,
|
||||
__visitor: &mut __V
|
||||
) -> __V::Result {
|
||||
match *self { #body_visit }
|
||||
<__V::Result as ::rustc_ast_ir::visit::VisitorResult>::output()
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user