From 84b3bb496934134a2bf4aeecfb4fd53be12ab80a Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 3 Mar 2021 16:31:03 +0100 Subject: [PATCH 01/20] Don't use a feature in the derive crate Derive TypeInfo for all of scale-infos types --- Cargo.toml | 5 ++- derive/src/lib.rs | 69 ++++++++++++++++++++++++++++---------- derive/src/trait_bounds.rs | 4 +-- src/form.rs | 1 + src/impls.rs | 40 ++++++++++++++++++++++ src/interner.rs | 21 ++++++++++++ src/meta_type.rs | 14 ++++++++ src/registry.rs | 10 ++++++ src/ty/composite.rs | 1 + src/ty/fields.rs | 1 + src/ty/mod.rs | 31 +++++++++++++++++ src/ty/path.rs | 1 + src/ty/variant.rs | 2 ++ test_suite/Cargo.toml | 2 +- test_suite/tests/derive.rs | 20 +++++------ 15 files changed, 190 insertions(+), 32 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 47743a48..1994bf74 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,9 @@ std = [ derive = [ "scale-info-derive" ] -# enables decoding and deserialization of portable scale-info type metadata +# Derive `TypeInfo` for our own types. +dogfood = ["derive"] +# Enables decoding and deserialization of portable scale-info type metadata. decode = [] [workspace] @@ -36,3 +38,4 @@ members = [ "derive", "test_suite", ] +# exclude = ["test_suite"] diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 7ba60a7e..6037105f 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#![cfg_attr(not(feature = "std"), no_std)] +// #![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; extern crate proc_macro; @@ -76,7 +76,29 @@ fn generate(input: TokenStream2) -> Result { fn generate_type(input: TokenStream2) -> Result { let mut ast: DeriveInput = syn::parse2(input.clone())?; - let scale_info = crate_name_ident("scale-info")?; + // Find the name given to the `scale-info` crate in the context we run in. + // If scale-info is not among the dependencies then we must be deriving + // types for the scale-info crate itself, in which case we need to rename + // "self" to something, so the object paths keep working. + let (scale_info, import_self_as_scale_info) = { + let actual_crate_name = proc_macro_crate::crate_name("scale-info"); + if let Err(e) = actual_crate_name { + if e.starts_with("Could not find `scale-info`") { + (Ident::new("_scale_info", Span::call_site()), true) + } else { + return Err(syn::Error::new(Span::call_site(), e)) + } + } else { + ( + Ident::new( + &actual_crate_name.expect("Checked Err above; qed"), + Span::call_site(), + ), + false, + ) + } + }; + let parity_scale_codec = crate_name_ident("parity-scale-codec")?; let ident = &ast.ident; @@ -97,33 +119,44 @@ fn generate_type(input: TokenStream2) -> Result { let generic_type_ids = ast.generics.type_params().map(|ty| { let ty_ident = &ty.ident; quote! { - :: #scale_info ::meta_type::<#ty_ident>() + #scale_info::meta_type::<#ty_ident>() } }); - let ast: DeriveInput = syn::parse2(input.clone())?; + let mut ast: DeriveInput = syn::parse2(input.clone())?; let build_type = match &ast.data { Data::Struct(ref s) => generate_composite_type(s, &scale_info), Data::Enum(ref e) => generate_variant_type(e, &scale_info), Data::Union(_) => return Err(Error::new_spanned(input, "Unions not supported")), }; + + // Remove any type parameter defaults, we don't want those. E.g. `impl` + ast.generics.type_params_mut().for_each(|type_param| { + type_param.default = None; + }); let generic_types = ast.generics.type_params(); let type_info_impl = quote! { - impl <#( #generic_types ),*> :: #scale_info ::TypeInfo for #ident #ty_generics #where_clause { + impl <#( #generic_types ),*> #scale_info::TypeInfo for #ident #ty_generics #where_clause { type Identity = Self; - fn type_info() -> :: #scale_info ::Type { - :: #scale_info ::Type::builder() - .path(:: #scale_info ::Path::new(stringify!(#ident), module_path!())) - .type_params(:: #scale_info ::prelude::vec![ #( #generic_type_ids ),* ]) + fn type_info() -> #scale_info::Type { + #scale_info::Type::builder() + .path(#scale_info::Path::new(stringify!(#ident), module_path!())) + .type_params(#scale_info::prelude::vec![ #( #generic_type_ids ),* ]) .#build_type } - } + }; + }; + let crate_rename = if import_self_as_scale_info { + quote! { extern crate self as _scale_info; } + } else { + quote! {} }; - Ok(quote! { - #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + // TODO: are these needed? + // #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const _: () = { - #type_info_impl; + #crate_rename + #type_info_impl }; }) } @@ -222,7 +255,7 @@ fn generate_composite_type(data_struct: &DataStruct, scale_info: &Ident) -> Toke } }; quote! { - composite(:: #scale_info ::build::Fields::#fields) + composite(#scale_info::build::Fields::#fields) } } @@ -252,7 +285,7 @@ fn generate_c_like_enum_def(variants: &VariantList, scale_info: &Ident) -> Token }); quote! { variant( - :: #scale_info ::build::Variants::fieldless() + #scale_info::build::Variants::fieldless() #( #variants )* ) } @@ -281,7 +314,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea quote! { .variant( #v_name, - :: #scale_info ::build::Fields::named() + #scale_info::build::Fields::named() #( #fields)* ) } @@ -291,7 +324,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea quote! { .variant( #v_name, - :: #scale_info ::build::Fields::unnamed() + #scale_info::build::Fields::unnamed() #( #fields)* ) } @@ -305,7 +338,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea }); quote! { variant( - :: #scale_info ::build::Variants::with_fields() + #scale_info::build::Variants::with_fields() #( #variants)* ) } diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index 8a64dd85..4c5f9e6c 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -66,14 +66,14 @@ pub fn make_where_clause<'a>( } else { where_clause .predicates - .push(parse_quote!(#ty : :: #scale_info ::TypeInfo + 'static)); + .push(parse_quote!(#ty : #scale_info ::TypeInfo + 'static)); } }); generics.type_params().into_iter().for_each(|type_param| { let ident = type_param.ident.clone(); let mut bounds = type_param.bounds.clone(); - bounds.push(parse_quote!(:: #scale_info ::TypeInfo)); + bounds.push(parse_quote!(#scale_info ::TypeInfo)); bounds.push(parse_quote!('static)); where_clause .predicates diff --git a/src/form.rs b/src/form.rs index 989d86a9..52d6f6f6 100644 --- a/src/form.rs +++ b/src/form.rs @@ -60,6 +60,7 @@ pub trait Form { /// through the registry and `IntoPortable`. #[cfg_attr(feature = "serde", derive(Serialize))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub enum MetaForm {} impl Form for MetaForm { diff --git a/src/impls.rs b/src/impls.rs index ae6b3b47..cb5beb09 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -33,6 +33,18 @@ use crate::{ TypeDefTuple, TypeInfo, }; +use core::num::{ + NonZeroI128, + NonZeroI16, + NonZeroI32, + NonZeroI64, + NonZeroI8, + NonZeroU128, + NonZeroU16, + NonZeroU32, + NonZeroU64, + NonZeroU8, +}; macro_rules! impl_metadata_for_primitives { ( $( $t:ty => $ident_kind:expr, )* ) => { $( @@ -119,6 +131,34 @@ impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P); +macro_rules! impl_for_non_zero { + ( $( $t: ty ),* $(,)? ) => { + $( + impl TypeInfo for $t { + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::prelude(stringify!($t))) + .composite(Fields::unnamed().field_of::<$t>(stringify!($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 5fc7b55c..438c87e7 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -32,6 +32,14 @@ use crate::prelude::{ vec::Vec, }; +use crate::{ + build::Fields, + form::MetaForm, + Path, + Type, + TypeInfo, +}; + #[cfg(feature = "serde")] use serde::{ Deserialize, @@ -72,6 +80,19 @@ impl scale::Decode for UntrackedSymbol { } } +// TODO: we should be able to derive this. +impl TypeInfo for UntrackedSymbol +where + T: TypeInfo + 'static, +{ + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::prelude("Path")) + .composite(Fields::named().field_of::("id", "NonZeroU32")) + } +} + impl UntrackedSymbol { /// Returns the index to the symbol in the interner table. pub fn id(&self) -> NonZeroU32 { diff --git a/src/meta_type.rs b/src/meta_type.rs index db5fbc39..9ce542b5 100644 --- a/src/meta_type.rs +++ b/src/meta_type.rs @@ -27,7 +27,9 @@ use crate::prelude::{ }; use crate::{ + build::Fields, form::MetaForm, + Path, Type, TypeInfo, }; @@ -49,6 +51,18 @@ pub struct MetaType { type_id: TypeId, } +// TODO: this is a total hack. Not sure what we can do here. +impl TypeInfo for MetaType { + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::new("MetaType", "meta_type")) + .composite( + Fields::named().field_of::("type_id", "TypeId"), + ) + } +} + impl PartialEq for MetaType { fn eq(&self, other: &Self) -> bool { self.type_id == other.type_id diff --git a/src/registry.rs b/src/registry.rs index 6e29472c..221a9e22 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -46,6 +46,7 @@ use crate::{ use scale::Encode; #[cfg(feature = "serde")] use serde::{ + de::DeserializeOwned, Deserialize, Serialize, }; @@ -166,6 +167,15 @@ impl Registry { /// A read-only registry containing types in their portable form for serialization. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +// #[cfg_attr(feature = "serde", derive(Serialize))] +// serialize = "T::Type: Serialize, T::String: Serialize", +// TODO: do we need this? +#[cfg_attr( + feature = "serde", + serde(bound( + deserialize = "::Type: DeserializeOwned, ::String: DeserializeOwned", + )) +)] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(Clone, Debug, PartialEq, Eq, Encode)] pub struct PortableRegistry { diff --git a/src/ty/composite.rs b/src/ty/composite.rs index 769c58b8..a5e7d612 100644 --- a/src/ty/composite.rs +++ b/src/ty/composite.rs @@ -70,6 +70,7 @@ use serde::{ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefComposite { /// The fields of the composite type. #[cfg_attr( diff --git a/src/ty/fields.rs b/src/ty/fields.rs index 1ef06ce9..7e19d958 100644 --- a/src/ty/fields.rs +++ b/src/ty/fields.rs @@ -67,6 +67,7 @@ use serde::{ #[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Field { /// The name of the field. None for unnamed fields. #[cfg_attr( diff --git a/src/ty/mod.rs b/src/ty/mod.rs index e3dd5cf4..bbd48f26 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -62,6 +62,8 @@ pub use self::{ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)] +// TODO: this should work +// #[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 #[cfg_attr( @@ -80,6 +82,28 @@ pub struct Type { type_def: TypeDef, } +impl TypeInfo for Type +where + Path: TypeInfo + 'static, + TypeDef: TypeInfo + 'static, + T: Form + TypeInfo + 'static, + // TODO: why doesn't this show up in the derived version? + ::Type: TypeInfo + 'static, +{ + type Identity = Self; + fn type_info() -> Type { + Type::builder() + .path(Path::new("Type", "scale_info::ty")) + .type_params(tuple_meta_type!(T)) + .composite( + crate::build::Fields::named() + .field_of::>("path", "Path") + .field_of::>("type_params", "Vec") + .field_of::>("type_def", "TypeDef"), + ) + } +} + impl IntoPortable for Type { type Output = Type; @@ -162,6 +186,7 @@ where #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub enum TypeDef { /// A composite type (e.g. a struct or a tuple) Composite(TypeDefComposite), @@ -203,6 +228,7 @@ impl IntoPortable for TypeDef { #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub enum TypeDefPrimitive { /// `bool` type Bool, @@ -240,6 +266,7 @@ pub enum TypeDefPrimitive { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefArray { /// The length of the array type. len: u32, @@ -294,6 +321,7 @@ where #[cfg_attr(feature = "serde", serde(transparent))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefTuple { /// The types of the tuple fields. fields: Vec, @@ -340,6 +368,7 @@ where #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefSequence { /// The element type of the sequence type. #[cfg_attr(feature = "serde", serde(rename = "type"))] @@ -390,6 +419,7 @@ where #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefCompact { /// The type wrapped in [`Compact`], i.e. the `T` in `Compact`. #[cfg_attr(feature = "serde", serde(rename = "type"))] @@ -435,6 +465,7 @@ where #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefPhantom { /// The PhantomData type parameter #[cfg_attr(feature = "serde", serde(rename = "type"))] diff --git a/src/ty/path.rs b/src/ty/path.rs index 4df862ee..5d191983 100644 --- a/src/ty/path.rs +++ b/src/ty/path.rs @@ -58,6 +58,7 @@ use serde::{ #[cfg_attr(feature = "serde", serde(transparent))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Path { /// The segments of the namespace. segments: Vec, diff --git a/src/ty/variant.rs b/src/ty/variant.rs index b201fc66..07731012 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -83,6 +83,7 @@ use serde::{ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, From, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct TypeDefVariant { /// The variants of a variant type #[cfg_attr( @@ -149,6 +150,7 @@ where )] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Debug, Encode)] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct Variant { /// The name of the variant. name: T::String, diff --git a/test_suite/Cargo.toml b/test_suite/Cargo.toml index 095f8127..0cb6b3be 100644 --- a/test_suite/Cargo.toml +++ b/test_suite/Cargo.toml @@ -10,7 +10,7 @@ license = "Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -scale-info = { path = "..", features = ["derive", "serde"] } +scale-info = { path = "..", features = ["derive", "serde"], default-features = false } scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] } serde = "1.0" diff --git a/test_suite/tests/derive.rs b/test_suite/tests/derive.rs index 55676c12..83bc27d6 100644 --- a/test_suite/tests/derive.rs +++ b/test_suite/tests/derive.rs @@ -298,14 +298,14 @@ fn whitespace_scrubbing_works() { #[rustversion::nightly] #[test] fn ui_tests() { - let t = trybuild::TestCases::new(); - t.compile_fail("tests/ui/fail_missing_derive.rs"); - t.compile_fail("tests/ui/fail_unions.rs"); - t.compile_fail("tests/ui/fail_use_codec_attrs_without_deriving_encode.rs"); - t.compile_fail("tests/ui/fail_with_invalid_codec_attrs.rs"); - t.pass("tests/ui/pass_with_valid_codec_attrs.rs"); - t.pass("tests/ui/pass_non_static_lifetime.rs"); - t.pass("tests/ui/pass_self_referential.rs"); - t.pass("tests/ui/pass_basic_generic_type.rs"); - t.pass("tests/ui/pass_complex_generic_self_referential_type.rs"); + // let t = trybuild::TestCases::new(); + // t.compile_fail("tests/ui/fail_missing_derive.rs"); + // t.compile_fail("tests/ui/fail_unions.rs"); + // t.compile_fail("tests/ui/fail_use_codec_attrs_without_deriving_encode.rs"); + // t.compile_fail("tests/ui/fail_with_invalid_codec_attrs.rs"); + // t.pass("tests/ui/pass_with_valid_codec_attrs.rs"); + // t.pass("tests/ui/pass_non_static_lifetime.rs"); + // t.pass("tests/ui/pass_self_referential.rs"); + // t.pass("tests/ui/pass_basic_generic_type.rs"); + // t.pass("tests/ui/pass_complex_generic_self_referential_type.rs"); } From c2f0f067acb55193485d8482d0e61ff76f265bbf Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 3 Mar 2021 19:00:06 +0100 Subject: [PATCH 02/20] Review grumbles Prepend `::` to paths when not deriving for `scale-info`. Alias self as `scale-info` Prefer unwrap_or_else to expect Add todo about broken features (break trybuild tests) --- derive/src/lib.rs | 58 +++++++++++++++++++++++--------------- derive/src/trait_bounds.rs | 12 +++++--- src/registry.rs | 10 ------- src/ty/mod.rs | 2 +- test_suite/Cargo.toml | 4 ++- test_suite/tests/derive.rs | 20 ++++++------- 6 files changed, 58 insertions(+), 48 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 6037105f..9c9abc63 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -// #![cfg_attr(not(feature = "std"), no_std)] +#![cfg_attr(not(feature = "std"), no_std)] extern crate alloc; extern crate proc_macro; @@ -80,21 +80,23 @@ fn generate_type(input: TokenStream2) -> Result { // If scale-info is not among the dependencies then we must be deriving // types for the scale-info crate itself, in which case we need to rename // "self" to something, so the object paths keep working. - let (scale_info, import_self_as_scale_info) = { + let (scale_info, import_self_as_scale_info, root_marker) = { let actual_crate_name = proc_macro_crate::crate_name("scale-info"); if let Err(e) = actual_crate_name { if e.starts_with("Could not find `scale-info`") { - (Ident::new("_scale_info", Span::call_site()), true) + (Ident::new("scale_info", Span::call_site()), true, quote! {}) } else { return Err(syn::Error::new(Span::call_site(), e)) } } else { + // TODO: maybe it's better to build a TokenStream with the :: and the crate name ( Ident::new( - &actual_crate_name.expect("Checked Err above; qed"), + &actual_crate_name.unwrap_or_else(|_| panic!("Checked for Err above and now it's not Ok. The world is broken.")), Span::call_site(), ), false, + quote!{ :: }, ) } }; @@ -113,20 +115,20 @@ fn generate_type(input: TokenStream2) -> Result { &ast.generics, &ast.data, &scale_info, + &root_marker, &parity_scale_codec, )?; - let generic_type_ids = ast.generics.type_params().map(|ty| { let ty_ident = &ty.ident; quote! { - #scale_info::meta_type::<#ty_ident>() + #root_marker #scale_info::meta_type::<#ty_ident>() } }); let mut ast: DeriveInput = syn::parse2(input.clone())?; let build_type = match &ast.data { - Data::Struct(ref s) => generate_composite_type(s, &scale_info), - Data::Enum(ref e) => generate_variant_type(e, &scale_info), + Data::Struct(ref s) => generate_composite_type(s, &scale_info, &root_marker), + Data::Enum(ref e) => generate_variant_type(e, &scale_info, &root_marker), Data::Union(_) => return Err(Error::new_spanned(input, "Unions not supported")), }; @@ -136,18 +138,18 @@ fn generate_type(input: TokenStream2) -> Result { }); let generic_types = ast.generics.type_params(); let type_info_impl = quote! { - impl <#( #generic_types ),*> #scale_info::TypeInfo for #ident #ty_generics #where_clause { + impl <#( #generic_types ),*> #root_marker #scale_info::TypeInfo for #ident #ty_generics #where_clause { type Identity = Self; fn type_info() -> #scale_info::Type { - #scale_info::Type::builder() - .path(#scale_info::Path::new(stringify!(#ident), module_path!())) - .type_params(#scale_info::prelude::vec![ #( #generic_type_ids ),* ]) + #root_marker #scale_info::Type::builder() + .path(#root_marker #scale_info::Path::new(stringify!(#ident), module_path!())) + .type_params(#root_marker #scale_info::prelude::vec![ #( #generic_type_ids ),* ]) .#build_type } }; }; let crate_rename = if import_self_as_scale_info { - quote! { extern crate self as _scale_info; } + quote! { extern crate self as scale_info; } } else { quote! {} }; @@ -238,7 +240,11 @@ fn clean_type_string(input: &str) -> String { .replace("& \'", "&'") } -fn generate_composite_type(data_struct: &DataStruct, scale_info: &Ident) -> TokenStream2 { +fn generate_composite_type( + data_struct: &DataStruct, + scale_info: &Ident, + root_marker: &TokenStream2, +) -> TokenStream2 { let fields = match data_struct.fields { Fields::Named(ref fs) => { let fields = generate_fields(&fs.named); @@ -255,13 +261,17 @@ fn generate_composite_type(data_struct: &DataStruct, scale_info: &Ident) -> Toke } }; quote! { - composite(#scale_info::build::Fields::#fields) + composite(#root_marker #scale_info::build::Fields::#fields) } } type VariantList = Punctuated; -fn generate_c_like_enum_def(variants: &VariantList, scale_info: &Ident) -> TokenStream2 { +fn generate_c_like_enum_def( + variants: &VariantList, + scale_info: &Ident, + root_marker: &TokenStream2, +) -> TokenStream2 { let variants = variants.into_iter().enumerate().map(|(i, v)| { let name = &v.ident; let discriminant = if let Some(( @@ -285,7 +295,7 @@ fn generate_c_like_enum_def(variants: &VariantList, scale_info: &Ident) -> Token }); quote! { variant( - #scale_info::build::Variants::fieldless() + #root_marker #scale_info::build::Variants::fieldless() #( #variants )* ) } @@ -298,11 +308,15 @@ fn is_c_like_enum(variants: &VariantList) -> bool { variants.iter().all(|v| matches!(v.fields, Fields::Unit)) } -fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStream2 { +fn generate_variant_type( + data_enum: &DataEnum, + scale_info: &Ident, + root_marker: &TokenStream2, +) -> TokenStream2 { let variants = &data_enum.variants; if is_c_like_enum(&variants) { - return generate_c_like_enum_def(variants, scale_info) + return generate_c_like_enum_def(variants, scale_info, root_marker) } let variants = variants.into_iter().map(|v| { @@ -314,7 +328,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea quote! { .variant( #v_name, - #scale_info::build::Fields::named() + #root_marker #scale_info::build::Fields::named() #( #fields)* ) } @@ -324,7 +338,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea quote! { .variant( #v_name, - #scale_info::build::Fields::unnamed() + #root_marker #scale_info::build::Fields::unnamed() #( #fields)* ) } @@ -338,7 +352,7 @@ fn generate_variant_type(data_enum: &DataEnum, scale_info: &Ident) -> TokenStrea }); quote! { variant( - #scale_info::build::Variants::with_fields() + #root_marker #scale_info::build::Variants::with_fields() #( #variants)* ) } diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index 4c5f9e6c..cf1634b4 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -13,7 +13,10 @@ // limitations under the License. use alloc::vec::Vec; -use proc_macro2::Ident; +use proc_macro2::{ + Ident, + TokenStream, +}; use syn::{ parse_quote, punctuated::Punctuated, @@ -33,6 +36,7 @@ pub fn make_where_clause<'a>( generics: &'a Generics, data: &'a syn::Data, scale_info: &Ident, + root_marker: &TokenStream, parity_scale_codec: &Ident, ) -> Result { let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| { @@ -62,18 +66,18 @@ pub fn make_where_clause<'a>( .push(parse_quote!(#ty : :: #parity_scale_codec ::HasCompact)); where_clause .predicates - .push(parse_quote!(<#ty as :: #parity_scale_codec ::HasCompact>::Type : :: #scale_info ::TypeInfo + 'static)); + .push(parse_quote!(<#ty as :: #parity_scale_codec ::HasCompact>::Type : #root_marker #scale_info ::TypeInfo + 'static)); } else { where_clause .predicates - .push(parse_quote!(#ty : #scale_info ::TypeInfo + 'static)); + .push(parse_quote!(#ty : #root_marker #scale_info ::TypeInfo + 'static)); } }); generics.type_params().into_iter().for_each(|type_param| { let ident = type_param.ident.clone(); let mut bounds = type_param.bounds.clone(); - bounds.push(parse_quote!(#scale_info ::TypeInfo)); + bounds.push(parse_quote!(#root_marker #scale_info ::TypeInfo)); bounds.push(parse_quote!('static)); where_clause .predicates diff --git a/src/registry.rs b/src/registry.rs index 221a9e22..6e29472c 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -46,7 +46,6 @@ use crate::{ use scale::Encode; #[cfg(feature = "serde")] use serde::{ - de::DeserializeOwned, Deserialize, Serialize, }; @@ -167,15 +166,6 @@ impl Registry { /// A read-only registry containing types in their portable form for serialization. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -// #[cfg_attr(feature = "serde", derive(Serialize))] -// serialize = "T::Type: Serialize, T::String: Serialize", -// TODO: do we need this? -#[cfg_attr( - feature = "serde", - serde(bound( - deserialize = "::Type: DeserializeOwned, ::String: DeserializeOwned", - )) -)] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(Clone, Debug, PartialEq, Eq, Encode)] pub struct PortableRegistry { diff --git a/src/ty/mod.rs b/src/ty/mod.rs index bbd48f26..fd05b914 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -136,7 +136,7 @@ impl_from_type_def_for_type!( ); impl Type { - /// Create a [`TypeBuilder`](`crate::build::TypeBuilder`) the public API for constructing a [`Type`] + /// Create a [`TypeBuilder`](`crate::build::TypeBuilder`), the public API for constructing a [`Type`] pub fn builder() -> TypeBuilder { TypeBuilder::default() } diff --git a/test_suite/Cargo.toml b/test_suite/Cargo.toml index 0cb6b3be..b2534b58 100644 --- a/test_suite/Cargo.toml +++ b/test_suite/Cargo.toml @@ -10,7 +10,9 @@ license = "Apache-2.0" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -scale-info = { path = "..", features = ["derive", "serde"], default-features = false } +scale-info = { path = "..", features = ["derive", "serde"] } +# TODO: this should work +# scale-info = { path = "..", features = ["derive", "serde"], default-features = false } scale = { package = "parity-scale-codec", version = "2.0", default-features = false, features = ["derive"] } serde = "1.0" diff --git a/test_suite/tests/derive.rs b/test_suite/tests/derive.rs index 83bc27d6..55676c12 100644 --- a/test_suite/tests/derive.rs +++ b/test_suite/tests/derive.rs @@ -298,14 +298,14 @@ fn whitespace_scrubbing_works() { #[rustversion::nightly] #[test] fn ui_tests() { - // let t = trybuild::TestCases::new(); - // t.compile_fail("tests/ui/fail_missing_derive.rs"); - // t.compile_fail("tests/ui/fail_unions.rs"); - // t.compile_fail("tests/ui/fail_use_codec_attrs_without_deriving_encode.rs"); - // t.compile_fail("tests/ui/fail_with_invalid_codec_attrs.rs"); - // t.pass("tests/ui/pass_with_valid_codec_attrs.rs"); - // t.pass("tests/ui/pass_non_static_lifetime.rs"); - // t.pass("tests/ui/pass_self_referential.rs"); - // t.pass("tests/ui/pass_basic_generic_type.rs"); - // t.pass("tests/ui/pass_complex_generic_self_referential_type.rs"); + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/fail_missing_derive.rs"); + t.compile_fail("tests/ui/fail_unions.rs"); + t.compile_fail("tests/ui/fail_use_codec_attrs_without_deriving_encode.rs"); + t.compile_fail("tests/ui/fail_with_invalid_codec_attrs.rs"); + t.pass("tests/ui/pass_with_valid_codec_attrs.rs"); + t.pass("tests/ui/pass_non_static_lifetime.rs"); + t.pass("tests/ui/pass_self_referential.rs"); + t.pass("tests/ui/pass_basic_generic_type.rs"); + t.pass("tests/ui/pass_complex_generic_self_referential_type.rs"); } From b4ba1545af25a4fa5edd0656d3b3c907561c25f8 Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 3 Mar 2021 19:41:01 +0100 Subject: [PATCH 03/20] Less noise is better: build a TokenStream2 containing the "::" prefix Move scale-info crate name construction to own function --- derive/src/lib.rs | 85 ++++++++++++++++++-------------------- derive/src/trait_bounds.rs | 9 ++-- 2 files changed, 44 insertions(+), 50 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 9c9abc63..75f0d3dc 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -76,31 +76,7 @@ fn generate(input: TokenStream2) -> Result { fn generate_type(input: TokenStream2) -> Result { let mut ast: DeriveInput = syn::parse2(input.clone())?; - // Find the name given to the `scale-info` crate in the context we run in. - // If scale-info is not among the dependencies then we must be deriving - // types for the scale-info crate itself, in which case we need to rename - // "self" to something, so the object paths keep working. - let (scale_info, import_self_as_scale_info, root_marker) = { - let actual_crate_name = proc_macro_crate::crate_name("scale-info"); - if let Err(e) = actual_crate_name { - if e.starts_with("Could not find `scale-info`") { - (Ident::new("scale_info", Span::call_site()), true, quote! {}) - } else { - return Err(syn::Error::new(Span::call_site(), e)) - } - } else { - // TODO: maybe it's better to build a TokenStream with the :: and the crate name - ( - Ident::new( - &actual_crate_name.unwrap_or_else(|_| panic!("Checked for Err above and now it's not Ok. The world is broken.")), - Span::call_site(), - ), - false, - quote!{ :: }, - ) - } - }; - + let (scale_info, import_self_as_scale_info) = scale_info_crate_tokens()?; let parity_scale_codec = crate_name_ident("parity-scale-codec")?; let ident = &ast.ident; @@ -115,20 +91,19 @@ fn generate_type(input: TokenStream2) -> Result { &ast.generics, &ast.data, &scale_info, - &root_marker, &parity_scale_codec, )?; let generic_type_ids = ast.generics.type_params().map(|ty| { let ty_ident = &ty.ident; quote! { - #root_marker #scale_info::meta_type::<#ty_ident>() + #scale_info::meta_type::<#ty_ident>() } }); let mut ast: DeriveInput = syn::parse2(input.clone())?; let build_type = match &ast.data { - Data::Struct(ref s) => generate_composite_type(s, &scale_info, &root_marker), - Data::Enum(ref e) => generate_variant_type(e, &scale_info, &root_marker), + Data::Struct(ref s) => generate_composite_type(s, &scale_info), + Data::Enum(ref e) => generate_variant_type(e, &scale_info), Data::Union(_) => return Err(Error::new_spanned(input, "Unions not supported")), }; @@ -138,12 +113,12 @@ fn generate_type(input: TokenStream2) -> Result { }); let generic_types = ast.generics.type_params(); let type_info_impl = quote! { - impl <#( #generic_types ),*> #root_marker #scale_info::TypeInfo for #ident #ty_generics #where_clause { + impl <#( #generic_types ),*> #scale_info::TypeInfo for #ident #ty_generics #where_clause { type Identity = Self; fn type_info() -> #scale_info::Type { - #root_marker #scale_info::Type::builder() - .path(#root_marker #scale_info::Path::new(stringify!(#ident), module_path!())) - .type_params(#root_marker #scale_info::prelude::vec![ #( #generic_type_ids ),* ]) + #scale_info::Type::builder() + .path(#scale_info::Path::new(stringify!(#ident), module_path!())) + .type_params(#scale_info::prelude::vec![ #( #generic_type_ids ),* ]) .#build_type } }; @@ -170,6 +145,29 @@ fn crate_name_ident(name: &str) -> Result { .map_err(|e| syn::Error::new(Span::call_site(), &e)) } +/// Find the name given to the `scale-info` crate in the context we run in. +/// If scale-info is not among the dependencies then we must be deriving +/// types for the scale-info crate itself, in which case we need to rename +/// "self" to something, so the object paths keep working. +fn scale_info_crate_tokens() -> Result<(TokenStream2, bool)> { + const SCALE_INFO_CRATE_NAME: &'static str = "scale-info"; + let actual_crate_name = proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME); + if let Err(e) = actual_crate_name { + if e.starts_with(&alloc::format!("Could not find `{}`", SCALE_INFO_CRATE_NAME)) { + let ident = Ident::new("scale_info", Span::call_site()); + Ok((quote!{ #ident }, true)) + } else { + Err(syn::Error::new(Span::call_site(), e)) + } + } else { + let ident = Ident::new( + &actual_crate_name.unwrap_or_else(|_| panic!("Checked for Err above and now it's not Ok. The world is broken.")), + Span::call_site(), + ); + Ok(( quote!{ :: #ident }, false, )) + } +} + type FieldsList = Punctuated; fn generate_fields(fields: &FieldsList) -> Vec { @@ -242,8 +240,7 @@ fn clean_type_string(input: &str) -> String { fn generate_composite_type( data_struct: &DataStruct, - scale_info: &Ident, - root_marker: &TokenStream2, + scale_info: &TokenStream2, ) -> TokenStream2 { let fields = match data_struct.fields { Fields::Named(ref fs) => { @@ -261,7 +258,7 @@ fn generate_composite_type( } }; quote! { - composite(#root_marker #scale_info::build::Fields::#fields) + composite(#scale_info::build::Fields::#fields) } } @@ -269,8 +266,7 @@ type VariantList = Punctuated; fn generate_c_like_enum_def( variants: &VariantList, - scale_info: &Ident, - root_marker: &TokenStream2, + scale_info: &TokenStream2, ) -> TokenStream2 { let variants = variants.into_iter().enumerate().map(|(i, v)| { let name = &v.ident; @@ -295,7 +291,7 @@ fn generate_c_like_enum_def( }); quote! { variant( - #root_marker #scale_info::build::Variants::fieldless() + #scale_info::build::Variants::fieldless() #( #variants )* ) } @@ -310,13 +306,12 @@ fn is_c_like_enum(variants: &VariantList) -> bool { fn generate_variant_type( data_enum: &DataEnum, - scale_info: &Ident, - root_marker: &TokenStream2, + scale_info: &TokenStream2, ) -> TokenStream2 { let variants = &data_enum.variants; if is_c_like_enum(&variants) { - return generate_c_like_enum_def(variants, scale_info, root_marker) + return generate_c_like_enum_def(variants, scale_info) } let variants = variants.into_iter().map(|v| { @@ -328,7 +323,7 @@ fn generate_variant_type( quote! { .variant( #v_name, - #root_marker #scale_info::build::Fields::named() + #scale_info::build::Fields::named() #( #fields)* ) } @@ -338,7 +333,7 @@ fn generate_variant_type( quote! { .variant( #v_name, - #root_marker #scale_info::build::Fields::unnamed() + #scale_info::build::Fields::unnamed() #( #fields)* ) } @@ -352,7 +347,7 @@ fn generate_variant_type( }); quote! { variant( - #root_marker #scale_info::build::Variants::with_fields() + #scale_info::build::Variants::with_fields() #( #variants)* ) } diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index cf1634b4..29fb4690 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -35,8 +35,7 @@ pub fn make_where_clause<'a>( input_ident: &'a Ident, generics: &'a Generics, data: &'a syn::Data, - scale_info: &Ident, - root_marker: &TokenStream, + scale_info: &TokenStream, parity_scale_codec: &Ident, ) -> Result { let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| { @@ -66,18 +65,18 @@ pub fn make_where_clause<'a>( .push(parse_quote!(#ty : :: #parity_scale_codec ::HasCompact)); where_clause .predicates - .push(parse_quote!(<#ty as :: #parity_scale_codec ::HasCompact>::Type : #root_marker #scale_info ::TypeInfo + 'static)); + .push(parse_quote!(<#ty as :: #parity_scale_codec ::HasCompact>::Type : #scale_info ::TypeInfo + 'static)); } else { where_clause .predicates - .push(parse_quote!(#ty : #root_marker #scale_info ::TypeInfo + 'static)); + .push(parse_quote!(#ty : #scale_info ::TypeInfo + 'static)); } }); generics.type_params().into_iter().for_each(|type_param| { let ident = type_param.ident.clone(); let mut bounds = type_param.bounds.clone(); - bounds.push(parse_quote!(#root_marker #scale_info ::TypeInfo)); + bounds.push(parse_quote!(#scale_info ::TypeInfo)); bounds.push(parse_quote!('static)); where_clause .predicates From b1d26c27db55b638dbfbfaa6f4ef943fff04829a Mon Sep 17 00:00:00 2001 From: David Palm Date: Wed, 3 Mar 2021 19:53:39 +0100 Subject: [PATCH 04/20] Use `crate::` when deriving for `scale-info` itself --- derive/src/lib.rs | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 75f0d3dc..94a046e2 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -76,7 +76,7 @@ fn generate(input: TokenStream2) -> Result { fn generate_type(input: TokenStream2) -> Result { let mut ast: DeriveInput = syn::parse2(input.clone())?; - let (scale_info, import_self_as_scale_info) = scale_info_crate_tokens()?; + let scale_info = scale_info_crate_tokens()?; let parity_scale_codec = crate_name_ident("parity-scale-codec")?; let ident = &ast.ident; @@ -123,16 +123,10 @@ fn generate_type(input: TokenStream2) -> Result { } }; }; - let crate_rename = if import_self_as_scale_info { - quote! { extern crate self as scale_info; } - } else { - quote! {} - }; Ok(quote! { // TODO: are these needed? // #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const _: () = { - #crate_rename #type_info_impl }; }) @@ -149,13 +143,13 @@ fn crate_name_ident(name: &str) -> Result { /// If scale-info is not among the dependencies then we must be deriving /// types for the scale-info crate itself, in which case we need to rename /// "self" to something, so the object paths keep working. -fn scale_info_crate_tokens() -> Result<(TokenStream2, bool)> { +fn scale_info_crate_tokens() -> Result { const SCALE_INFO_CRATE_NAME: &'static str = "scale-info"; let actual_crate_name = proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME); if let Err(e) = actual_crate_name { + // A proper error type would be good here (https://github.com/bkchr/proc-macro-crate/issues/7) if e.starts_with(&alloc::format!("Could not find `{}`", SCALE_INFO_CRATE_NAME)) { - let ident = Ident::new("scale_info", Span::call_site()); - Ok((quote!{ #ident }, true)) + Ok(quote!{ crate }) } else { Err(syn::Error::new(Span::call_site(), e)) } @@ -164,7 +158,7 @@ fn scale_info_crate_tokens() -> Result<(TokenStream2, bool)> { &actual_crate_name.unwrap_or_else(|_| panic!("Checked for Err above and now it's not Ok. The world is broken.")), Span::call_site(), ); - Ok(( quote!{ :: #ident }, false, )) + Ok(quote!{ :: #ident }) } } From 22fb440422150820bd196086a09c96f6f94678d9 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 08:05:32 +0100 Subject: [PATCH 05/20] Derive TypeInfo for UntrackedSymbol --- src/interner.rs | 22 +--------------------- 1 file changed, 1 insertion(+), 21 deletions(-) diff --git a/src/interner.rs b/src/interner.rs index 438c87e7..d160916d 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -32,14 +32,6 @@ use crate::prelude::{ vec::Vec, }; -use crate::{ - build::Fields, - form::MetaForm, - Path, - Type, - TypeInfo, -}; - #[cfg(feature = "serde")] use serde::{ Deserialize, @@ -53,6 +45,7 @@ use serde::{ #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(transparent))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] pub struct UntrackedSymbol { /// The index to the symbol in the interner table. id: NonZeroU32, @@ -80,19 +73,6 @@ impl scale::Decode for UntrackedSymbol { } } -// TODO: we should be able to derive this. -impl TypeInfo for UntrackedSymbol -where - T: TypeInfo + 'static, -{ - type Identity = Self; - fn type_info() -> Type { - Type::builder() - .path(Path::prelude("Path")) - .composite(Fields::named().field_of::("id", "NonZeroU32")) - } -} - impl UntrackedSymbol { /// Returns the index to the symbol in the interner table. pub fn id(&self) -> NonZeroU32 { From 00aae3405aa3c7c8bae8ec34aa6207bdc29d483e Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 09:41:29 +0100 Subject: [PATCH 06/20] wip --- src/meta_type.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/meta_type.rs b/src/meta_type.rs index 9ce542b5..a7d28cfa 100644 --- a/src/meta_type.rs +++ b/src/meta_type.rs @@ -54,11 +54,14 @@ pub struct MetaType { // TODO: this is a total hack. Not sure what we can do here. impl TypeInfo for MetaType { type Identity = Self; + fn type_info() -> Type { Type::builder() .path(Path::new("MetaType", "meta_type")) .composite( - Fields::named().field_of::("type_id", "TypeId"), + Fields::named() + // .field_of:: Type>("fn_type_info", "fn() -> Type") + .field_of::("type_id", "TypeId") ) } } From 5a165b18818c7b15935fc702fbe2167f134a1fbc Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 10:14:48 +0100 Subject: [PATCH 07/20] Add ref to ticket that blocks deriving Typeinfo for Type --- src/ty/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/ty/mod.rs b/src/ty/mod.rs index fd05b914..2f91db29 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -62,8 +62,6 @@ pub use self::{ #[cfg_attr(feature = "serde", serde(rename_all = "lowercase"))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)] -// TODO: this should work -// #[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 #[cfg_attr( @@ -82,13 +80,14 @@ pub struct Type { type_def: TypeDef, } +// Issue https://github.com/paritytech/scale-info/issues/73 is why we can't derive `TypeInfo` for `Type` impl TypeInfo for Type where Path: TypeInfo + 'static, TypeDef: TypeInfo + 'static, T: Form + TypeInfo + 'static, - // TODO: why doesn't this show up in the derived version? - ::Type: TypeInfo + 'static, + // We need this and the derive does not handle that yet. + T::Type: TypeInfo + 'static, { type Identity = Self; fn type_info() -> Type { From 9ac63062c3f1992c055e2a4dc26ef658ed9b5b89 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 11:05:46 +0100 Subject: [PATCH 08/20] Remove TypeInfo impl for MetaType --- derive/src/lib.rs | 16 ++++++++++------ src/meta_type.rs | 17 ----------------- 2 files changed, 10 insertions(+), 23 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 94a046e2..34d1edce 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -124,8 +124,7 @@ fn generate_type(input: TokenStream2) -> Result { }; }; Ok(quote! { - // TODO: are these needed? - // #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] + #[allow(non_upper_case_globals, unused_attributes, unused_qualifications)] const _: () = { #type_info_impl }; @@ -148,17 +147,22 @@ fn scale_info_crate_tokens() -> Result { let actual_crate_name = proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME); if let Err(e) = actual_crate_name { // A proper error type would be good here (https://github.com/bkchr/proc-macro-crate/issues/7) - if e.starts_with(&alloc::format!("Could not find `{}`", SCALE_INFO_CRATE_NAME)) { - Ok(quote!{ crate }) + if e.starts_with(&alloc::format!( + "Could not find `{}`", + SCALE_INFO_CRATE_NAME + )) { + Ok(quote! { crate }) } else { Err(syn::Error::new(Span::call_site(), e)) } } else { let ident = Ident::new( - &actual_crate_name.unwrap_or_else(|_| panic!("Checked for Err above and now it's not Ok. The world is broken.")), + &actual_crate_name.unwrap_or_else(|_| { + panic!("Checked for Err above and now it's not Ok. The world is broken.") + }), Span::call_site(), ); - Ok(quote!{ :: #ident }) + Ok(quote! { :: #ident }) } } diff --git a/src/meta_type.rs b/src/meta_type.rs index a7d28cfa..db5fbc39 100644 --- a/src/meta_type.rs +++ b/src/meta_type.rs @@ -27,9 +27,7 @@ use crate::prelude::{ }; use crate::{ - build::Fields, form::MetaForm, - Path, Type, TypeInfo, }; @@ -51,21 +49,6 @@ pub struct MetaType { type_id: TypeId, } -// TODO: this is a total hack. Not sure what we can do here. -impl TypeInfo for MetaType { - type Identity = Self; - - fn type_info() -> Type { - Type::builder() - .path(Path::new("MetaType", "meta_type")) - .composite( - Fields::named() - // .field_of:: Type>("fn_type_info", "fn() -> Type") - .field_of::("type_id", "TypeId") - ) - } -} - impl PartialEq for MetaType { fn eq(&self, other: &Self) -> bool { self.type_id == other.type_id From 39f84596ff7eb17e6e46fb577817255c9b8b93e4 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 11:08:38 +0100 Subject: [PATCH 09/20] Clippy is right --- derive/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 34d1edce..1c4acc99 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -143,7 +143,7 @@ fn crate_name_ident(name: &str) -> Result { /// types for the scale-info crate itself, in which case we need to rename /// "self" to something, so the object paths keep working. fn scale_info_crate_tokens() -> Result { - const SCALE_INFO_CRATE_NAME: &'static str = "scale-info"; + const SCALE_INFO_CRATE_NAME: &str = "scale-info"; let actual_crate_name = proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME); if let Err(e) = actual_crate_name { // A proper error type would be good here (https://github.com/bkchr/proc-macro-crate/issues/7) From 7db67784ff5ed76603362a3c02680e113bd0e235 Mon Sep 17 00:00:00 2001 From: David Palm Date: Thu, 4 Mar 2021 11:21:45 +0100 Subject: [PATCH 10/20] Cleanup --- Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 1994bf74..bf88d11c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -38,4 +38,3 @@ members = [ "derive", "test_suite", ] -# exclude = ["test_suite"] From 5c22f1912b407d7799bfa830126112460af890b7 Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 25 Jun 2021 17:00:05 +0200 Subject: [PATCH 11/20] Remove `NonZero*` impls --- src/impls.rs | 40 ---------------------------------------- 1 file changed, 40 deletions(-) diff --git a/src/impls.rs b/src/impls.rs index 24f9d8c4..95e7a2d8 100644 --- a/src/impls.rs +++ b/src/impls.rs @@ -41,18 +41,6 @@ use crate::{ TypeDefTuple, TypeInfo, }; -// use core::num::{ -// NonZeroI128, -// NonZeroI16, -// NonZeroI32, -// NonZeroI64, -// NonZeroI8, -// NonZeroU128, -// NonZeroU16, -// NonZeroU32, -// NonZeroU64, -// NonZeroU8, -// }; macro_rules! impl_metadata_for_primitives { ( $( $t:ty => $ident_kind:expr, )* ) => { $( @@ -128,34 +116,6 @@ impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S); impl_metadata_for_tuple!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T); -// macro_rules! impl_for_non_zero { -// ( $( $t: ty ),* $(,)? ) => { -// $( -// impl TypeInfo for $t { -// type Identity = Self; -// fn type_info() -> Type { -// Type::builder() -// .path(Path::prelude(stringify!($t))) -// .composite(Fields::unnamed().field(|f| f.ty::<$t>())) -// } -// } -// )* -// }; -// } - -// impl_for_non_zero!( -// NonZeroI8, -// NonZeroI16, -// NonZeroI32, -// NonZeroI64, -// NonZeroI128, -// NonZeroU8, -// NonZeroU16, -// NonZeroU32, -// NonZeroU64, -// NonZeroU128 -// ); - impl TypeInfo for Vec where T: TypeInfo + 'static, From 58dc3d2e5f195d7369020f639d25c7a00a6b0688 Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 25 Jun 2021 17:01:00 +0200 Subject: [PATCH 12/20] Cleanup --- src/ty/mod.rs | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/src/ty/mod.rs b/src/ty/mod.rs index 53c44082..8057117b 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -87,29 +87,6 @@ pub struct Type { docs: Vec, } -// // Issue https://github.com/paritytech/scale-info/issues/73 is why we can't derive `TypeInfo` for `Type` -// impl TypeInfo for Type -// where -// Path: TypeInfo + 'static, -// TypeDef: TypeInfo + 'static, -// T: Form + TypeInfo + 'static, -// // We need this and the derive does not handle that yet. -// T::Type: TypeInfo + 'static, -// { -// type Identity = Self; -// fn type_info() -> Type { -// Type::builder() -// .path(Path::new("Type", "scale_info::ty")) -// .type_params(tuple_meta_type!(T)) -// .composite( -// crate::build::Fields::named() -// .field_of::>("path", "Path") -// .field_of::>("type_params", "Vec") -// .field_of::>("type_def", "TypeDef"), -// ) -// } -// } - impl IntoPortable for Type { type Output = Type; From e73c061526ddf3805762a96e51a9033dcf3a6ffe Mon Sep 17 00:00:00 2001 From: David Palm Date: Fri, 25 Jun 2021 17:03:27 +0200 Subject: [PATCH 13/20] =?UTF-8?q?Don't=20bind=20<=E2=80=A6=20as=20HasCompa?= =?UTF-8?q?ct>::Type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- derive/src/trait_bounds.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index f9dec088..62f1e45d 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -72,9 +72,6 @@ pub fn make_where_clause<'a>( where_clause .predicates .push(parse_quote!(#ty : #parity_scale_codec ::HasCompact)); - where_clause - .predicates - .push(parse_quote!(<#ty as #parity_scale_codec ::HasCompact>::Type : #scale_info ::TypeInfo + 'static)); } else { where_clause .predicates From c7bfb5224d42248dfdc9ccb00f54d522d2493662 Mon Sep 17 00:00:00 2001 From: David Palm Date: Mon, 28 Jun 2021 17:14:05 +0200 Subject: [PATCH 14/20] Review grumbles --- Cargo.toml | 3 +-- derive/src/lib.rs | 7 +++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6a7f5e78..5f1c2f5c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,12 +34,11 @@ derive = [ dogfood = [ "derive" ] -# Enables decoding and deserialization of portable scale-info type metadata. # Include rustdoc strings in the type metadata. docs = [ "scale-info-derive/docs" ] -# enables decoding and deserialization of portable scale-info type metadata +# Enables decoding and deserialization of portable scale-info type metadata. decode = [ "scale/full" ] diff --git a/derive/src/lib.rs b/derive/src/lib.rs index a7203dcf..d98a4d82 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -138,10 +138,9 @@ fn crate_name_ident(name: &str) -> Result { .map_err(|e| syn::Error::new(Span::call_site(), &e)) } -/// Find the name given to the `scale-info` crate in the context we run in. -/// If scale-info is not among the dependencies then we must be deriving -/// types for the scale-info crate itself, in which case we need to rename -/// "self" to something, so the object paths keep working. +/// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not among the dependencies +/// then we must be deriving types for the scale-info crate itself, in which case we need to refer to it using the +/// reserved word "crate", so the object paths keep working. fn scale_info_crate_tokens() -> Result { use proc_macro_crate::FoundCrate; const SCALE_INFO_CRATE_NAME: &str = "scale-info"; From 89d44990770b7930cbe8e7f5a3c2efadd6644ed3 Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 29 Jun 2021 07:41:08 +0200 Subject: [PATCH 15/20] Fix comment --- derive/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index d98a4d82..a50eb1a7 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -138,9 +138,9 @@ fn crate_name_ident(name: &str) -> Result { .map_err(|e| syn::Error::new(Span::call_site(), &e)) } -/// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not among the dependencies -/// then we must be deriving types for the scale-info crate itself, in which case we need to refer to it using the -/// reserved word "crate", so the object paths keep working. +/// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not +/// among the dependencies then we must be deriving types for the scale-info crate itself, in which +/// case we need to refer to it using the reserved word "crate", so the object paths keep working. fn scale_info_crate_tokens() -> Result { use proc_macro_crate::FoundCrate; const SCALE_INFO_CRATE_NAME: &str = "scale-info"; From c7c19fc68ad5938bdc106c3f79f721a53cb7963e Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 29 Jun 2021 15:11:13 +0200 Subject: [PATCH 16/20] Address review feedback --- derive/src/lib.rs | 14 +++++++------- derive/src/trait_bounds.rs | 7 ++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index ad995df3..775fcd17 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -64,7 +64,7 @@ fn generate_type(input: TokenStream2) -> Result { let attrs = attr::Attributes::from_ast(&ast)?; - let scale_info = scale_info_crate_tokens()?; + let scale_info = scale_info_crate_path()?; let parity_scale_codec = crate_name_ident("parity-scale-codec")?; let ident = &ast.ident; @@ -135,15 +135,15 @@ fn crate_name_ident(name: &str) -> Result { /// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not /// among the dependencies then we must be deriving types for the scale-info crate itself, in which /// case we need to refer to it using the reserved word "crate", so the object paths keep working. -fn scale_info_crate_tokens() -> Result { +fn scale_info_crate_path() -> Result { use proc_macro_crate::FoundCrate; const SCALE_INFO_CRATE_NAME: &str = "scale-info"; let crate_ident = match proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME) { - Ok(FoundCrate::Itself) => quote! { crate }, + Ok(FoundCrate::Itself) => parse_quote! { crate }, Ok(FoundCrate::Name(name)) => { let ident = Ident::new(&name, Span::call_site()); - quote! { :: #ident } + parse_quote! { :: #ident } } Err(e) => return Err(syn::Error::new(Span::call_site(), e)), }; @@ -216,7 +216,7 @@ fn clean_type_string(input: &str) -> String { fn generate_composite_type( data_struct: &DataStruct, - scale_info: &TokenStream2, + scale_info: &syn::Path, ) -> TokenStream2 { let fields = match data_struct.fields { Fields::Named(ref fs) => { @@ -242,7 +242,7 @@ type VariantList = Punctuated; fn generate_c_like_enum_def( variants: &VariantList, - scale_info: &TokenStream2, + scale_info: &syn::Path, ) -> TokenStream2 { let variants = variants .into_iter() @@ -277,7 +277,7 @@ fn is_c_like_enum(variants: &VariantList) -> bool { fn generate_variant_type( data_enum: &DataEnum, - scale_info: &TokenStream2, + scale_info: &syn::Path, ) -> TokenStream2 { let variants = &data_enum.variants; diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index afd13b18..ffe17ea3 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -13,10 +13,7 @@ // limitations under the License. use alloc::vec::Vec; -use proc_macro2::{ - Ident, - TokenStream, -}; +use proc_macro2::Ident; use syn::{ parse_quote, punctuated::Punctuated, @@ -55,7 +52,7 @@ pub fn make_where_clause<'a>( input_ident: &'a Ident, generics: &'a Generics, data: &'a syn::Data, - scale_info: &TokenStream, + scale_info: &syn::Path, parity_scale_codec: &Ident, ) -> Result { let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| { From d3259c5aea23f6079eff785d5cb4bf9e80f3c704 Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 29 Jun 2021 15:18:15 +0200 Subject: [PATCH 17/20] fmt --- derive/src/lib.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 775fcd17..e4dd027d 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -275,10 +275,7 @@ fn is_c_like_enum(variants: &VariantList) -> bool { variants.iter().all(|v| matches!(v.fields, Fields::Unit)) } -fn generate_variant_type( - data_enum: &DataEnum, - scale_info: &syn::Path, -) -> TokenStream2 { +fn generate_variant_type(data_enum: &DataEnum, scale_info: &syn::Path) -> TokenStream2 { let variants = &data_enum.variants; if is_c_like_enum(variants) { From 5fd7525fa17e8e56d2731b2830ef0a2367dab081 Mon Sep 17 00:00:00 2001 From: David Palm Date: Tue, 24 Aug 2021 14:10:56 +0200 Subject: [PATCH 18/20] cleanup --- derive/src/trait_bounds.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/derive/src/trait_bounds.rs b/derive/src/trait_bounds.rs index b20cb605..6ff729a2 100644 --- a/derive/src/trait_bounds.rs +++ b/derive/src/trait_bounds.rs @@ -53,7 +53,6 @@ pub fn make_where_clause<'a>( generics: &'a Generics, data: &'a syn::Data, scale_info: &syn::Path, - // parity_scale_codec: &Ident, ) -> Result { let mut where_clause = generics.where_clause.clone().unwrap_or_else(|| { WhereClause { From ba2e94aa688fa388a3b16faf56c22e81b043c234 Mon Sep 17 00:00:00 2001 From: Giles Cope Date: Sat, 16 Jul 2022 15:22:28 +0100 Subject: [PATCH 19/20] Fixup after merge --- derive/src/lib.rs | 74 ++++++++++++++++++++++++----------------------- 1 file changed, 38 insertions(+), 36 deletions(-) diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 868ec3ca..b03aed7e 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -100,14 +100,14 @@ impl TypeInfoImpl { let ty_ident = &tp.ident; let ty = if self.attrs.skip_type_params().map_or(true, |skip| !skip.skip(tp)) { - quote! { ::core::option::Option::Some(:: #scale_info ::meta_type::<#ty_ident>()) } + quote! { ::core::option::Option::Some(#scale_info ::meta_type::<#ty_ident>()) } } else { quote! { ::core::option::Option::None } }; quote! { - :: #scale_info ::TypeParameter::new(::core::stringify!(#ty_ident), #ty) + #scale_info ::TypeParameter::new(::core::stringify!(#ty_ident), #ty) } }); @@ -122,7 +122,7 @@ impl TypeInfoImpl { let docs = self.generate_docs(&self.ast.attrs); Ok(quote! { - impl #impl_generics :: #scale_info ::TypeInfo for #ident #ty_generics #where_clause { + impl #impl_generics #scale_info ::TypeInfo for #ident #ty_generics #where_clause { type Identity = Self; @@ -159,7 +159,7 @@ impl TypeInfoImpl { }; quote! { - composite(:: #scale_info ::build::Fields::#fields) + composite( #scale_info ::build::Fields::#fields) } } @@ -259,7 +259,7 @@ impl TypeInfoImpl { }); quote! { variant( - :: #scale_info ::build::Variants::new() + #scale_info ::build::Variants::new() #( #variants )* ) @@ -302,39 +302,41 @@ impl TypeInfoImpl { } } -// /// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not -// /// among the dependencies then we must be deriving types for the scale-info crate itself, in which -// /// case we need to refer to it using the reserved word "crate", so the object paths keep working. -// fn scale_info_crate_path() -> Result { -// use proc_macro_crate::FoundCrate; -// const SCALE_INFO_CRATE_NAME: &str = "scale-info"; - -// let crate_ident = match proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME) { -// Ok(FoundCrate::Itself) => parse_quote! { crate }, -// Ok(FoundCrate::Name(name)) => { -// let crate_ident = Ident::new(&name, Span::call_site()); -// parse_quote! { :: #crate_ident } -// } -// Err(e) => return Err(syn::Error::new(Span::call_site(), e)), -// }; -// Ok(crate_ident) - -/// Get the name of a crate, to be robust against renamed dependencies. -fn crate_name_path(name: &str) -> Result { - proc_macro_crate::crate_name(name) - .map(|crate_name| { - use proc_macro_crate::FoundCrate::*; - match crate_name { - Itself => Ident::new("self", Span::call_site()).into(), - Name(name) => { - let crate_ident = Ident::new(&name, Span::call_site()); - parse_quote!( ::#crate_ident ) - } - } - }) - .map_err(|e| syn::Error::new(Span::call_site(), &e)) +/// Find the name given to the `scale-info` crate in the context we run in. If scale-info is not +/// among the dependencies then we must be deriving types for the scale-info crate itself, in which +/// case we need to refer to it using the reserved word "crate", so the object paths keep working. +fn crate_name_path(_name: &str) -> Result { + use proc_macro_crate::FoundCrate; + const SCALE_INFO_CRATE_NAME: &str = "scale-info"; + + let crate_ident = match proc_macro_crate::crate_name(SCALE_INFO_CRATE_NAME) { + Ok(FoundCrate::Itself) => parse_quote! { crate }, + Ok(FoundCrate::Name(name)) => { + let crate_ident = Ident::new(&name, Span::call_site()); + parse_quote! { #crate_ident } + } + Err(e) => return Err(syn::Error::new(Span::call_site(), e)), + }; + Ok(crate_ident) } +// /// Get the name of a crate, to be robust against renamed dependencies. +// fn crate_name_path(name: &str) -> Result { +// proc_macro_crate::crate_name(name) +// .map(|crate_name| { +// use proc_macro_crate::FoundCrate::*; +// match crate_name { +// Itself => parse_quote! { crate }, +// Ident::new("self", Span::call_site()).into(), +// Name(name) => { +// let crate_ident = Ident::new(&name, Span::call_site()); +// parse_quote!( ::#crate_ident ) +// } +// } +// }) +// .map_err(|e| syn::Error::new(Span::call_site(), &e)) +// } + fn crate_path(crate_path_attr: Option<&CratePathAttr>) -> Result { crate_path_attr .map(|path_attr| Ok(path_attr.path().clone())) From 3420903a69a0bfbf4c94a98240a3ba3ccc590060 Mon Sep 17 00:00:00 2001 From: Squirrel Date: Tue, 19 Jul 2022 09:15:35 +0100 Subject: [PATCH 20/20] additional support to allow frame-metadata to derive TypeInfo (#163) * support for frame-metadata to have TypeInfo --- src/form.rs | 1 + src/lib.rs | 14 ++++++++++++++ src/registry.rs | 2 ++ src/ty/mod.rs | 2 ++ 4 files changed, 19 insertions(+) diff --git a/src/form.rs b/src/form.rs index 53393bf5..2f1b8244 100644 --- a/src/form.rs +++ b/src/form.rs @@ -76,6 +76,7 @@ impl Form for MetaForm { /// the registry itself) but can no longer be used to resolve to the original /// underlying data. #[cfg_attr(feature = "serde", derive(Serialize))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Debug)] pub enum PortableForm {} diff --git a/src/lib.rs b/src/lib.rs index 8b8131ce..c8efca0d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -342,6 +342,8 @@ mod utils; #[cfg(test)] mod tests; +use core::any::TypeId; + #[doc(hidden)] pub use scale; @@ -391,3 +393,15 @@ where { MetaType::new::() } + +impl TypeInfo for TypeId { + type Identity = Self; + + fn type_info() -> Type { + Type::builder() + .path(Path::new("TypeId", "core::any")) + .composite(build::Fields::named() + .field(|f| f.ty::().name("t").type_name("u64")) + ) + } +} diff --git a/src/registry.rs b/src/registry.rs index 1e225f14..82f44364 100644 --- a/src/registry.rs +++ b/src/registry.rs @@ -162,6 +162,7 @@ impl Registry { #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[cfg_attr(all(feature = "serde", feature = "decode"), derive(serde::Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[derive(Clone, Debug, PartialEq, Eq, Encode)] pub struct PortableRegistry { types: Vec, @@ -199,6 +200,7 @@ impl PortableRegistry { #[cfg_attr(feature = "serde", derive(serde::Serialize))] #[cfg_attr(all(feature = "serde", feature = "decode"), derive(serde::Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[derive(Clone, Debug, PartialEq, Eq, Encode)] pub struct PortableType { #[codec(compact)] diff --git a/src/ty/mod.rs b/src/ty/mod.rs index d457b41f..71f0f275 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -179,6 +179,7 @@ where )) )] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, From, Debug, Encode)] pub struct TypeParameter { /// The name of the generic type parameter e.g. "T". @@ -549,6 +550,7 @@ where /// enabled, but can be decoded or deserialized into the `PortableForm` without this feature. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(any(feature = "std", feature = "decode"), derive(scale::Decode))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Encode, Debug)] pub struct TypeDefBitSequence { /// The type implementing [`bitvec::store::BitStore`].