From 6cef98d1ce1ecedb763ef48093c1455dd9cd2503 Mon Sep 17 00:00:00 2001 From: cheme Date: Mon, 7 Jan 2019 16:05:47 +0100 Subject: [PATCH] Decl_storage macro : force traits. (#1317) * Missing trait def on two calls. Slight mcla refact on transfo. * Allways provide GenesisConfig even when useless (for runtime module export). * Revert "Allways provide GenesisConfig even when useless (for runtime module" This reverts commit 84a29bc592023d1ee107519c58693ec19dbde2d2. * Fix Vec usage (from rstd). --- .../procedural/src/storage/transformation.rs | 112 +++++++++++------- srml/support/src/storage/generator.rs | 26 ++++ 2 files changed, 92 insertions(+), 46 deletions(-) diff --git a/srml/support/procedural/src/storage/transformation.rs b/srml/support/procedural/src/storage/transformation.rs index 2a2179e0ec18f..104c5c830c895 100644 --- a/srml/support/procedural/src/storage/transformation.rs +++ b/srml/support/procedural/src/storage/transformation.rs @@ -169,7 +169,7 @@ fn decl_store_extra_genesis( .. } = sline; - let is_simple = if let DeclStorageType::Simple(..) = storage_type { true } else { false }; + let type_infos = get_type_infos(storage_type); let mut opt_build; // need build line @@ -180,20 +180,16 @@ fn decl_store_extra_genesis( let ident = &getter.getfn.content; quote!( #ident ) }; - let option_extracteed = if let DeclStorageType::Simple(ref st) = storage_type { - if ext::has_parametric_type(st, traitinstance) { - is_trait_needed = true; - has_trait_field = true; - } - ext::extract_type_option(st) - } else { None }; - let is_option = option_extracteed.is_some(); - let storage_type = option_extracteed.unwrap_or_else(|| quote!( #storage_type )); + if type_infos.is_simple && ext::has_parametric_type(type_infos.full_type, traitinstance) { + is_trait_needed = true; + has_trait_field = true; + } + let storage_type = type_infos.typ.clone(); config_field.extend(quote!( pub #ident: #storage_type, )); opt_build = Some(build.as_ref().map(|b| &b.expr.content).map(|b|quote!( #b )) .unwrap_or_else(|| quote!( (|config: &GenesisConfig<#traitinstance>| config.#ident.clone()) ))); let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d| - if is_option { + if type_infos.is_option { quote!( #d.unwrap_or_default() ) } else { quote!( #d ) @@ -204,20 +200,25 @@ fn decl_store_extra_genesis( opt_build = build.as_ref().map(|b| &b.expr.content).map(|b| quote!( #b )); } + let typ = type_infos.typ; if let Some(builder) = opt_build { is_trait_needed = true; - if is_simple { + if type_infos.is_simple { builders.extend(quote!{{ use #scrate::codec::Encode; let v = (#builder)(&self); - r.insert(Self::hash(<#name<#traitinstance>>::key()).to_vec(), v.encode()); + r.insert(Self::hash( + <#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>>::key() + ).to_vec(), v.encode()); }}); } else { + let kty = type_infos.map_key.clone().expect("is not simple; qed"); builders.extend(quote!{{ use #scrate::codec::Encode; let data = (#builder)(&self); for (k, v) in data.into_iter() { - r.insert(Self::hash(&<#name<#traitinstance>>::key_for(k)).to_vec(), v.encode()); + let key = <#name<#traitinstance> as #scrate::storage::generator::StorageMap<#kty, #typ>>::key_for(&k); + r.insert(Self::hash(&key[..]).to_vec(), v.encode()); } }}); } @@ -361,25 +362,22 @@ fn decl_storage_items( .. } = sline; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; - let is_option = extracted_opt.is_some(); + let type_infos = get_type_infos(storage_type); + let gettype = type_infos.full_type; let fielddefault = default_value.inner.get(0).as_ref().map(|d| &d.expr).map(|d| quote!( #d )) .unwrap_or_else(|| quote!{ Default::default() }); - let typ = extracted_opt.unwrap_or(quote!( #gettype )); + let typ = type_infos.typ; - let option_simple_1 = if !is_option { + let option_simple_1 = if !type_infos.is_option { // raw type case quote!( unwrap_or_else ) } else { // Option<> type case quote!( or_else ) }; - let implementation = if is_simple { - let mutate_impl = if !is_option { + let implementation = if type_infos.is_simple { + let mutate_impl = if !type_infos.is_option { quote!{ >::put(&val, storage) } @@ -430,8 +428,8 @@ fn decl_storage_items( } } else { - let kty = stk.expect("is not simple; qed"); - let mutate_impl = if !is_option { + let kty = type_infos.map_key.expect("is not simple; qed"); + let mutate_impl = if !type_infos.is_option { quote!{ >::insert(key, &val, storage) } @@ -531,20 +529,19 @@ fn impl_store_fns( if let Some(getter) = getter { let get_fn = &getter.getfn.content; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; - let typ = extracted_opt.unwrap_or(quote!(#gettype)); - let item = if is_simple { + let type_infos = get_type_infos(storage_type); + let gettype = type_infos.full_type; + + let typ = type_infos.typ; + let item = if type_infos.is_simple { quote!{ pub fn #get_fn() -> #gettype { <#name<#traitinstance> as #scrate::storage::generator::StorageValue<#typ>> :: get(&#scrate::storage::RuntimeStorage) } } } else { - let kty = stk.expect("is not simple; qed"); + let kty = type_infos.map_key.expect("is not simple; qed"); // map quote!{ pub fn #get_fn>(key: K) -> #gettype { @@ -576,14 +573,11 @@ fn store_functions_to_metadata ( .. } = sline; - let (is_simple, extracted_opt, stk, gettype) = match storage_type { - DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), - DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), - }; + let type_infos = get_type_infos(storage_type); + let gettype = type_infos.full_type; - let is_option = extracted_opt.is_some(); - let typ = extracted_opt.unwrap_or(quote!( #gettype )); - let stype = if is_simple { + let typ = type_infos.typ; + let stype = if type_infos.is_simple { let styp = clean_type_string(&typ.to_string()); quote!{ #scrate::storage::generator::StorageFunctionType::Plain( @@ -591,7 +585,7 @@ fn store_functions_to_metadata ( ) } } else { - let kty = stk.expect("is not simple; qed"); + let kty = type_infos.map_key.expect("is not simple; qed"); let kty = clean_type_string("e!(#kty).to_string()); let styp = clean_type_string(&typ.to_string()); quote!{ @@ -601,13 +595,13 @@ fn store_functions_to_metadata ( } } }; - let modifier = if !is_option { + let modifier = if type_infos.is_option { quote!{ - #scrate::storage::generator::StorageFunctionModifier::Default + #scrate::storage::generator::StorageFunctionModifier::Optional } } else { quote!{ - #scrate::storage::generator::StorageFunctionModifier::Optional + #scrate::storage::generator::StorageFunctionModifier::Default } }; let default = default_value.inner.get(0).as_ref().map(|d| &d.expr) @@ -647,10 +641,10 @@ fn store_functions_to_metadata ( let def_get = quote! { pub struct #struct_name<#traitinstance>(pub #scrate::rstd::marker::PhantomData<#traitinstance>); #[cfg(feature = "std")] - static #cache_name: #scrate::once_cell::sync::OnceCell> = #scrate::once_cell::sync::OnceCell::INIT; + static #cache_name: #scrate::once_cell::sync::OnceCell<#scrate::rstd::vec::Vec> = #scrate::once_cell::sync::OnceCell::INIT; #[cfg(feature = "std")] impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> { - fn default_byte(&self) -> Vec { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { use #scrate::codec::Encode; #cache_name.get_or_init(|| { let def_val: #gettype = #default; @@ -660,7 +654,7 @@ fn store_functions_to_metadata ( } #[cfg(not(feature = "std"))] impl<#traitinstance: #traittype> #scrate::storage::generator::DefaultByte for #struct_name<#traitinstance> { - fn default_byte(&self) -> Vec { + fn default_byte(&self) -> #scrate::rstd::vec::Vec { use #scrate::codec::Encode; let def_val: #gettype = #default; <#gettype as Encode>::encode(&def_val) @@ -677,3 +671,29 @@ fn store_functions_to_metadata ( } }) } + + +struct DeclStorageTypeInfos<'a> { + pub is_simple: bool, + pub full_type: &'a syn::Type, + pub is_option: bool, + pub typ: TokenStream2, + pub map_key: Option<&'a syn::Type>, +} + +fn get_type_infos(storage_type: &DeclStorageType) -> DeclStorageTypeInfos { + let (is_simple, extracted_type, map_key, full_type) = match storage_type { + DeclStorageType::Simple(ref st) => (true, ext::extract_type_option(st), None, st), + DeclStorageType::Map(ref map) => (false, ext::extract_type_option(&map.value), Some(&map.key), &map.value), + }; + let is_option = extracted_type.is_some(); + let typ = extracted_type.unwrap_or(quote!( #full_type )); + DeclStorageTypeInfos { + is_simple, + full_type, + is_option, + typ, + map_key, + } +} + diff --git a/srml/support/src/storage/generator.rs b/srml/support/src/storage/generator.rs index e28dbda89e24d..7cf5e28dedf9a 100644 --- a/srml/support/src/storage/generator.rs +++ b/srml/support/src/storage/generator.rs @@ -946,3 +946,29 @@ mod test2 { type BlockNumber = u32; } } + +#[cfg(test)] +#[allow(dead_code)] +mod test3 { + pub trait Trait { + type Origin; + type BlockNumber; + } + decl_module! { + pub struct Module for enum Call where origin: T::Origin {} + } + decl_storage! { + trait Store for Module as Test { + Foo get(foo) config(initial_foo): u32; + } + } + + type PairOf = (T, T); + + struct TraitImpl {} + + impl Trait for TraitImpl { + type Origin = u32; + type BlockNumber = u32; + } +}