Skip to content

Commit

Permalink
Auto merge of #117578 - compiler-errors:derive-encode-in-rustc_type_i…
Browse files Browse the repository at this point in the history
…r, r=davidtwco

Derive `TyEncodable`/`TyDecodable` in `rustc_type_ir`

when `derive(TyEncodable)` or `derive(TyDecodable)` sees an `I` type parameter on a struct that has no `'tcx`, then parameterize the `TyEncoder`/`TyDecoder`'s interner over that variable rather than `TyCtxt<'tcx>`.

Also, emit where clauses for fields rather than generics.
  • Loading branch information
bors committed Nov 6, 2023
2 parents f9b6446 + bee7b58 commit 6bf2fb3
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 486 deletions.
30 changes: 20 additions & 10 deletions compiler/rustc_macros/src/serialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,16 @@ use syn::spanned::Spanned;

pub fn type_decodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
let decoder_ty = quote! { __D };
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! { 'tcx });
}
s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder<I = ::rustc_middle::ty::TyCtxt<'tcx>>});
s.add_bounds(synstructure::AddBounds::Generics);
let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
} else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
quote! { <I = I> }
} else {
quote! {}
};

s.add_impl_generic(parse_quote! {#decoder_ty: ::rustc_type_ir::codec::TyDecoder #bound });
s.add_bounds(synstructure::AddBounds::Fields);

decodable_body(s, decoder_ty)
}
Expand Down Expand Up @@ -97,12 +102,17 @@ fn decode_field(field: &syn::Field) -> proc_macro2::TokenStream {
}

pub fn type_encodable_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
if !s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
s.add_impl_generic(parse_quote! {'tcx});
}
let bound = if s.ast().generics.lifetimes().any(|lt| lt.lifetime.ident == "tcx") {
quote! { <I = ::rustc_middle::ty::TyCtxt<'tcx>> }
} else if s.ast().generics.type_params().any(|ty| ty.ident == "I") {
quote! { <I = I> }
} else {
quote! {}
};

let encoder_ty = quote! { __E };
s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder<I = ::rustc_middle::ty::TyCtxt<'tcx>>});
s.add_bounds(synstructure::AddBounds::Generics);
s.add_impl_generic(parse_quote! {#encoder_ty: ::rustc_type_ir::codec::TyEncoder #bound });
s.add_bounds(synstructure::AddBounds::Fields);

encodable_body(s, encoder_ty, false)
}
Expand Down
29 changes: 2 additions & 27 deletions compiler/rustc_type_ir/src/canonical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,17 @@ use std::hash::Hash;
use std::ops::ControlFlow;

use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::{Decodable, Encodable};

use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor};
use crate::TyDecoder;
use crate::{HashStableContext, Interner, TyEncoder, UniverseIndex};
use crate::{HashStableContext, 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"))]
#[derive(TyEncodable, TyDecodable)]
pub struct Canonical<I: Interner, V> {
pub value: V,
pub max_universe: UniverseIndex,
Expand Down Expand Up @@ -127,27 +126,3 @@ where
self.variables.visit_with(folder)
}
}

impl<I: Interner, E: TyEncoder<I = I>, V: Encodable<E>> Encodable<E> for Canonical<I, V>
where
I::CanonicalVars: Encodable<E>,
{
fn encode(&self, s: &mut E) {
self.value.encode(s);
self.max_universe.encode(s);
self.variables.encode(s);
}
}

impl<I: Interner, D: TyDecoder<I = I>, V: Decodable<D>> Decodable<D> for Canonical<I, V>
where
I::CanonicalVars: Decodable<D>,
{
fn decode(d: &mut D) -> Self {
Canonical {
value: Decodable::decode(d),
max_universe: Decodable::decode(d),
variables: Decodable::decode(d),
}
}
}
68 changes: 2 additions & 66 deletions compiler/rustc_type_ir/src/const_kind.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use rustc_data_structures::stable_hasher::HashStable;
use rustc_data_structures::stable_hasher::StableHasher;
use rustc_serialize::{Decodable, Decoder, Encodable};
use std::fmt;

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

use self::ConstKind::*;

Expand All @@ -20,6 +16,7 @@ use self::ConstKind::*;
Ord = "feature_allow_slow_enum",
Hash(bound = "")
)]
#[derive(TyEncodable, TyDecodable)]
pub enum ConstKind<I: Interner> {
/// A const generic parameter.
Param(I::ParamConst),
Expand Down Expand Up @@ -92,67 +89,6 @@ where
}
}

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> PartialEq for ConstKind<I> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_type_ir/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
#![deny(rustc::diagnostic_outside_of_impl)]
#![allow(internal_features)]

extern crate self as rustc_type_ir;

#[macro_use]
extern crate bitflags;
#[macro_use]
Expand Down
139 changes: 2 additions & 137 deletions compiler/rustc_type_ir/src/predicate_kind.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_serialize::Decoder;
use rustc_serialize::{Decodable, Encodable};
use std::fmt;
use std::ops::ControlFlow;

use crate::fold::{FallibleTypeFolder, TypeFoldable};
use crate::visit::{TypeVisitable, TypeVisitor};
use crate::{HashStableContext, Interner};
use crate::{TyDecoder, TyEncoder};

/// A clause is something that can appear in where bounds or be inferred
/// by implied bounds.
#[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))]
#[derive(TyEncodable, TyDecodable)]
pub enum ClauseKind<I: Interner> {
/// Corresponds to `where Foo: Bar<A, B, C>`. `Foo` here would be
/// the `Self` type of the trait reference and `A`, `B`, and `C`
Expand Down Expand Up @@ -161,65 +159,9 @@ where
}
}

impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for ClauseKind<I>
where
I::Ty: Decodable<D>,
I::Const: Decodable<D>,
I::GenericArg: Decodable<D>,
I::TraitPredicate: Decodable<D>,
I::ProjectionPredicate: Decodable<D>,
I::TypeOutlivesPredicate: Decodable<D>,
I::RegionOutlivesPredicate: Decodable<D>,
{
fn decode(d: &mut D) -> Self {
match Decoder::read_usize(d) {
0 => ClauseKind::Trait(Decodable::decode(d)),
1 => ClauseKind::RegionOutlives(Decodable::decode(d)),
2 => ClauseKind::TypeOutlives(Decodable::decode(d)),
3 => ClauseKind::Projection(Decodable::decode(d)),
4 => ClauseKind::ConstArgHasType(Decodable::decode(d), Decodable::decode(d)),
5 => ClauseKind::WellFormed(Decodable::decode(d)),
6 => ClauseKind::ConstEvaluatable(Decodable::decode(d)),
_ => panic!(
"{}",
format!(
"invalid enum variant tag while decoding `{}`, expected 0..{}",
"ClauseKind", 7,
)
),
}
}
}

impl<I: Interner, E: TyEncoder> Encodable<E> for ClauseKind<I>
where
I::Ty: Encodable<E>,
I::Const: Encodable<E>,
I::GenericArg: Encodable<E>,
I::TraitPredicate: Encodable<E>,
I::ProjectionPredicate: Encodable<E>,
I::TypeOutlivesPredicate: Encodable<E>,
I::RegionOutlivesPredicate: Encodable<E>,
{
fn encode(&self, s: &mut E) {
let discriminant = clause_kind_discriminant(self);
match self {
ClauseKind::Trait(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
ClauseKind::RegionOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
ClauseKind::TypeOutlives(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
ClauseKind::Projection(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
ClauseKind::ConstArgHasType(c, t) => s.emit_enum_variant(discriminant, |s| {
c.encode(s);
t.encode(s);
}),
ClauseKind::WellFormed(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
ClauseKind::ConstEvaluatable(p) => s.emit_enum_variant(discriminant, |s| p.encode(s)),
}
}
}

#[derive(derivative::Derivative)]
#[derivative(Clone(bound = ""), Hash(bound = ""))]
#[derive(TyEncodable, TyDecodable)]
pub enum PredicateKind<I: Interner> {
/// Prove a clause
Clause(ClauseKind<I>),
Expand Down Expand Up @@ -418,83 +360,6 @@ where
}
}

impl<I: Interner, D: TyDecoder<I = I>> Decodable<D> for PredicateKind<I>
where
I::DefId: Decodable<D>,
I::Const: Decodable<D>,
I::GenericArgs: Decodable<D>,
I::Term: Decodable<D>,
I::CoercePredicate: Decodable<D>,
I::SubtypePredicate: Decodable<D>,
I::ClosureKind: Decodable<D>,
ClauseKind<I>: Decodable<D>,
{
fn decode(d: &mut D) -> Self {
match Decoder::read_usize(d) {
0 => PredicateKind::Clause(Decodable::decode(d)),
1 => PredicateKind::ObjectSafe(Decodable::decode(d)),
2 => PredicateKind::ClosureKind(
Decodable::decode(d),
Decodable::decode(d),
Decodable::decode(d),
),
3 => PredicateKind::Subtype(Decodable::decode(d)),
4 => PredicateKind::Coerce(Decodable::decode(d)),
5 => PredicateKind::ConstEquate(Decodable::decode(d), Decodable::decode(d)),
6 => PredicateKind::Ambiguous,
7 => PredicateKind::AliasRelate(
Decodable::decode(d),
Decodable::decode(d),
Decodable::decode(d),
),
_ => panic!(
"{}",
format!(
"invalid enum variant tag while decoding `{}`, expected 0..{}",
"PredicateKind", 8,
)
),
}
}
}

impl<I: Interner, E: TyEncoder> Encodable<E> for PredicateKind<I>
where
I::DefId: Encodable<E>,
I::Const: Encodable<E>,
I::GenericArgs: Encodable<E>,
I::Term: Encodable<E>,
I::CoercePredicate: Encodable<E>,
I::SubtypePredicate: Encodable<E>,
I::ClosureKind: Encodable<E>,
ClauseKind<I>: Encodable<E>,
{
fn encode(&self, s: &mut E) {
let discriminant = predicate_kind_discriminant(self);
match self {
PredicateKind::Clause(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
PredicateKind::ObjectSafe(d) => s.emit_enum_variant(discriminant, |s| d.encode(s)),
PredicateKind::ClosureKind(d, g, k) => s.emit_enum_variant(discriminant, |s| {
d.encode(s);
g.encode(s);
k.encode(s);
}),
PredicateKind::Subtype(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
PredicateKind::Coerce(c) => s.emit_enum_variant(discriminant, |s| c.encode(s)),
PredicateKind::ConstEquate(a, b) => s.emit_enum_variant(discriminant, |s| {
a.encode(s);
b.encode(s);
}),
PredicateKind::Ambiguous => s.emit_enum_variant(discriminant, |_s| {}),
PredicateKind::AliasRelate(a, b, d) => s.emit_enum_variant(discriminant, |s| {
a.encode(s);
b.encode(s);
d.encode(s);
}),
}
}
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
#[derive(HashStable_Generic, Encodable, Decodable)]
pub enum AliasRelationDirection {
Expand Down
Loading

0 comments on commit 6bf2fb3

Please sign in to comment.