diff --git a/CHANGELOG.md b/CHANGELOG.md index addcdcb934..bcdd8c3e7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,7 @@ The minor version will be incremented upon a breaking change and the patch versi - idl: Fix using constant identifiers as generic arguments ([#3522](https://github.com/coral-xyz/anchor/pull/3522)). - client: Remove `std::process::exit` usage ([#3544](https://github.com/coral-xyz/anchor/pull/3544)). - idl: Fix using `Pubkey` constants with `seeds::program` ([#3559](https://github.com/coral-xyz/anchor/pull/3559)). +- lang: Fix instructions with no accounts causing compilation errors when using `declare_program!` ([#3567](https://github.com/coral-xyz/anchor/pull/3567)). ### Breaking diff --git a/lang/attribute/program/src/declare_program/mods/cpi.rs b/lang/attribute/program/src/declare_program/mods/cpi.rs index 05e1016a27..d5dfb4eb8a 100644 --- a/lang/attribute/program/src/declare_program/mods/cpi.rs +++ b/lang/attribute/program/src/declare_program/mods/cpi.rs @@ -26,6 +26,12 @@ fn gen_cpi_instructions(idl: &Idl) -> proc_macro2::TokenStream { let method_name = format_ident!("{}", ix.name); let accounts_ident = format_ident!("{}", ix.name.to_camel_case()); + let accounts_generic = if ix.accounts.is_empty() { + quote!() + } else { + quote!(<'info>) + }; + let args = ix.args.iter().map(|arg| { let name = format_ident!("{}", arg.name); let ty = convert_idl_type_to_syn_type(&arg.ty); @@ -61,7 +67,7 @@ fn gen_cpi_instructions(idl: &Idl) -> proc_macro2::TokenStream { quote! { pub fn #method_name<'a, 'b, 'c, 'info>( - ctx: anchor_lang::context::CpiContext<'a, 'b, 'c, 'info, accounts::#accounts_ident<'info>>, + ctx: anchor_lang::context::CpiContext<'a, 'b, 'c, 'info, accounts::#accounts_ident #accounts_generic>, #(#args),* ) -> #ret_type { let ix = { diff --git a/tests/declare-program/idls/external.json b/tests/declare-program/idls/external.json index 3bb4e4b641..c709fcfdfa 100644 --- a/tests/declare-program/idls/external.json +++ b/tests/declare-program/idls/external.json @@ -73,6 +73,21 @@ } ] }, + { + "name": "test_compilation_no_accounts", + "discriminator": [ + 194, + 91, + 205, + 217, + 51, + 10, + 247, + 201 + ], + "accounts": [], + "args": [] + }, { "name": "test_compilation_return_type", "discriminator": [ diff --git a/tests/declare-program/programs/external/src/lib.rs b/tests/declare-program/programs/external/src/lib.rs index 86a08ae0b8..f7a538a049 100644 --- a/tests/declare-program/programs/external/src/lib.rs +++ b/tests/declare-program/programs/external/src/lib.rs @@ -45,6 +45,11 @@ pub mod external { pub fn test_compilation_return_type(_ctx: Context) -> Result { Ok(true) } + + // Compilation test for an instruction with no accounts + pub fn test_compilation_no_accounts(_ctx: Context) -> Result<()> { + Ok(()) + } } #[derive(Accounts)] @@ -52,6 +57,9 @@ pub struct TestCompilation<'info> { pub signer: Signer<'info>, } +#[derive(Accounts)] +pub struct TestCompilationNoAccounts {} + #[derive(Accounts)] pub struct Init<'info> { #[account(mut)]