From e77fd477083692f60b55e6ae6ceb445bddaa0301 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 8 Sep 2020 17:34:16 +0100 Subject: [PATCH 01/13] Add bounds for generic type param --- derive/src/lib.rs | 11 +- derive/src/trait_bounds.rs | 208 +++++++++++++++++++++++++++++++++++++ test_suite/tests/derive.rs | 25 +++++ 3 files changed, 239 insertions(+), 5 deletions(-) create mode 100644 derive/src/trait_bounds.rs diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 0e9bd874..6cdc91c9 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -17,6 +17,7 @@ extern crate alloc; mod impl_wrapper; +mod trait_bounds; use alloc::vec::Vec; use proc_macro::TokenStream; @@ -24,7 +25,6 @@ use proc_macro2::TokenStream as TokenStream2; use quote::quote; use syn::{ parse::{Error, Result}, - parse_quote, punctuated::Punctuated, token::Comma, Data, DataEnum, DataStruct, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Variant, @@ -47,10 +47,11 @@ fn generate(input: TokenStream2) -> Result { fn generate_type(input: TokenStream2) -> Result { let mut ast: DeriveInput = syn::parse2(input.clone())?; - ast.generics.type_params_mut().for_each(|p| { - p.bounds.push(parse_quote!(_scale_info::TypeInfo)); - p.bounds.push(parse_quote!('static)); - }); + trait_bounds::add( + &ast.ident, + &mut ast.generics, + &ast.data, + )?; let ident = &ast.ident; let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs new file mode 100644 index 00000000..5f822886 --- /dev/null +++ b/derive/src/trait_bounds.rs @@ -0,0 +1,208 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use alloc::vec::Vec; +use proc_macro2::Ident; +use syn::{ + spanned::Spanned, + visit::{self, Visit}, + Generics, Result, Type, TypePath, + parse_quote, +}; + +/// Visits the ast and checks if one of the given idents is found. +struct ContainIdents<'a> { + result: bool, + idents: &'a[Ident] +} + +impl<'a, 'ast> Visit<'ast> for ContainIdents<'a> { + fn visit_ident(&mut self, i: &'ast Ident) { + if self.idents.iter().any(|id| id == i) { + self.result = true; + } + } +} + +/// Checks if the given type contains one of the given idents. +fn type_contain_idents(ty: &Type, idents: &[Ident]) -> bool { + let mut visitor = ContainIdents { result: false, idents }; + visitor.visit_type(ty); + visitor.result +} + +/// Visits the ast and checks if the a type path starts with the given ident. +struct TypePathStartsWithIdent<'a> { + result: bool, + ident: &'a Ident +} + +impl<'a, 'ast> Visit<'ast> for TypePathStartsWithIdent<'a> { + fn visit_type_path(&mut self, i: &'ast TypePath) { + if let Some(segment) = i.path.segments.first() { + if &segment.ident == self.ident { + self.result = true; + return; + } + } + + visit::visit_type_path(self, i); + } +} + +/// Checks if the given type path or any containing type path starts with the given ident. +fn type_path_or_sub_starts_with_ident(ty: &TypePath, ident: &Ident) -> bool { + let mut visitor = TypePathStartsWithIdent { result: false, ident }; + visitor.visit_type_path(ty); + visitor.result +} + +/// Checks if the given type or any containing type path starts with the given ident. +fn type_or_sub_type_path_starts_with_ident(ty: &Type, ident: &Ident) -> bool { + let mut visitor = TypePathStartsWithIdent { result: false, ident }; + visitor.visit_type(ty); + visitor.result +} + +/// Visits the ast and collects all type paths that do not start or contain the given ident. +/// +/// Returns `T`, `N`, `A` for `Vec<(Recursive, A)>` with `Recursive` as ident. +struct FindTypePathsNotStartOrContainIdent<'a> { + result: Vec, + ident: &'a Ident +} + +impl<'a, 'ast> Visit<'ast> for FindTypePathsNotStartOrContainIdent<'a> { + fn visit_type_path(&mut self, i: &'ast TypePath) { + if type_path_or_sub_starts_with_ident(i, &self.ident) { + visit::visit_type_path(self, i); + } else { + self.result.push(i.clone()); + } + } +} + +/// Collects all type paths that do not start or contain the given ident in the given type. +/// +/// Returns `T`, `N`, `A` for `Vec<(Recursive, A)>` with `Recursive` as ident. +fn find_type_paths_not_start_or_contain_ident(ty: &Type, ident: &Ident) -> Vec { + let mut visitor = FindTypePathsNotStartOrContainIdent { result: Vec::new(), ident }; + visitor.visit_type(ty); + visitor.result +} + +/// Add required trait bounds to all generic types. +pub fn add( + input_ident: &Ident, + generics: &mut Generics, + data: &syn::Data, +) -> Result<()> { + generics.type_params_mut().for_each(|p| { + p.bounds.push(parse_quote!(_scale_info::TypeInfo)); + p.bounds.push(parse_quote!('static)); + }); + + let ty_params = generics.type_params().map(|p| p.ident.clone()).collect::>(); + if ty_params.is_empty() { + return Ok(()); + } + + let codec_types = get_types_to_add_trait_bound(input_ident, data, &ty_params)?; + + if !codec_types.is_empty() { + let where_clause = generics.make_where_clause(); + + codec_types + .into_iter() + .for_each(|ty| { + where_clause.predicates.push(parse_quote!(#ty : _scale_info::TypeInfo + 'static)) + }); + } + + Ok(()) +} + +/// Returns all types that must be added to the where clause with the respective trait bound. +fn get_types_to_add_trait_bound( + input_ident: &Ident, + data: &syn::Data, + ty_params: &[Ident], +) -> Result> { + let res = collect_types(&data, |_| { true }, |_| { true })? + .into_iter() + // Only add a bound if the type uses a generic + .filter(|ty| type_contain_idents(ty, &ty_params)) + // If a struct is containing itself as field type, we can not add this type into the where clause. + // This is required to work a round the following compiler bug: https://github.com/rust-lang/rust/issues/47032 + .flat_map(|ty| { + find_type_paths_not_start_or_contain_ident(&ty, input_ident) + .into_iter() + .map(|ty| Type::Path(ty.clone())) + // Remove again types that do not contain any of our generic parameters + .filter(|ty| type_contain_idents(ty, &ty_params)) + // todo: [AJ] can I remove this + // // Add back the original type, as we don't want to loose him. + // .chain(core::iter::once(ty)) + }) + // Remove all remaining types that start/contain the input ident to not have them in the where clause. + .filter(|ty| !type_or_sub_type_path_starts_with_ident(ty, input_ident)) + .collect(); + + Ok(res) +} + +fn collect_types( + data: &syn::Data, + type_filter: fn(&syn::Field) -> bool, + variant_filter: fn(&syn::Variant) -> bool, +) -> Result> { + use syn::*; + + let types = match *data { + Data::Struct(ref data) => match &data.fields { + | Fields::Named(FieldsNamed { named: fields , .. }) + | Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. }) => { + fields.iter() + .filter(|f| type_filter(f)) + .map(|f| f.ty.clone()) + .collect() + }, + + Fields::Unit => { Vec::new() }, + }, + + Data::Enum(ref data) => data.variants.iter() + .filter(|variant| variant_filter(variant)) + .flat_map(|variant| { + match &variant.fields { + | Fields::Named(FieldsNamed { named: fields , .. }) + | Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. }) => { + fields.iter() + .filter(|f| type_filter(f)) + .map(|f| f.ty.clone()) + .collect() + }, + + Fields::Unit => { Vec::new() }, + } + }).collect(), + + Data::Union(ref data) => return Err(Error::new( + data.union_token.span(), + "Union types are not supported." + )), + }; + + Ok(types) +} diff --git a/test_suite/tests/derive.rs b/test_suite/tests/derive.rs index d50e694a..10c81c9b 100644 --- a/test_suite/tests/derive.rs +++ b/test_suite/tests/derive.rs @@ -128,3 +128,28 @@ fn enum_derive() { assert_type!(E, ty); } + +#[test] +fn associated_types_derive_without_bounds() { + trait Types { + type A; + } + #[allow(unused)] + #[derive(TypeInfo)] + struct Assoc { + a: T::A + } + + #[derive(TypeInfo)] + enum ConcreteTypes {} + impl Types for ConcreteTypes { + type A = bool; + } + + let struct_type = Type::builder() + .path(Path::new("Assoc", "derive")) + .type_params(tuple_meta_type!(ConcreteTypes)) + .composite(Fields::named().field_of::("a")); + + assert_type!(Assoc, struct_type); +} From 506da3fd0dbe668843b801e18b8ed3feee1eb8fd Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 9 Sep 2020 09:43:59 +0100 Subject: [PATCH 02/13] Fmt --- derive/src/lib.rs | 6 +-- derive/src/trait_bounds.rs | 77 ++++++++++++++++---------------------- test_suite/tests/derive.rs | 2 +- 3 files changed, 34 insertions(+), 51 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 6cdc91c9..2eadd0c8 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -47,11 +47,7 @@ fn generate(input: TokenStream2) -> Result { fn generate_type(input: TokenStream2) -> Result { let mut ast: DeriveInput = syn::parse2(input.clone())?; - trait_bounds::add( - &ast.ident, - &mut ast.generics, - &ast.data, - )?; + trait_bounds::add(&ast.ident, &mut ast.generics, &ast.data)?; let ident = &ast.ident; let (impl_generics, ty_generics, where_clause) = ast.generics.split_for_impl(); diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index 5f822886..dc4cf362 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -15,16 +15,16 @@ use alloc::vec::Vec; use proc_macro2::Ident; use syn::{ + parse_quote, spanned::Spanned, visit::{self, Visit}, Generics, Result, Type, TypePath, - parse_quote, }; /// Visits the ast and checks if one of the given idents is found. struct ContainIdents<'a> { result: bool, - idents: &'a[Ident] + idents: &'a [Ident], } impl<'a, 'ast> Visit<'ast> for ContainIdents<'a> { @@ -45,7 +45,7 @@ fn type_contain_idents(ty: &Type, idents: &[Ident]) -> bool { /// Visits the ast and checks if the a type path starts with the given ident. struct TypePathStartsWithIdent<'a> { result: bool, - ident: &'a Ident + ident: &'a Ident, } impl<'a, 'ast> Visit<'ast> for TypePathStartsWithIdent<'a> { @@ -80,7 +80,7 @@ fn type_or_sub_type_path_starts_with_ident(ty: &Type, ident: &Ident) -> bool { /// Returns `T`, `N`, `A` for `Vec<(Recursive, A)>` with `Recursive` as ident. struct FindTypePathsNotStartOrContainIdent<'a> { result: Vec, - ident: &'a Ident + ident: &'a Ident, } impl<'a, 'ast> Visit<'ast> for FindTypePathsNotStartOrContainIdent<'a> { @@ -97,17 +97,16 @@ impl<'a, 'ast> Visit<'ast> for FindTypePathsNotStartOrContainIdent<'a> { /// /// Returns `T`, `N`, `A` for `Vec<(Recursive, A)>` with `Recursive` as ident. fn find_type_paths_not_start_or_contain_ident(ty: &Type, ident: &Ident) -> Vec { - let mut visitor = FindTypePathsNotStartOrContainIdent { result: Vec::new(), ident }; + let mut visitor = FindTypePathsNotStartOrContainIdent { + result: Vec::new(), + ident, + }; visitor.visit_type(ty); visitor.result } /// Add required trait bounds to all generic types. -pub fn add( - input_ident: &Ident, - generics: &mut Generics, - data: &syn::Data, -) -> Result<()> { +pub fn add(input_ident: &Ident, generics: &mut Generics, data: &syn::Data) -> Result<()> { generics.type_params_mut().for_each(|p| { p.bounds.push(parse_quote!(_scale_info::TypeInfo)); p.bounds.push(parse_quote!('static)); @@ -123,23 +122,19 @@ pub fn add( if !codec_types.is_empty() { let where_clause = generics.make_where_clause(); - codec_types - .into_iter() - .for_each(|ty| { - where_clause.predicates.push(parse_quote!(#ty : _scale_info::TypeInfo + 'static)) - }); + codec_types.into_iter().for_each(|ty| { + where_clause + .predicates + .push(parse_quote!(#ty : _scale_info::TypeInfo + 'static)) + }); } Ok(()) } /// Returns all types that must be added to the where clause with the respective trait bound. -fn get_types_to_add_trait_bound( - input_ident: &Ident, - data: &syn::Data, - ty_params: &[Ident], -) -> Result> { - let res = collect_types(&data, |_| { true }, |_| { true })? +fn get_types_to_add_trait_bound(input_ident: &Ident, data: &syn::Data, ty_params: &[Ident]) -> Result> { + let res = collect_types(&data, |_| true, |_| true)? .into_iter() // Only add a bound if the type uses a generic .filter(|ty| type_contain_idents(ty, &ty_params)) @@ -171,37 +166,29 @@ fn collect_types( let types = match *data { Data::Struct(ref data) => match &data.fields { - | Fields::Named(FieldsNamed { named: fields , .. }) + Fields::Named(FieldsNamed { named: fields, .. }) | Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. }) => { - fields.iter() - .filter(|f| type_filter(f)) - .map(|f| f.ty.clone()) - .collect() - }, + fields.iter().filter(|f| type_filter(f)).map(|f| f.ty.clone()).collect() + } - Fields::Unit => { Vec::new() }, + Fields::Unit => Vec::new(), }, - Data::Enum(ref data) => data.variants.iter() + Data::Enum(ref data) => data + .variants + .iter() .filter(|variant| variant_filter(variant)) - .flat_map(|variant| { - match &variant.fields { - | Fields::Named(FieldsNamed { named: fields , .. }) - | Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. }) => { - fields.iter() - .filter(|f| type_filter(f)) - .map(|f| f.ty.clone()) - .collect() - }, - - Fields::Unit => { Vec::new() }, + .flat_map(|variant| match &variant.fields { + Fields::Named(FieldsNamed { named: fields, .. }) + | Fields::Unnamed(FieldsUnnamed { unnamed: fields, .. }) => { + fields.iter().filter(|f| type_filter(f)).map(|f| f.ty.clone()).collect() } - }).collect(), - Data::Union(ref data) => return Err(Error::new( - data.union_token.span(), - "Union types are not supported." - )), + Fields::Unit => Vec::new(), + }) + .collect(), + + Data::Union(ref data) => return Err(Error::new(data.union_token.span(), "Union types are not supported.")), }; Ok(types) diff --git a/test_suite/tests/derive.rs b/test_suite/tests/derive.rs index 10c81c9b..194e6974 100644 --- a/test_suite/tests/derive.rs +++ b/test_suite/tests/derive.rs @@ -137,7 +137,7 @@ fn associated_types_derive_without_bounds() { #[allow(unused)] #[derive(TypeInfo)] struct Assoc { - a: T::A + a: T::A, } #[derive(TypeInfo)] From 08e267ba220feaa2f1d08a8aca7d85c10aa4e0e8 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 9 Sep 2020 09:46:48 +0100 Subject: [PATCH 03/13] Remove redundant clone --- derive/src/trait_bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index dc4cf362..11350235 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -143,7 +143,7 @@ fn get_types_to_add_trait_bound(input_ident: &Ident, data: &syn::Data, ty_params .flat_map(|ty| { find_type_paths_not_start_or_contain_ident(&ty, input_ident) .into_iter() - .map(|ty| Type::Path(ty.clone())) + .map(|ty| Type::Path(ty)) // Remove again types that do not contain any of our generic parameters .filter(|ty| type_contain_idents(ty, &ty_params)) // todo: [AJ] can I remove this From 62a28e35113b945d9d327c2e8f1e1b25f8db2eb7 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 9 Sep 2020 09:59:09 +0100 Subject: [PATCH 04/13] Make clippy happy --- derive/src/trait_bounds.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index 11350235..6b6d2895 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -143,7 +143,9 @@ fn get_types_to_add_trait_bound(input_ident: &Ident, data: &syn::Data, ty_params .flat_map(|ty| { find_type_paths_not_start_or_contain_ident(&ty, input_ident) .into_iter() - .map(|ty| Type::Path(ty)) + // Add this back if we add the .chain line below back + // .map(|ty| Type::Path(ty.clone())) + .map(Type::Path) // Remove again types that do not contain any of our generic parameters .filter(|ty| type_contain_idents(ty, &ty_params)) // todo: [AJ] can I remove this From 477ff965ef9911934f38a360b7d13d8930aeb44a Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 7 Sep 2020 17:01:42 +0100 Subject: [PATCH 05/13] Impl TypeInfo for Path --- src/ty/path.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/ty/path.rs b/src/ty/path.rs index f934de84..65f1c5cc 100644 --- a/src/ty/path.rs +++ b/src/ty/path.rs @@ -12,12 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{ - form::{CompactForm, Form, MetaForm}, - tm_std::*, - utils::is_rust_identifier, - IntoCompact, Registry, -}; +use crate::{build::Fields, form::{CompactForm, Form, MetaForm}, tm_std::*, utils::is_rust_identifier, IntoCompact, Registry, TypeInfo, Type}; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -58,6 +53,16 @@ impl IntoCompact for Path { } } +impl TypeInfo for Path { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Path")) + .composite( + Fields::named().field_of::::String>>("segments") + ) + } +} + impl Path { /// Create a new Path /// From 66d8d08689de8b21fe7b85ade8a9556cc2a9eae6 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 7 Sep 2020 17:03:44 +0100 Subject: [PATCH 06/13] Impl TypeInfo for Fields and NonZero types --- src/impls.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/interner.rs | 11 +++++++++++ src/ty/fields.rs | 15 ++++++++++++++- 3 files changed, 64 insertions(+), 1 deletion(-) diff --git a/src/impls.rs b/src/impls.rs index 5ffc2f9e..d8145e7e 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -15,6 +15,18 @@ use crate::build::*; use crate::tm_std::*; use crate::*; +use core::num::{ + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, +}; macro_rules! impl_metadata_for_primitives { ( $( $t:ty => $ident_kind:expr, )* ) => { $( @@ -89,6 +101,33 @@ impl_metadata_for_tuple!(A, B, C, D, E, F, G, H); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J); +macro_rules! impl_for_non_zero { + ( $( $t:ty ),* $(,)? ) => { + $( + impl TypeInfo for $t { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude(stringify!($t))) + .composite(Fields::unnamed().field_of::<$t>()) + } + } + )* + } +} + +impl_for_non_zero! { + NonZeroI8, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI128, + NonZeroU8, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU128, +} + impl TypeInfo for Vec where T: TypeInfo + 'static, diff --git a/src/interner.rs b/src/interner.rs index a3b811cc..b4404a25 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -22,6 +22,7 @@ //! elements and is later used for compact serialization within the registry. use crate::tm_std::*; +use crate::{build::Fields, form::MetaForm, TypeInfo, Type, Path}; use serde::{Deserialize, Serialize}; /// A symbol that is not lifetime tracked. @@ -56,6 +57,16 @@ impl scale::Decode for UntrackedSymbol { } } +impl TypeInfo for UntrackedSymbol { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Path")) + .composite( + Fields::named().field_of::("id") + ) + } +} + /// A symbol from an interner. /// /// Can be used to resolve to the associated instance. diff --git a/src/ty/fields.rs b/src/ty/fields.rs index ea9d1d7f..b4437333 100644 --- a/src/ty/fields.rs +++ b/src/ty/fields.rs @@ -15,8 +15,9 @@ use crate::tm_std::*; use crate::{ + build::Fields, form::{CompactForm, Form, MetaForm}, - IntoCompact, MetaType, Registry, TypeInfo, + IntoCompact, MetaType, Registry, TypeInfo, Type, Path, }; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -51,6 +52,18 @@ impl IntoCompact for Field { } } +impl TypeInfo for Field { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Field")) + .composite( + Fields::named() + .field_of::::String>>("name") + .field_of::::TypeId>>("ty") + ) + } +} + impl Field { /// Creates a new field. /// From a8bd169a6398b4e0bdf58fb32a3561d952bde2df Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 7 Sep 2020 17:16:51 +0100 Subject: [PATCH 07/13] Impl TypeInfo for Variants --- src/ty/variant.rs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/src/ty/variant.rs b/src/ty/variant.rs index eca6fe34..8e06c140 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -14,11 +14,7 @@ use crate::tm_std::*; -use crate::{ - build::FieldsBuilder, - form::{CompactForm, Form, MetaForm}, - Field, IntoCompact, Registry, -}; +use crate::{build::{FieldsBuilder, Fields}, form::{CompactForm, Form, MetaForm}, Field, IntoCompact, Path, Registry, TypeInfo, Type}; use derive_more::From; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -82,6 +78,17 @@ impl IntoCompact for TypeDefVariant { } } +impl TypeInfo for TypeDefVariant { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDefVariant")) + .composite( + Fields::named() + .field_of::>("variants") + ) + } +} + impl TypeDefVariant { /// Create a new `TypeDefVariant` with the given variants pub fn new(variants: I) -> Self @@ -143,6 +150,19 @@ impl IntoCompact for Variant { } } +impl TypeInfo for Variant { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Variant")) + .composite( + Fields::named() + .field_of::<::String>("name") + .field_of::>>("fields") + .field_of::>("discriminant") + ) + } +} + impl Variant { /// Creates a new variant with the given fields. pub fn with_fields(name: &'static str, fields: FieldsBuilder) -> Self { From 37d435c5da6688c95b3d3148944588d2e74cdae4 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 7 Sep 2020 17:20:40 +0100 Subject: [PATCH 08/13] Impl TypeInfo for TypeDefComposite --- src/ty/composite.rs | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/ty/composite.rs b/src/ty/composite.rs index 0de269e8..80e0838c 100644 --- a/src/ty/composite.rs +++ b/src/ty/composite.rs @@ -15,8 +15,9 @@ use crate::tm_std::*; use crate::{ + build::Fields, form::{CompactForm, Form, MetaForm}, - Field, IntoCompact, Registry, + Field, IntoCompact, Registry, TypeInfo, Type, Path, }; use derive_more::From; use scale::{Decode, Encode}; @@ -69,6 +70,17 @@ impl IntoCompact for TypeDefComposite { } } +impl TypeInfo for TypeDefComposite { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDefComposite")) + .composite( + Fields::named() + .field_of::>>("fields") + ) + } +} + impl TypeDefComposite { /// Creates a new struct definition with named fields. pub fn new(fields: I) -> Self From 4eebe4d587f2fc650118f9ce922aee69c0a30b58 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Mon, 7 Sep 2020 17:32:54 +0100 Subject: [PATCH 09/13] TypeInfo for Composite type --- src/ty/mod.rs | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/ty/mod.rs b/src/ty/mod.rs index 48fdb13f..49eda949 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -15,7 +15,7 @@ use crate::tm_std::*; use crate::{ - build::TypeBuilder, + build::{TypeBuilder, Fields, Variants}, form::{CompactForm, Form, MetaForm}, IntoCompact, MetaType, Registry, TypeInfo, }; @@ -60,6 +60,19 @@ impl IntoCompact for Type { } } +impl TypeInfo for Type { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Type")) + .composite( + Fields::named() + .field_of::>("path") + .field_of::::TypeId>>("params") + .field_of::>("def") + ) + } +} + impl From for Type { fn from(primitive: TypeDefPrimitive) -> Self { Self::new(Path::voldemort(), Vec::new(), primitive) @@ -125,6 +138,17 @@ pub enum TypeDef { Primitive(TypeDefPrimitive), } +impl TypeInfo for TypeDef { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDef")) + .variant( + Variants::with_fields() + .variant("Composite", Fields::unnamed().field_of::>()) + ) + } +} + impl IntoCompact for TypeDef { type Output = TypeDef; From 7ed8235bb9ba3f63a4bc8c6460f22e8bdb451d17 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 8 Sep 2020 11:26:53 +0100 Subject: [PATCH 10/13] Add more type variants --- src/ty/mod.rs | 44 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/src/ty/mod.rs b/src/ty/mod.rs index 49eda949..0a580c53 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -67,8 +67,8 @@ impl TypeInfo for Type { .composite( Fields::named() .field_of::>("path") - .field_of::::TypeId>>("params") - .field_of::>("def") + .field_of::::TypeId>>("type_params") + .field_of::>("type_def") ) } } @@ -145,6 +145,11 @@ impl TypeInfo for TypeDef { .variant( Variants::with_fields() .variant("Composite", Fields::unnamed().field_of::>()) + .variant("Variant", Fields::unnamed().field_of::>()) + .variant("Sequence", Fields::unnamed().field_of::>()) + .variant("Array", Fields::unnamed().field_of::>()) + .variant("Tuple", Fields::unnamed().field_of::>()) + // .variant("Primitive", Fields::unnamed().field_of::()) ) } } @@ -218,6 +223,19 @@ impl IntoCompact for TypeDefArray { } } +impl TypeInfo for TypeDefArray { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDefArray")) + .composite( + Fields::named() + .field_of::("len") + .field_of::<::TypeId>("type_param") + ) + } +} + + impl TypeDefArray { /// Creates a new array type. pub fn new(len: u32, type_param: MetaType) -> Self { @@ -244,6 +262,17 @@ impl IntoCompact for TypeDefTuple { } } +impl TypeInfo for TypeDefTuple { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDefTuple")) + .composite( + Fields::named() + .field_of::::TypeId>>("fields") + ) + } +} + impl TypeDefTuple { /// Creates a new tuple type definition from the given types. pub fn new(type_params: T) -> Self @@ -280,6 +309,17 @@ impl IntoCompact for TypeDefSequence { } } +impl TypeInfo for TypeDefSequence { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("TypeDefSequence")) + .composite( + Fields::named() + .field_of::<::TypeId>("type_param") + ) + } +} + impl TypeDefSequence { /// Creates a new sequence type. /// From ac58b2df44918a070b04ffc06de19df4295445ca Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Tue, 8 Sep 2020 14:32:35 +0100 Subject: [PATCH 11/13] dogfood WIP --- Cargo.toml | 3 +++ derive/Cargo.toml | 4 ++++ derive/src/impl_wrapper.rs | 9 ++++++- derive/src/lib.rs | 32 +++++++++++++++++++++++++ derive/src/symbol.rs | 49 ++++++++++++++++++++++++++++++++++++++ src/form.rs | 10 +++++++- src/meta_type.rs | 12 +++++++++- src/ty/variant.rs | 26 ++------------------ 8 files changed, 118 insertions(+), 27 deletions(-) create mode 100644 derive/src/symbol.rs diff --git a/Cargo.toml b/Cargo.toml index 37a028e3..99af4f1d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,9 @@ std = [ derive = [ "scale-info-derive" ] +dogfood = [ + "scale-info-derive/dogfood" +] [workspace] members = [ diff --git a/derive/Cargo.toml b/derive/Cargo.toml index 6d13c46c..9bc2fd6e 100644 --- a/derive/Cargo.toml +++ b/derive/Cargo.toml @@ -18,3 +18,7 @@ proc-macro = true quote = "1.0" syn = { version = "1.0", features = ["derive"] } proc-macro2 = "1.0" + +[features] +# allows the scale-info crate to derive TypeInfo impls for its own types +dogfood = [] diff --git a/derive/src/impl_wrapper.rs b/derive/src/impl_wrapper.rs index 840026cf..e71e9240 100644 --- a/derive/src/impl_wrapper.rs +++ b/derive/src/impl_wrapper.rs @@ -19,10 +19,17 @@ use proc_macro2::{Span, TokenStream as TokenStream2}; use quote::quote; use syn::Ident; +#[cfg(not(feature = "dogfood"))] +const CRATE_NAME: &str = "scale_info"; + +#[cfg(feature = "dogfood")] +const CRATE_NAME: &str = "self"; + pub fn wrap(ident: &Ident, trait_name: &'static str, impl_quote: TokenStream2) -> TokenStream2 { let mut renamed = format!("_IMPL_{}_FOR_", trait_name); renamed.push_str(ident.to_string().trim_start_matches("r#")); let dummy_const = Ident::new(&renamed, Span::call_site()); + let crate_name = Ident::new(CRATE_NAME, Span::call_site()); quote! { #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] @@ -30,7 +37,7 @@ pub fn wrap(ident: &Ident, trait_name: &'static str, impl_quote: TokenStream2) - #[allow(unknown_lints)] #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))] #[allow(rust_2018_idioms)] - use scale_info as _scale_info; + extern crate #crate_name as _scale_info; #[cfg(not(feature = "std"))] extern crate alloc; diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 2eadd0c8..5202b22c 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -17,6 +17,7 @@ extern crate alloc; mod impl_wrapper; +mod symbol; mod trait_bounds; use alloc::vec::Vec; @@ -29,6 +30,7 @@ use syn::{ token::Comma, Data, DataEnum, DataStruct, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Variant, }; +use symbol::*; #[proc_macro_derive(TypeInfo)] pub fn type_info(input: TokenStream) -> TokenStream { @@ -58,6 +60,36 @@ fn generate_type(input: TokenStream2) -> Result { } }); + let meta_items = ast + .attrs + .iter() + .flat_map(|attr| { + if attr.path != SCALE_INFO { + return Ok(Vec::new()) + } + + match attr.parse_meta() { + Ok(List(meta)) => Ok(meta.nested.into_iter().collect()), + Ok(other) => { + cx.error_spanned_by(other, "expected #[scale_info(...)]"); + Err(()) + } + Err(err) => { + cx.syn_error(err); + Err(()) + } + } + }) + .flatten(); + + // Parse `#[serde(bound = "T: SomeBound")]` + // Meta(NameValue(m)) if m.path == BOUND => { + // if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { + // ser_bound.set(&m.path, where_predicates.clone()); + // de_bound.set(&m.path, where_predicates); + // } + // } + let ast: DeriveInput = syn::parse2(input.clone())?; let build_type = match &ast.data { Data::Struct(ref s) => generate_composite_type(s), diff --git a/derive/src/symbol.rs b/derive/src/symbol.rs new file mode 100644 index 00000000..6690c3d2 --- /dev/null +++ b/derive/src/symbol.rs @@ -0,0 +1,49 @@ +// Copyright 2019-2020 Parity Technologies (UK) Ltd. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#[derive(Copy, Clone)] +pub struct Symbol(&'static str); + +pub const BOUND: Symbol = Symbol("bound"); +pub const SERDE: Symbol = Symbol("scale_info"); + +impl PartialEq for Ident { + fn eq(&self, word: &Symbol) -> bool { + self == word.0 + } +} + +impl<'a> PartialEq for &'a Ident { + fn eq(&self, word: &Symbol) -> bool { + *self == word.0 + } +} + +impl PartialEq for Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl<'a> PartialEq for &'a Path { + fn eq(&self, word: &Symbol) -> bool { + self.is_ident(word.0) + } +} + +impl Display for Symbol { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + formatter.write_str(self.0) + } +} diff --git a/src/form.rs b/src/form.rs index 10902f3e..bff28141 100644 --- a/src/form.rs +++ b/src/form.rs @@ -31,7 +31,7 @@ //! (also via lifetime tracking) are possible but current not needed. use crate::tm_std::*; -use crate::{interner::UntrackedSymbol, meta_type::MetaType}; +use crate::{build::Variants, interner::UntrackedSymbol, meta_type::MetaType, TypeInfo, Type, Path}; use serde::Serialize; /// Trait to control the internal structures of type definitions. @@ -74,3 +74,11 @@ impl Form for CompactForm { type TypeId = UntrackedSymbol; type String = String; } + +impl TypeInfo for CompactForm { + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("CompactForm")) + .variant(Variants::fieldless()) + } +} diff --git a/src/meta_type.rs b/src/meta_type.rs index bf7dcdd4..40b057e8 100644 --- a/src/meta_type.rs +++ b/src/meta_type.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::tm_std::*; -use crate::{form::MetaForm, Type, TypeInfo}; +use crate::{build::Fields, form::MetaForm, Path, Type, TypeInfo}; /// A metatype abstraction. /// @@ -32,6 +32,16 @@ pub struct MetaType { type_id: TypeId, } +// /// Impl required to satisfy constraint on ['crate::form::Form'], to allow deriving TypeInfo when +// /// using the "dogfood" feature. In practice the ['crate::form::CompactForm'] is used for encoding +// /// so this definition itself probably would not be used. +// impl TypeInfo for MetaType { +// fn type_info() -> Type { +// Type::builder().path(Path::prelude("MetaType")) +// .composite(Fields::named().field_of::("type_id")) +// } +// } + impl PartialEq for MetaType { fn eq(&self, other: &Self) -> bool { self.type_id == other.type_id diff --git a/src/ty/variant.rs b/src/ty/variant.rs index 8e06c140..a2ff08b4 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -63,6 +63,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] #[serde(rename_all = "lowercase")] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefVariant { #[serde(skip_serializing_if = "Vec::is_empty", default)] variants: Vec>, @@ -78,17 +79,6 @@ impl IntoCompact for TypeDefVariant { } } -impl TypeInfo for TypeDefVariant { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDefVariant")) - .composite( - Fields::named() - .field_of::>("variants") - ) - } -} - impl TypeDefVariant { /// Create a new `TypeDefVariant` with the given variants pub fn new(variants: I) -> Self @@ -121,6 +111,7 @@ impl TypeDefVariant { serialize = "T::TypeId: Serialize, T::String: Serialize", deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Variant { /// The name of the struct variant. name: T::String, @@ -150,19 +141,6 @@ impl IntoCompact for Variant { } } -impl TypeInfo for Variant { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("Variant")) - .composite( - Fields::named() - .field_of::<::String>("name") - .field_of::>>("fields") - .field_of::>("discriminant") - ) - } -} - impl Variant { /// Creates a new variant with the given fields. pub fn with_fields(name: &'static str, fields: FieldsBuilder) -> Self { From 62fd0efa09a501eea98257be0f740acd8a9aae31 Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 9 Sep 2020 10:10:18 +0100 Subject: [PATCH 12/13] Remove redundant symbols after rebase --- derive/src/lib.rs | 32 ----------------------------- derive/src/symbol.rs | 49 -------------------------------------------- 2 files changed, 81 deletions(-) delete mode 100644 derive/src/symbol.rs diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 5202b22c..2eadd0c8 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -17,7 +17,6 @@ extern crate alloc; mod impl_wrapper; -mod symbol; mod trait_bounds; use alloc::vec::Vec; @@ -30,7 +29,6 @@ use syn::{ token::Comma, Data, DataEnum, DataStruct, DeriveInput, Expr, ExprLit, Field, Fields, Lit, Variant, }; -use symbol::*; #[proc_macro_derive(TypeInfo)] pub fn type_info(input: TokenStream) -> TokenStream { @@ -60,36 +58,6 @@ fn generate_type(input: TokenStream2) -> Result { } }); - let meta_items = ast - .attrs - .iter() - .flat_map(|attr| { - if attr.path != SCALE_INFO { - return Ok(Vec::new()) - } - - match attr.parse_meta() { - Ok(List(meta)) => Ok(meta.nested.into_iter().collect()), - Ok(other) => { - cx.error_spanned_by(other, "expected #[scale_info(...)]"); - Err(()) - } - Err(err) => { - cx.syn_error(err); - Err(()) - } - } - }) - .flatten(); - - // Parse `#[serde(bound = "T: SomeBound")]` - // Meta(NameValue(m)) if m.path == BOUND => { - // if let Ok(where_predicates) = parse_lit_into_where(cx, BOUND, BOUND, &m.lit) { - // ser_bound.set(&m.path, where_predicates.clone()); - // de_bound.set(&m.path, where_predicates); - // } - // } - let ast: DeriveInput = syn::parse2(input.clone())?; let build_type = match &ast.data { Data::Struct(ref s) => generate_composite_type(s), diff --git a/derive/src/symbol.rs b/derive/src/symbol.rs deleted file mode 100644 index 6690c3d2..00000000 --- a/derive/src/symbol.rs +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2019-2020 Parity Technologies (UK) Ltd. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -#[derive(Copy, Clone)] -pub struct Symbol(&'static str); - -pub const BOUND: Symbol = Symbol("bound"); -pub const SERDE: Symbol = Symbol("scale_info"); - -impl PartialEq for Ident { - fn eq(&self, word: &Symbol) -> bool { - self == word.0 - } -} - -impl<'a> PartialEq for &'a Ident { - fn eq(&self, word: &Symbol) -> bool { - *self == word.0 - } -} - -impl PartialEq for Path { - fn eq(&self, word: &Symbol) -> bool { - self.is_ident(word.0) - } -} - -impl<'a> PartialEq for &'a Path { - fn eq(&self, word: &Symbol) -> bool { - self.is_ident(word.0) - } -} - -impl Display for Symbol { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - formatter.write_str(self.0) - } -} From 4188f029052196268b38af62279224ed510125cb Mon Sep 17 00:00:00 2001 From: Andrew Jones Date: Wed, 9 Sep 2020 10:51:09 +0100 Subject: [PATCH 13/13] Derive TypeInfo imps with dogfood --- src/form.rs | 10 +------ src/meta_type.rs | 12 +------- src/ty/composite.rs | 15 ++-------- src/ty/fields.rs | 16 ++-------- src/ty/mod.rs | 72 +++++---------------------------------------- src/ty/path.rs | 13 ++------ src/ty/variant.rs | 2 +- 7 files changed, 16 insertions(+), 124 deletions(-) diff --git a/src/form.rs b/src/form.rs index bff28141..10902f3e 100644 --- a/src/form.rs +++ b/src/form.rs @@ -31,7 +31,7 @@ //! (also via lifetime tracking) are possible but current not needed. use crate::tm_std::*; -use crate::{build::Variants, interner::UntrackedSymbol, meta_type::MetaType, TypeInfo, Type, Path}; +use crate::{interner::UntrackedSymbol, meta_type::MetaType}; use serde::Serialize; /// Trait to control the internal structures of type definitions. @@ -74,11 +74,3 @@ impl Form for CompactForm { type TypeId = UntrackedSymbol; type String = String; } - -impl TypeInfo for CompactForm { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("CompactForm")) - .variant(Variants::fieldless()) - } -} diff --git a/src/meta_type.rs b/src/meta_type.rs index 40b057e8..bf7dcdd4 100644 --- a/src/meta_type.rs +++ b/src/meta_type.rs @@ -13,7 +13,7 @@ // limitations under the License. use crate::tm_std::*; -use crate::{build::Fields, form::MetaForm, Path, Type, TypeInfo}; +use crate::{form::MetaForm, Type, TypeInfo}; /// A metatype abstraction. /// @@ -32,16 +32,6 @@ pub struct MetaType { type_id: TypeId, } -// /// Impl required to satisfy constraint on ['crate::form::Form'], to allow deriving TypeInfo when -// /// using the "dogfood" feature. In practice the ['crate::form::CompactForm'] is used for encoding -// /// so this definition itself probably would not be used. -// impl TypeInfo for MetaType { -// fn type_info() -> Type { -// Type::builder().path(Path::prelude("MetaType")) -// .composite(Fields::named().field_of::("type_id")) -// } -// } - impl PartialEq for MetaType { fn eq(&self, other: &Self) -> bool { self.type_id == other.type_id diff --git a/src/ty/composite.rs b/src/ty/composite.rs index 80e0838c..a51eb144 100644 --- a/src/ty/composite.rs +++ b/src/ty/composite.rs @@ -15,9 +15,8 @@ use crate::tm_std::*; use crate::{ - build::Fields, form::{CompactForm, Form, MetaForm}, - Field, IntoCompact, Registry, TypeInfo, Type, Path, + Field, IntoCompact, Registry, }; use derive_more::From; use scale::{Decode, Encode}; @@ -55,6 +54,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] #[serde(rename_all = "lowercase")] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefComposite { #[serde(skip_serializing_if = "Vec::is_empty", default)] fields: Vec>, @@ -70,17 +70,6 @@ impl IntoCompact for TypeDefComposite { } } -impl TypeInfo for TypeDefComposite { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDefComposite")) - .composite( - Fields::named() - .field_of::>>("fields") - ) - } -} - impl TypeDefComposite { /// Creates a new struct definition with named fields. pub fn new(fields: I) -> Self diff --git a/src/ty/fields.rs b/src/ty/fields.rs index b4437333..51086513 100644 --- a/src/ty/fields.rs +++ b/src/ty/fields.rs @@ -15,9 +15,8 @@ use crate::tm_std::*; use crate::{ - build::Fields, form::{CompactForm, Form, MetaForm}, - IntoCompact, MetaType, Registry, TypeInfo, Type, Path, + IntoCompact, MetaType, Registry, TypeInfo, }; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -32,6 +31,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; serialize = "T::TypeId: Serialize, T::String: Serialize", deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Field { /// The name of the field. None for unnamed fields. #[serde(skip_serializing_if = "Option::is_none", default)] @@ -52,18 +52,6 @@ impl IntoCompact for Field { } } -impl TypeInfo for Field { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("Field")) - .composite( - Fields::named() - .field_of::::String>>("name") - .field_of::::TypeId>>("ty") - ) - } -} - impl Field { /// Creates a new field. /// diff --git a/src/ty/mod.rs b/src/ty/mod.rs index 0a580c53..e0b8b351 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -15,7 +15,7 @@ use crate::tm_std::*; use crate::{ - build::{TypeBuilder, Fields, Variants}, + build::TypeBuilder, form::{CompactForm, Form, MetaForm}, IntoCompact, MetaType, Registry, TypeInfo, }; @@ -36,6 +36,7 @@ pub use self::{composite::*, fields::*, path::*, variant::*}; serialize = "T::TypeId: Serialize, T::String: Serialize", deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Type { /// The unique path to the type. Can be empty for built-in types #[serde(skip_serializing_if = "Path::is_empty", default)] @@ -60,19 +61,6 @@ impl IntoCompact for Type { } } -impl TypeInfo for Type { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("Type")) - .composite( - Fields::named() - .field_of::>("path") - .field_of::::TypeId>>("type_params") - .field_of::>("type_def") - ) - } -} - impl From for Type { fn from(primitive: TypeDefPrimitive) -> Self { Self::new(Path::voldemort(), Vec::new(), primitive) @@ -123,6 +111,7 @@ impl Type { deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] #[serde(rename_all = "camelCase")] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub enum TypeDef { /// A composite type (e.g. a struct or a tuple) Composite(TypeDefComposite), @@ -138,22 +127,6 @@ pub enum TypeDef { Primitive(TypeDefPrimitive), } -impl TypeInfo for TypeDef { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDef")) - .variant( - Variants::with_fields() - .variant("Composite", Fields::unnamed().field_of::>()) - .variant("Variant", Fields::unnamed().field_of::>()) - .variant("Sequence", Fields::unnamed().field_of::>()) - .variant("Array", Fields::unnamed().field_of::>()) - .variant("Tuple", Fields::unnamed().field_of::>()) - // .variant("Primitive", Fields::unnamed().field_of::()) - ) - } -} - impl IntoCompact for TypeDef { type Output = TypeDef; @@ -172,6 +145,7 @@ impl IntoCompact for TypeDef { /// A primitive Rust type. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, Encode, Decode, Debug)] #[serde(rename_all = "lowercase")] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub enum TypeDefPrimitive { /// `bool` type Bool, @@ -204,6 +178,7 @@ pub enum TypeDefPrimitive { /// An array type. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, Encode, Decode, Debug)] #[serde(bound(serialize = "T::TypeId: Serialize", deserialize = "T::TypeId: DeserializeOwned"))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefArray { /// The length of the array type. pub len: u32, @@ -223,19 +198,6 @@ impl IntoCompact for TypeDefArray { } } -impl TypeInfo for TypeDefArray { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDefArray")) - .composite( - Fields::named() - .field_of::("len") - .field_of::<::TypeId>("type_param") - ) - } -} - - impl TypeDefArray { /// Creates a new array type. pub fn new(len: u32, type_param: MetaType) -> Self { @@ -247,6 +209,7 @@ impl TypeDefArray { #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, Encode, Decode, Debug)] #[serde(bound(serialize = "T::TypeId: Serialize", deserialize = "T::TypeId: DeserializeOwned"))] #[serde(transparent)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefTuple { /// The types of the tuple fields. fields: Vec, @@ -262,17 +225,6 @@ impl IntoCompact for TypeDefTuple { } } -impl TypeInfo for TypeDefTuple { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDefTuple")) - .composite( - Fields::named() - .field_of::::TypeId>>("fields") - ) - } -} - impl TypeDefTuple { /// Creates a new tuple type definition from the given types. pub fn new(type_params: T) -> Self @@ -293,6 +245,7 @@ impl TypeDefTuple { /// A type to refer to a sequence of elements of the same type. #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Serialize, Deserialize, Encode, Decode, Debug)] #[serde(bound(serialize = "T::TypeId: Serialize", deserialize = "T::TypeId: DeserializeOwned"))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefSequence { /// The element type of the sequence type. #[serde(rename = "type")] @@ -309,17 +262,6 @@ impl IntoCompact for TypeDefSequence { } } -impl TypeInfo for TypeDefSequence { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("TypeDefSequence")) - .composite( - Fields::named() - .field_of::<::TypeId>("type_param") - ) - } -} - impl TypeDefSequence { /// Creates a new sequence type. /// diff --git a/src/ty/path.rs b/src/ty/path.rs index 65f1c5cc..e7a7184a 100644 --- a/src/ty/path.rs +++ b/src/ty/path.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{build::Fields, form::{CompactForm, Form, MetaForm}, tm_std::*, utils::is_rust_identifier, IntoCompact, Registry, TypeInfo, Type}; +use crate::{form::{CompactForm, Form, MetaForm}, tm_std::*, utils::is_rust_identifier, IntoCompact, Registry}; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -29,6 +29,7 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize}; serialize = "T::TypeId: Serialize, T::String: Serialize", deserialize = "T::TypeId: DeserializeOwned, T::String: DeserializeOwned" ))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Path { /// The segments of the namespace. segments: Vec, @@ -53,16 +54,6 @@ impl IntoCompact for Path { } } -impl TypeInfo for Path { - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("Path")) - .composite( - Fields::named().field_of::::String>>("segments") - ) - } -} - impl Path { /// Create a new Path /// diff --git a/src/ty/variant.rs b/src/ty/variant.rs index a2ff08b4..c6780ed8 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -14,7 +14,7 @@ use crate::tm_std::*; -use crate::{build::{FieldsBuilder, Fields}, form::{CompactForm, Form, MetaForm}, Field, IntoCompact, Path, Registry, TypeInfo, Type}; +use crate::{build::FieldsBuilder, form::{CompactForm, Form, MetaForm}, Field, IntoCompact, Registry}; use derive_more::From; use scale::{Decode, Encode}; use serde::{de::DeserializeOwned, Deserialize, Serialize};