Skip to content

Commit 7d49f74

Browse files
authored
Update to frame-metadata 22 (#8327)
The main change in [the proposed `frame-metadata@22`](paritytech/frame-metadata#101) is that the deprecation information was tidied to remove some possible but confusing states, which simplifies making use of it in client code. One change made in the process is that **the ability to deprecate the entire of the Call/Error/Event enum was removed**. In other words, prior to this change a pallet author could do either of these: ```rust /// Deprecate the entire enum (but this is ignored if any variants are deprecated): #[deprecated(note = "This is deprecated")] #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event<T: Config<I>, I: 'static = ()> { /// An account was created with some free balance. Endowed { account: T::AccountId, free_balance: T::Balance }, /// An account was removed whose balance was non-zero but below ExistentialDeposit, /// resulting in an outright loss. DustLost { account: T::AccountId, amount: T::Balance }, } /// Deprecate individual variants: #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event<T: Config<I>, I: 'static = ()> { /// An account was created with some free balance. #[deprecated(note = "This is deprecated")] Endowed { account: T::AccountId, free_balance: T::Balance }, /// An account was removed whose balance was non-zero but below ExistentialDeposit, /// resulting in an outright loss. #[deprecated(note = "This is deprecated too")] DustLost { account: T::AccountId, amount: T::Balance }, } ``` After this PR, **a pallet author can still deprecate individual variants, but not the entire enum**. Some reasoning behind this change: 1. It's unlikely that the entire of these enums would ever be entirely deprecated. 2. In the case of calls, there is no obvious place to put such a warning anyway. 3. Sticking to just deprecating variants makes it a little simpler for client code; fewer cases to handle during codegen or whatever. 4. Avoid a confusing state where `#[deprecation]` can be put on the entire enum _and_ some variants, which leads to the enum-wide deprecation warning being ignored. See paritytech/frame-metadata#100 for some more context on the changes. # Notes This PR currently pulls `frame-metadata` via a github branch, for testing purposes. If we are happy here, I'll merge that PR, release `frame-metadata` and remove the github dependency before we merge this.
1 parent ce69f0d commit 7d49f74

28 files changed

Lines changed: 349 additions & 233 deletions

File tree

Cargo.lock

Lines changed: 9 additions & 9 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ frame-benchmarking-pallet-pov = { default-features = false, path = "substrate/fr
800800
frame-election-provider-solution-type = { path = "substrate/frame/election-provider-support/solution-type", default-features = false }
801801
frame-election-provider-support = { path = "substrate/frame/election-provider-support", default-features = false }
802802
frame-executive = { path = "substrate/frame/executive", default-features = false }
803-
frame-metadata = { version = "21.0.0", default-features = false }
803+
frame-metadata = { version = "22.0.0", default-features = false }
804804
frame-metadata-hash-extension = { path = "substrate/frame/metadata-hash-extension", default-features = false }
805805
frame-support = { path = "substrate/frame/support", default-features = false }
806806
frame-support-procedural = { path = "substrate/frame/support/procedural", default-features = false }

prdoc/pr_8327.prdoc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
title: Update to the latest unstable V16 metadata.
2+
3+
doc:
4+
- audience: Runtime Dev
5+
description: |
6+
The frame-metadata version is bumped to v22 to bring in the latest unstable V16 metadata format. Notably,
7+
deprecation information has changed slightly, and deprecation notices on the outer Event/Error enums
8+
are no longer supported (but each variant can still be marked as deprecated).
9+
10+
11+
crates:
12+
- name: sp-metadata-ir
13+
bump: major

substrate/frame/examples/view-functions/src/tests.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ use scale_info::meta_type;
2828
use frame_support::{derive_impl, pallet_prelude::PalletInfoAccess, view_functions::ViewFunction};
2929
use sp_io::hashing::twox_128;
3030
use sp_metadata_ir::{
31-
DeprecationStatusIR, PalletViewFunctionMetadataIR, PalletViewFunctionParamMetadataIR,
31+
ItemDeprecationInfoIR, PalletViewFunctionMetadataIR, PalletViewFunctionParamMetadataIR,
3232
};
3333
use sp_runtime::testing::TestXt;
3434

@@ -144,7 +144,7 @@ fn metadata_ir_definitions() {
144144
inputs: vec![],
145145
output: meta_type::<Option<u32>>(),
146146
docs: vec![" Query value with no input args."],
147-
deprecation_info: DeprecationStatusIR::NotDeprecated,
147+
deprecation_info: ItemDeprecationInfoIR::NotDeprecated,
148148
},
149149
PalletViewFunctionMetadataIR {
150150
name: "get_value_with_arg",
@@ -155,7 +155,7 @@ fn metadata_ir_definitions() {
155155
},],
156156
output: meta_type::<Option<u32>>(),
157157
docs: vec![" Query value with input args."],
158-
deprecation_info: DeprecationStatusIR::NotDeprecated,
158+
deprecation_info: ItemDeprecationInfoIR::NotDeprecated,
159159
},
160160
]
161161
);

