diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index d88de063..e17dc308 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -40,6 +40,7 @@ jobs: - name: check-features run: | cargo check --no-default-features --features bit-vec + cargo check --no-default-features --features dogfood cargo check --no-default-features --features docs cargo check --no-default-features --features serde cargo check --no-default-features --features serde,decode diff --git a/Cargo.toml b/Cargo.toml index 0aff87b8..354d4e20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,11 +31,15 @@ std = [ derive = [ "scale-info-derive" ] +# Derive `TypeInfo` for our own types. +dogfood = [ + "derive" +] # 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 e5c9007f..b03aed7e 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -76,6 +76,7 @@ struct TypeInfoImpl { impl TypeInfoImpl { fn parse(input: TokenStream2) -> Result { let ast: DeriveInput = syn::parse2(input)?; + let attrs = attr::Attributes::from_ast(&ast)?; Ok(Self { ast, attrs }) @@ -98,12 +99,16 @@ impl TypeInfoImpl { let type_params = self.ast.generics.type_params().map(|tp| { 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) + } }); @@ -117,12 +122,14 @@ 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; + fn type_info() -> #scale_info::Type { - #scale_info::Type::builder() - .path(#scale_info::Path::new(::core::stringify!(#ident), ::core::module_path!())) - .type_params(#scale_info::prelude::vec![ #( #type_params ),* ]) + #scale_info ::Type::builder() + .path(#scale_info ::Path::new(::core::stringify!(#ident), ::core::module_path!())) + .type_params(#scale_info ::prelude::vec![ #( #type_params ),* ]) #docs .#build_type } @@ -152,7 +159,7 @@ impl TypeInfoImpl { }; quote! { - composite(#scale_info::build::Fields::#fields) + composite( #scale_info ::build::Fields::#fields) } } @@ -252,7 +259,8 @@ impl TypeInfoImpl { }); quote! { variant( - #scale_info::build::Variants::new() + #scale_info ::build::Variants::new() + #( #variants )* ) } @@ -294,22 +302,41 @@ impl TypeInfoImpl { } } -/// 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())) diff --git a/src/form.rs b/src/form.rs index 96ad1ff0..2f1b8244 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 { @@ -75,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/interner.rs b/src/interner.rs index 112575ec..624e5afd 100644 --- a/src/interner.rs +++ b/src/interner.rs @@ -46,6 +46,7 @@ use serde::{ )] #[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. #[codec(compact)] 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/composite.rs b/src/ty/composite.rs index c14d7860..01bd0d77 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 7b4a0c91..bad7953d 100644 --- a/src/ty/fields.rs +++ b/src/ty/fields.rs @@ -73,6 +73,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 b1defa7e..71f0f275 100644 --- a/src/ty/mod.rs +++ b/src/ty/mod.rs @@ -52,6 +52,7 @@ pub use self::{ /// A [`Type`] definition with optional metadata. #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "dogfood", derive(scale_info_derive::TypeInfo))] #[cfg_attr( feature = "serde", serde(bound( @@ -119,7 +120,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() } @@ -178,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". @@ -244,6 +246,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) #[codec(index = 0)] @@ -297,6 +300,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 #[codec(index = 0)] @@ -349,6 +353,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, @@ -403,6 +408,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, @@ -452,6 +458,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"))] @@ -502,6 +509,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"))] @@ -542,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`]. diff --git a/src/ty/path.rs b/src/ty/path.rs index 1d31ac71..55158a5e 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 cac1ee3f..a5511923 100644 --- a/src/ty/variant.rs +++ b/src/ty/variant.rs @@ -82,6 +82,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( @@ -148,6 +149,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,