Skip to content

Commit

Permalink
Fix feeless_if in pallet section (#6032)
Browse files Browse the repository at this point in the history
fixes #5981 

Could confirm the issue with the added tests:

```
test tests/split_ui/pass/split_call.rs [should pass] ... error
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error[E0423]: expected value, found attribute macro `origin`
  --> tests/split_ui/pass/split_call.rs:23:1
   |
23 | #[frame_support::pallet(dev_mode)]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a value
   |
   = note: this error originates in the attribute macro `frame_support::pallet` (in Nightly builds, run with -Z macro-backtrace for more info)
```

# Description

`origin` unexpectedly resolved to a macro, which is available at the
span of invocation. The solution here is to use the expansion as a
function instead of a call and pass in the desired values to avoid
ambiguities.
  • Loading branch information
eagr authored Oct 14, 2024
1 parent aca11dc commit 6f03f7a
Show file tree
Hide file tree
Showing 4 changed files with 118 additions and 7 deletions.
11 changes: 11 additions & 0 deletions prdoc/pr_6032.prdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
title: Fix `feeless_if` in pallet section

doc:
- audience: Runtime Dev
description: |
Fix compilation with `pallet::feeless_if` in a pallet section: a local binding unexpectely
resolved to a macro definition.

crates:
- name: frame-support-procedural
bump: patch
15 changes: 8 additions & 7 deletions substrate/frame/support/procedural/src/pallet/expand/call.rs
Original file line number Diff line number Diff line change
Expand Up @@ -253,13 +253,13 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
})
.collect::<Vec<_>>();

let feeless_check = methods.iter().map(|method| &method.feeless_check).collect::<Vec<_>>();
let feeless_check_result =
feeless_check.iter().zip(args_name.iter()).map(|(feeless_check, arg_name)| {
if let Some(feeless_check) = feeless_check {
quote::quote!(#feeless_check(origin, #( #arg_name, )*))
let feeless_checks = methods.iter().map(|method| &method.feeless_check).collect::<Vec<_>>();
let feeless_check =
feeless_checks.iter().zip(args_name.iter()).map(|(feeless_check, arg_name)| {
if let Some(check) = feeless_check {
quote::quote_spanned!(span => #check)
} else {
quote::quote!(false)
quote::quote_spanned!(span => |_origin, #( #arg_name, )*| { false })
}
});

Expand Down Expand Up @@ -393,7 +393,8 @@ pub fn expand_call(def: &mut Def) -> proc_macro2::TokenStream {
#(
#cfg_attrs
Self::#fn_name { #( #args_name_pattern_ref, )* } => {
#feeless_check_result
let feeless_check = #feeless_check;
feeless_check(origin, #( #args_name, )*)
},
)*
Self::__Ignore(_, _) => unreachable!("__Ignore cannot be used"),
Expand Down
63 changes: 63 additions & 0 deletions substrate/frame/support/test/tests/split_ui/pass/call/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use frame_support::pallet_macros::pallet_section;

#[pallet_section]
mod call {
#[pallet::call]
impl<T: Config> Pallet<T> {
#[pallet::call_index(0)]
pub fn noop0(origin: OriginFor<T>) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}

#[pallet::call_index(1)]
pub fn noop1(origin: OriginFor<T>, _x: u64) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}

#[pallet::call_index(2)]
pub fn noop2(origin: OriginFor<T>, _x: u64, _y: u64) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}

#[pallet::call_index(3)]
#[pallet::feeless_if(|_origin: &OriginFor<T>| -> bool { true })]
pub fn noop_feeless0(origin: OriginFor<T>) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}

#[pallet::call_index(4)]
#[pallet::feeless_if(|_origin: &OriginFor<T>, x: &u64| -> bool { *x == 1 })]
pub fn noop_feeless1(origin: OriginFor<T>, _x: u64) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}

#[pallet::call_index(5)]
#[pallet::feeless_if(|_origin: &OriginFor<T>, x: &u64, y: &u64| -> bool { *x == *y })]
pub fn noop_feeless2(origin: OriginFor<T>, _x: u64, _y: u64) -> DispatchResult {
ensure_signed(origin)?;
Ok(())
}
}
}
36 changes: 36 additions & 0 deletions substrate/frame/support/test/tests/split_ui/pass/split_call.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// This file is part of Substrate.

// Copyright (C) Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use frame_support::pallet_macros::import_section;

mod call;

#[import_section(call::call)]
#[frame_support::pallet(dev_mode)]
pub mod pallet {
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;

#[pallet::pallet]
pub struct Pallet<T>(_);

#[pallet::config]
pub trait Config: frame_system::Config {}
}

fn main() {
}

0 comments on commit 6f03f7a

Please sign in to comment.