diff --git a/substrate/frame/support/procedural/src/storage/genesis_config/builder_def.rs b/substrate/frame/support/procedural/src/storage/genesis_config/builder_def.rs index fbab681949..78c659d466 100644 --- a/substrate/frame/support/procedural/src/storage/genesis_config/builder_def.rs +++ b/substrate/frame/support/procedural/src/storage/genesis_config/builder_def.rs @@ -44,32 +44,55 @@ impl BuilderDef { let storage_trait = &line.storage_trait; let value_type = &line.value_type; - // Contains the data to inset at genesis either from build or config. + // Defines the data variable to use for insert at genesis either from build or config. let mut data = None; if let Some(builder) = &line.build { is_generic |= ext::expr_contains_ident(&builder, &def.module_runtime_generic); is_generic |= line.is_generic; - data = Some(quote_spanned!(builder.span() => &(#builder)(self))); + data = Some(match &line.storage_type { + StorageLineTypeDef::Simple(_) if line.is_option => + quote_spanned!(builder.span() => + let data = (#builder)(self); + let data = Option::as_ref(&data); + ), + _ => quote_spanned!(builder.span() => let data = &(#builder)(self); ), + }); } else if let Some(config) = &line.config { is_generic |= line.is_generic; - data = Some(quote!(&self.#config;)); + data = Some(match &line.storage_type { + StorageLineTypeDef::Simple(_) if line.is_option => + quote!( let data = Some(&self.#config); ), + _ => quote!( let data = &self.#config; ), + }); }; if let Some(data) = data { blocks.push(match &line.storage_type { - StorageLineTypeDef::Simple(_) => { + StorageLineTypeDef::Simple(_) if line.is_option => { quote!{{ - let v: &#value_type = #data; + #data + let v: Option<&#value_type>= data; + if let Some(v) = v { + <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); + } + }} + }, + StorageLineTypeDef::Simple(_) if !line.is_option => { + quote!{{ + #data + let v: &#value_type = data; <#storage_struct as #scrate::#storage_trait>::put::<&#value_type>(v); }} }, + StorageLineTypeDef::Simple(_) => unreachable!(), StorageLineTypeDef::Map(map) | StorageLineTypeDef::LinkedMap(map) => { let key = &map.key; quote!{{ - let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = #data; + #data + let data: &#scrate::rstd::vec::Vec<(#key, #value_type)> = data; data.iter().for_each(|(k, v)| { <#storage_struct as #scrate::#storage_trait>::insert::< &#key, &#value_type @@ -81,7 +104,8 @@ impl BuilderDef { let key1 = &map.key1; let key2 = &map.key2; quote!{{ - let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = #data; + #data + let data: &#scrate::rstd::vec::Vec<(#key1, #key2, #value_type)> = data; data.iter().for_each(|(k1, k2, v)| { <#storage_struct as #scrate::#storage_trait>::insert::< &#key1, &#key2, &#value_type diff --git a/substrate/frame/support/test/tests/decl_storage.rs b/substrate/frame/support/test/tests/decl_storage.rs index cdd99275a6..231dbdbdac 100644 --- a/substrate/frame/support/test/tests/decl_storage.rs +++ b/substrate/frame/support/test/tests/decl_storage.rs @@ -19,6 +19,7 @@ #[allow(dead_code)] mod tests { use support::metadata::*; + use runtime_io::TestExternalities; use std::marker::PhantomData; use codec::{Encode, Decode, EncodeLike}; @@ -44,7 +45,7 @@ mod tests { // getters: pub / $default // we need at least one type which uses T, otherwise GenesisConfig will complain. GETU32 get(fn u32_getter): T::Origin; - pub PUBGETU32 get(fn pub_u32_getter) build(|config: &GenesisConfig| config.u32_getter_with_config): u32; + pub PUBGETU32 get(fn pub_u32_getter): u32; GETU32WITHCONFIG get(fn u32_getter_with_config) config(): u32; pub PUBGETU32WITHCONFIG get(fn pub_u32_getter_with_config) config(): u32; GETU32MYDEF get(fn u32_getter_mydef): Option; @@ -53,6 +54,10 @@ mod tests { pub PUBGETU32WITHCONFIGMYDEF get(fn pub_u32_getter_with_config_mydef) config(): u32 = 1; PUBGETU32WITHCONFIGMYDEFOPT get(fn pub_u32_getter_with_config_mydef_opt) config(): Option; + GetU32WithBuilder get(fn u32_with_builder) build(|_| 1): u32; + GetOptU32WithBuilderSome get(fn opt_u32_with_builder_some) build(|_| Some(1)): Option; + GetOptU32WithBuilderNone get(fn opt_u32_with_builder_none) build(|_| None): Option; + // map non-getters: pub / $default MAPU32 : map u32 => Option; pub PUBMAPU32 : map u32 => Option; @@ -209,7 +214,33 @@ mod tests { ), documentation: DecodeDifferent::Encode(&[]), }, - + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetU32WithBuilder"), + modifier: StorageEntryModifier::Default, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetU32WithBuilder(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetOptU32WithBuilderSome"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderSome(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, + StorageEntryMetadata { + name: DecodeDifferent::Encode("GetOptU32WithBuilderNone"), + modifier: StorageEntryModifier::Optional, + ty: StorageEntryType::Plain(DecodeDifferent::Encode("u32")), + default: DecodeDifferent::Encode( + DefaultByteGetter(&__GetByteStructGetOptU32WithBuilderNone(PhantomData::)) + ), + documentation: DecodeDifferent::Encode(&[]), + }, StorageEntryMetadata { name: DecodeDifferent::Encode("MAPU32"), modifier: StorageEntryModifier::Optional, @@ -412,7 +443,7 @@ mod tests { #[test] fn store_metadata() { let metadata = Module::::storage_metadata(); - assert_eq!(EXPECTED_METADATA, metadata); + pretty_assertions::assert_eq!(EXPECTED_METADATA, metadata); } #[test] @@ -427,6 +458,16 @@ mod tests { assert_eq!(config.pub_u32_getter_with_config_mydef_opt, 0u32); } + #[test] + fn check_builder_config() { + let config = GenesisConfig::default(); + let storage = config.build_storage().unwrap(); + TestExternalities::from(storage).execute_with(|| { + assert_eq!(Module::::u32_with_builder(), 1); + assert_eq!(Module::::opt_u32_with_builder_some(), Some(1)); + assert_eq!(Module::::opt_u32_with_builder_none(), None); + }) + } } #[cfg(test)]