substrate/frame/support/procedural/src/deprecation.rs

Lines changed: 66 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,28 @@ fn deprecation_msg_formatter(msg: &str) -> String {
3636
)
3737
}
3838

39-
fn parse_deprecated_meta(crate_: &TokenStream, attr: &syn::Attribute) -> Result<TokenStream> {
39+
// Should we generate a #crate_::__private::metadata_ir::ItemDeprecationInfoIR
40+
// or a #crate_::__private::metadata_ir::VariantDeprecationInfoIR? In other words,
41+
// are we targeting variant deprecation information, or generic item deprecation
42+
// information.
43+
#[derive(Copy, Clone, PartialEq)]
44+
enum DeprecationTarget {
45+
Item,
46+
Variant,
47+
}
48+
49+
fn parse_deprecated_meta(
50+
crate_: &TokenStream,
51+
attr: &syn::Attribute,
52+
target: DeprecationTarget,
53+
) -> Result<TokenStream> {
54+
let target = match target {
55+
DeprecationTarget::Item =>
56+
quote! { #crate_::__private::metadata_ir::ItemDeprecationInfoIR },
57+
DeprecationTarget::Variant =>
58+
quote! { #crate_::__private::metadata_ir::VariantDeprecationInfoIR },
59+
};
60+
4061
match &attr.meta {
4162
Meta::List(meta_list) => {
4263
let parsed = meta_list
@@ -60,14 +81,19 @@ fn parse_deprecated_meta(crate_: &TokenStream, attr: &syn::Attribute) -> Result<
6081
Ok::<(Option<&syn::Lit>, Option<&syn::Lit>), Error>(acc)
6182
})?;
6283
note.map_or_else(
63-
|| Err(Error::new(attr.span(), deprecation_msg_formatter("Invalid deprecation attribute: missing `note`"))),
84+
|| {
85+
Err(Error::new(
86+
attr.span(),
87+
deprecation_msg_formatter("Invalid deprecation attribute: missing `note`"),
88+
))
89+
},
6490
|note| {
6591
let since = if let Some(str) = since {
6692
quote! { Some(#str) }
6793
} else {
6894
quote! { None }
6995
};
70-
let doc = quote! { #crate_::__private::metadata_ir::DeprecationStatusIR::Deprecated { note: #note, since: #since }};
96+
let doc = quote! { #target::Deprecated { note: #note, since: #since }};
7197
Ok(doc)
7298
},
7399
)
@@ -77,14 +103,12 @@ fn parse_deprecated_meta(crate_: &TokenStream, attr: &syn::Attribute) -> Result<
77103
..
78104
}) => {
79105
// #[deprecated = "lit"]
80-
let doc = quote! { #crate_::__private::metadata_ir::DeprecationStatusIR::Deprecated { note: #lit, since: None } };
106+
let doc = quote! { #target::Deprecated { note: #lit, since: None } };
81107
Ok(doc)
82108
},
83109
Meta::Path(_) => {
84110
// #[deprecated]
85-
Ok(
86-
quote! { #crate_::__private::metadata_ir::DeprecationStatusIR::DeprecatedWithoutNote },
87-
)
111+
Ok(quote! { #target::DeprecatedWithoutNote })
88112
},
89113
_ => Err(Error::new(
90114
attr.span(),
@@ -93,50 +117,60 @@ fn parse_deprecated_meta(crate_: &TokenStream, attr: &syn::Attribute) -> Result<
93117
}
94118
}
95119

120+
fn find_deprecation_attr(attrs: &[syn::Attribute]) -> Option<&syn::Attribute> {
121+
attrs.iter().find(|a| a.path().is_ident("deprecated"))
122+
}
123+
124+
fn parse_deprecation(
125+
path: &TokenStream,
126+
attrs: &[syn::Attribute],
127+
target: DeprecationTarget,
128+
) -> Result<Option<TokenStream>> {
129+
find_deprecation_attr(attrs)
130+
.map(|a| parse_deprecated_meta(path, a, target))
131+
.transpose()
132+
}
133+
96134
/// collects deprecation attribute if its present.
97135
pub fn get_deprecation(path: &TokenStream, attrs: &[syn::Attribute]) -> Result<TokenStream> {
98-
parse_deprecation(path, attrs).map(|item| {
136+
parse_deprecation(path, attrs, DeprecationTarget::Item).map(|item| {
99137
item.unwrap_or_else(|| {
100-
quote! {#path::__private::metadata_ir::DeprecationStatusIR::NotDeprecated}
138+
quote! {#path::__private::metadata_ir::ItemDeprecationInfoIR::NotDeprecated}
101139
})
102140
})
103141
}
104142

105-
fn parse_deprecation(path: &TokenStream, attrs: &[syn::Attribute]) -> Result<Option<TokenStream>> {
106-
attrs
107-
.iter()
108-
.find(|a| a.path().is_ident("deprecated"))
109-
.map(|a| parse_deprecated_meta(path, a))
110-
.transpose()
143+
/// Call this on enum attributes to return an error if the #[deprecation] attribute is found.
144+
pub fn prevent_deprecation_attr_on_outer_enum(parent_attrs: &[syn::Attribute]) -> Result<()> {
145+
if let Some(attr) = find_deprecation_attr(parent_attrs) {
146+
return Err(Error::new(
147+
attr.span(),
148+
"The `#[deprecated]` attribute should be applied to individual variants, not the enum as a whole.",
149+
));
150+
}
151+
Ok(())
111152
}
112153

113154
/// collects deprecation attribute if its present for enum-like types
114155
pub fn get_deprecation_enum<'a>(
115156
path: &TokenStream,
116-
parent_attrs: &[syn::Attribute],
117157
children_attrs: impl Iterator<Item = (u8, &'a [syn::Attribute])>,
118158
) -> Result<TokenStream> {
119-
let parent_deprecation = parse_deprecation(path, parent_attrs)?;
120-
121159
let children = children_attrs
122160
.filter_map(|(key, attributes)| {
123-
let key = quote::quote! { #path::__private::codec::Compact(#key as u8) };
124-
let deprecation_status = parse_deprecation(path, attributes).transpose();
161+
let deprecation_status =
162+
parse_deprecation(path, attributes, DeprecationTarget::Variant).transpose();
125163
deprecation_status.map(|item| item.map(|item| quote::quote! { (#key, #item) }))
126164
})
127165
.collect::<Result<Vec<TokenStream>>>()?;
128-
match (parent_deprecation, children.as_slice()) {
129-
(None, []) =>
130-
Ok(quote::quote! { #path::__private::metadata_ir::DeprecationInfoIR::NotDeprecated }),
131-
(None, _) => {
132-
let children = quote::quote! { #path::__private::scale_info::prelude::collections::BTreeMap::from([#( #children),*]) };
133-
Ok(
134-
quote::quote! { #path::__private::metadata_ir::DeprecationInfoIR::VariantsDeprecated(#children) },
135-
)
136-
},
137-
(Some(depr), _) => Ok(
138-
quote::quote! { #path::__private::metadata_ir::DeprecationInfoIR::ItemDeprecated(#depr) },
139-
),
166+
167+
if children.is_empty() {
168+
Ok(
169+
quote::quote! { #path::__private::metadata_ir::EnumDeprecationInfoIR::nothing_deprecated() },
170+
)
171+
} else {
172+
let children = quote::quote! { #path::__private::scale_info::prelude::collections::BTreeMap::from([#( #children),*]) };
173+
Ok(quote::quote! { #path::__private::metadata_ir::EnumDeprecationInfoIR(#children) })
140174
}
141175
}
142176

substrate/frame/support/procedural/src/pallet/expand/call.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -265,7 +265,6 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
265265

266266
let deprecation = match crate::deprecation::get_deprecation_enum(
267267
&quote::quote! {#frame_support},
268-
def.call.as_ref().map(|call| call.attrs.as_ref()).unwrap_or(&[]),
269268
methods.iter().map(|item| (item.call_index as u8, item.attrs.as_ref())),
270269
) {
271270
Ok(deprecation) => deprecation,

substrate/frame/support/procedural/src/pallet/expand/error.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,6 @@ pub fn expand_error(def: &mut Def) -> proc_macro2::TokenStream {
106106

107107
let deprecation = match crate::deprecation::get_deprecation_enum(
108108
&quote::quote! {#frame_support},
109-
&error.attrs,
110109
error_item.variants.iter().enumerate().map(|(index, item)| {
111110
let index = crate::deprecation::variant_index_for_deprecation(index as u8, item);
112111

substrate/frame/support/procedural/src/pallet/expand/event.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,6 @@ pub fn expand_event(def: &mut Def) -> proc_macro2::TokenStream {
9898

9999
let deprecation = match crate::deprecation::get_deprecation_enum(
100100
&quote::quote! {#frame_support},
101-
&event.attrs,
102101
event_item.variants.iter().enumerate().map(|(index, item)| {
103102
let index = crate::deprecation::variant_index_for_deprecation(index as u8, item);
104103

substrate/frame/support/procedural/src/pallet/expand/pallet_struct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ pub fn expand_pallet_struct(def: &mut Def) -> proc_macro2::TokenStream {
300300
impl<#type_use_gen> #pallet_ident<#type_use_gen> {
301301
#[allow(dead_code)]
302302
#[doc(hidden)]
303-
pub fn deprecation_info() -> #frame_support::__private::metadata_ir::DeprecationStatusIR {
303+
pub fn deprecation_info() -> #frame_support::__private::metadata_ir::ItemDeprecationInfoIR {
304304
#deprecation_status
305305
}
306306
}

substrate/frame/support/procedural/src/pallet/parse/call.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ pub struct CallDef {
5151
pub docs: Vec<syn::Expr>,
5252
/// The optional `weight` attribute on the `pallet::call`.
5353
pub inherited_call_weight: Option<InheritedCallWeightAttr>,
54-
/// attributes
55-
pub attrs: Vec<syn::Attribute>,
5654
}
5755

5856
/// The weight of a call.
@@ -220,6 +218,9 @@ impl CallDef {
220218
} else {
221219
return Err(syn::Error::new(item.span(), "Invalid pallet::call, expected item impl"));
222220
};
221+
222+
crate::deprecation::prevent_deprecation_attr_on_outer_enum(&item_impl.attrs)?;
223+
223224
let instances = vec![
224225
helper::check_impl_gen(&item_impl.generics, item_impl.impl_token.span())?,
225226
helper::check_pallet_struct_usage(&item_impl.self_ty)?,
@@ -461,7 +462,6 @@ impl CallDef {
461462
where_clause: item_impl.generics.where_clause.clone(),
462463
docs: get_doc_literals(&item_impl.attrs),
463464
inherited_call_weight,
464-
attrs: item_impl.attrs.clone(),
465465
})
466466
}
467467
}

0 commit comments

Comments
 (0)