Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lang: Remove 3 lifetime definitions from Context #3340

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions lang/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,22 @@ use std::fmt;
/// Ok(())
/// }
/// ```
pub struct Context<'a, 'b, 'c, 'info, T: Bumps> {
pub struct Context<'info, T: 'info + Bumps> {
/// Currently executing program id.
pub program_id: &'a Pubkey,
pub program_id: &'info Pubkey,
/// Deserialized accounts.
pub accounts: &'b mut T,
pub accounts: &'info mut T,
/// Remaining accounts given but not deserialized or validated.
/// Be very careful when using this directly.
pub remaining_accounts: &'c [AccountInfo<'info>],
pub remaining_accounts: &'info [AccountInfo<'info>],
/// Bump seeds found during constraint validation. This is provided as a
/// convenience so that handlers don't have to recalculate bump seeds or
/// pass them in as arguments.
/// Type is the bumps struct generated by #[derive(Accounts)]
pub bumps: T::Bumps,
}

impl<'a, 'b, 'c, 'info, T> fmt::Debug for Context<'a, 'b, 'c, 'info, T>
impl<'info, T> fmt::Debug for Context<'info, T>
where
T: fmt::Debug + Bumps,
{
Expand All @@ -50,14 +50,14 @@ where
}
}

impl<'a, 'b, 'c, 'info, T> Context<'a, 'b, 'c, 'info, T>
impl<'info, T> Context<'info, T>
where
T: Bumps + Accounts<'info, T::Bumps>,
T: 'info + Bumps + Accounts<'info, T::Bumps>,
{
pub fn new(
program_id: &'a Pubkey,
accounts: &'b mut T,
remaining_accounts: &'c [AccountInfo<'info>],
program_id: &'info Pubkey,
accounts: &'info mut T,
remaining_accounts: &'info [AccountInfo<'info>],
bumps: T::Bumps,
) -> Self {
Self {
Expand Down
4 changes: 2 additions & 2 deletions lang/syn/src/codegen/program/dispatch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,9 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
/// If no match is found, the fallback function is executed if it exists, or an error is
/// returned if it doesn't exist.
fn dispatch<'info>(
program_id: &Pubkey,
program_id: &'info Pubkey,
accounts: &'info [AccountInfo<'info>],
data: &[u8],
data: &'info [u8],
) -> anchor_lang::Result<()> {
#(#global_ixs)*

Expand Down
12 changes: 10 additions & 2 deletions lang/syn/src/codegen/program/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,22 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
///
/// The `entry` function here, defines the standard entry to a Solana
/// program, where execution begins.
pub fn entry<'info>(program_id: &Pubkey, accounts: &'info [AccountInfo<'info>], data: &[u8]) -> anchor_lang::solana_program::entrypoint::ProgramResult {
pub fn entry<'info>(
program_id: &'info Pubkey,
accounts: &'info [AccountInfo<'info>],
data: &'info [u8]
) -> anchor_lang::solana_program::entrypoint::ProgramResult {
try_entry(program_id, accounts, data).map_err(|e| {
e.log();
e.into()
})
}

fn try_entry<'info>(program_id: &Pubkey, accounts: &'info [AccountInfo<'info>], data: &[u8]) -> anchor_lang::Result<()> {
fn try_entry<'info>(
program_id: &'info Pubkey,
accounts: &'info [AccountInfo<'info>],
data: &'info [u8]
) -> anchor_lang::Result<()> {
#[cfg(feature = "anchor-debug")]
{
msg!("anchor-debug is active");
Expand Down
30 changes: 22 additions & 8 deletions lang/syn/src/codegen/program/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let ix_arg_names: Vec<&syn::Ident> = ix.args.iter().map(|arg| &arg.name).collect();
let ix_name = generate_ix_variant_name(ix.raw_method.sig.ident.to_string());
let ix_method_name = &ix.raw_method.sig.ident;
let anchor = &ix.anchor_ident;
let accounts_struct_name = &ix.anchor_ident;
let variant_arm = generate_ix_variant(ix.raw_method.sig.ident.to_string(), &ix.args);
let ix_name_log = format!("Instruction: {ix_name}");
let ret_type = &ix.returns.ty.to_token_stream();
Expand All @@ -117,9 +117,9 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
#(#cfgs)*
#[inline(never)]
pub fn #ix_method_name<'info>(
__program_id: &Pubkey,
__accounts: &'info[AccountInfo<'info>],
__ix_data: &[u8],
__program_id: &'info Pubkey,
__accounts: &'info [AccountInfo<'info>],
__ix_data: &'info [u8],
) -> anchor_lang::Result<()> {
#[cfg(not(feature = "no-log-ix-name"))]
anchor_lang::prelude::msg!(#ix_name_log);
Expand All @@ -130,13 +130,13 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let instruction::#variant_arm = ix;

// Bump collector.
let mut __bumps = <#anchor as anchor_lang::Bumps>::Bumps::default();
let mut __bumps = <#accounts_struct_name as anchor_lang::Bumps>::Bumps::default();

let mut __reallocs = std::collections::BTreeSet::new();

// Deserialize accounts.
let mut __remaining_accounts: &[AccountInfo] = __accounts;
let mut __accounts = #anchor::try_accounts(
let mut __remaining_accounts = __accounts;
let mut __accounts = #accounts_struct_name::try_accounts(
__program_id,
&mut __remaining_accounts,
__ix_data,
Expand All @@ -148,7 +148,21 @@ pub fn generate(program: &Program) -> proc_macro2::TokenStream {
let result = #program_name::#ix_method_name(
anchor_lang::context::Context::new(
__program_id,
&mut __accounts,
// SAFETY: The transmute shortens the inner `AccountInfo` lifetimes to
// match the lifetimes of other arguments. All references are going to
// be valid at least for the duration of the user-defined instruction
// handlers.
//
// This is done to avoid having to define multiple lifetimes for the
// `Context` struct, which requies Anchor users to do the same in
// various cases (e.g. remaining accounts usage), resulting in a poor
// developer experience.
unsafe {
::core::mem::transmute::<
&mut #accounts_struct_name<'info>,
&mut #accounts_struct_name<'_>
>(&mut __accounts)
},
__remaining_accounts,
__bumps,
),
Expand Down
4 changes: 1 addition & 3 deletions tests/misc/programs/remaining-accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ pub mod remaining_accounts {
Ok(())
}

pub fn test_remaining_accounts<'c: 'info, 'info>(
ctx: Context<'_, '_, 'c, 'info, TestRemainingAccounts>,
) -> Result<()> {
pub fn test_remaining_accounts(ctx: Context<TestRemainingAccounts>) -> Result<()> {
let remaining_accounts_iter = &mut ctx.remaining_accounts.iter();

let token_account =
Expand Down
Loading