* Fix hygiene issues in `declare_program!` and `declare_loader!` The `declare_program!` and `declare_loader!` macros both expand to new macro definitions (based on the `$name` argument). These 'inner' macros make use of the special `$crate` metavariable to access items in the crate where the 'inner' macros is defined. However, this only works due to a bug in rustc. When a macro is expanded, all `$crate` tokens in its output are 'marked' as being resolved in the defining crate of that macro. An inner macro (including the body of its arms) is 'just' another set of tokens that appears in the body of the outer macro, so any `$crate` identifiers used there are resolved relative to the 'outer' macro. For example, consider the following code: ```rust macro_rules! outer { () => { macro_rules! inner { () => { $crate::Foo } } } } ``` The path `$crate::Foo` will be resolved relative to the crate that defines `outer`, **not** the crate which defines `inner`. However, rustc currently loses this extra resolution information (referred to as 'hygiene' information) when a crate is serialized. In the above example, this means that the macro `inner` (which gets defined in whatever crate invokes `outer!`) will behave differently depending on which crate it is invoked from: When `inner` is invoked from the same crate in which it is defined, the hygiene information will still be available, which will cause `$crate::Foo` to be resolved in the crate which defines 'outer'. When `inner` is invoked from a different crate, it will be loaded from the metadata of the crate which defines 'inner'. Since the hygiene information is currently lost, rust will 'forget' that `$crate::Foo` is supposed to be resolved in the context of 'outer'. Instead, it will be resolved relative to the crate which defines 'inner', which can cause incorrect code to compile. This bug will soon be fixed in rust (see https://github.com/rust-lang/rust/pull/72121), which will break `declare_program!` and `declare_loader!`. Fortunately, it's possible to obtain the desired behavior (`$crate` resolving in the context of the 'inner' macro) by use of a procedural macro. This commit adds a `respan!` proc-macro to the `sdk/macro` crate. Using the newly-stabilized (on Nightly) `Span::resolved_at` method, the `$crate` identifier can be made to be resolved in the context of the proper crate. Since `Span::resolved_at` is only stable on the latest nightly, referencing it on an earlier version of Rust will cause a compilation error. This requires the `rustversion` crate to be used, which allows conditionally compiling code epending on the Rust compiler version in use. Since this method is already stabilized in the latest nightly, there will never be a situation where the hygiene bug is fixed (e.g. https://github.com/rust-lang/rust/pull/72121) is merged but we are unable to call `Span::resolved_at`. (cherry picked from commit05445c718e
) # Conflicts: # Cargo.lock # sdk/Cargo.toml * Replace FIXME with an issue link (cherry picked from commitb0cb2b0106
) * Update lock files (cherry picked from commit42f88484f4
) # Conflicts: # programs/bpf/Cargo.lock # programs/librapay/Cargo.lock # programs/move_loader/Cargo.lock * Split comment over multiple lines Due to https://github.com/rust-lang/rustfmt/issues/4325, leaving this as one line causes rustfmt to add extra indentation to the surrounding code. (cherry picked from commitfed69e96a9
) * Fix clippy lints (cherry picked from commite7387f60a7
) * Apply #![feature(proc_macro_hygiene)] when needed This allows the rust-bpf-builder toolchain to build the sdk (cherry picked from commit95490ff56e
) # Conflicts: # sdk/build.rs # sdk/src/lib.rs * Update Cargo.toml * Update lib.rs * Add rustc_version * lock file updates Co-authored-by: Aaron Hill <aa1ronham@gmail.com> Co-authored-by: Jack May <jack@solana.com> Co-authored-by: Michael Vines <mvines@gmail.com>
100 lines
2.5 KiB
Rust
100 lines
2.5 KiB
Rust
#![cfg_attr(RUSTC_NEEDS_PROC_MACRO_HYGIENE, feature(proc_macro_hygiene))]
|
|
|
|
// Allows macro expansion of `use ::solana_sdk::*` to work within this crate
|
|
extern crate self as solana_sdk;
|
|
|
|
pub mod account;
|
|
pub mod account_utils;
|
|
pub mod bpf_loader;
|
|
pub mod clock;
|
|
pub mod commitment_config;
|
|
pub mod decode_error;
|
|
pub mod entrypoint_native;
|
|
pub mod epoch_info;
|
|
pub mod epoch_schedule;
|
|
pub mod fee_calculator;
|
|
pub mod hash;
|
|
pub mod incinerator;
|
|
pub mod inflation;
|
|
pub mod instruction;
|
|
pub mod loader_instruction;
|
|
pub mod message;
|
|
pub mod move_loader;
|
|
pub mod native_loader;
|
|
pub mod native_token;
|
|
pub mod nonce;
|
|
pub mod packet;
|
|
pub mod poh_config;
|
|
pub mod program_utils;
|
|
pub mod pubkey;
|
|
pub mod rent;
|
|
pub mod rpc_port;
|
|
pub mod sanitize;
|
|
pub mod short_vec;
|
|
pub mod slot_hashes;
|
|
pub mod slot_history;
|
|
pub mod stake_history;
|
|
pub mod system_instruction;
|
|
pub mod system_program;
|
|
pub mod sysvar;
|
|
pub mod timing;
|
|
|
|
/// Convenience macro to declare a static public key and functions to interact with it
|
|
///
|
|
/// Input: a single literal base58 string representation of a program's id
|
|
///
|
|
/// # Example
|
|
///
|
|
/// ```
|
|
/// # // wrapper is used so that the macro invocation occurs in the item position
|
|
/// # // rather than in the statement position which isn't allowed.
|
|
/// use std::str::FromStr;
|
|
/// use solana_sdk::{declare_id, pubkey::Pubkey};
|
|
///
|
|
/// # mod item_wrapper {
|
|
/// # use solana_sdk::declare_id;
|
|
/// declare_id!("My11111111111111111111111111111111111111111");
|
|
/// # }
|
|
/// # use item_wrapper::id;
|
|
///
|
|
/// let my_id = Pubkey::from_str("My11111111111111111111111111111111111111111").unwrap();
|
|
/// assert_eq!(id(), my_id);
|
|
/// ```
|
|
pub use solana_sdk_macro::declare_id;
|
|
pub use solana_sdk_macro::pubkeys;
|
|
#[rustversion::since(1.46.0)]
|
|
pub use solana_sdk_macro::respan;
|
|
|
|
// On-chain program specific modules
|
|
pub mod account_info;
|
|
pub mod entrypoint;
|
|
pub mod log;
|
|
pub mod program;
|
|
pub mod program_error;
|
|
pub mod program_stubs;
|
|
|
|
// Modules not usable by on-chain programs
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod client;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod genesis_config;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod hard_forks;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod shred_version;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod signature;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod signers;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod system_transaction;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod transaction;
|
|
#[cfg(not(feature = "program"))]
|
|
pub mod transport;
|
|
|
|
#[macro_use]
|
|
extern crate serde_derive;
|
|
pub extern crate bs58;
|
|
extern crate log as logger;
|