4个版本

使用旧的Rust 2015

0.0.5 2018年10月31日
0.0.4 2017年10月23日
0.0.3 2017年3月2日
0.0.1 2017年2月22日

#20 in #hack

Download history 52/week @ 2023-10-19 63/week @ 2023-10-26 46/week @ 2023-11-02 64/week @ 2023-11-09 49/week @ 2023-11-16 68/week @ 2023-11-23 57/week @ 2023-11-30 53/week @ 2023-12-07 64/week @ 2023-12-14 61/week @ 2023-12-21 50/week @ 2023-12-28 51/week @ 2024-01-04 48/week @ 2024-01-11 56/week @ 2024-01-18 55/week @ 2024-01-25 50/week @ 2024-02-01

每月217次下载
用于 2 个crate

MIT/Apache

6KB
94

表达式位置的过程宏

github crates.io docs.rs build status


注意: 从Rust 1.45开始,此crate已被原生对#[proc_macro]在表达式位置的支持所取代。只有当您关心支持1.31到1.45之间的编译器时,才应考虑使用此crate。

自Rust 1.30以来,语言支持用户定义的类似函数的过程宏。然而,这些只能在项目位置调用,不能在语句或表达式中调用。

此crate实现了一种可以在语句或表达式位置调用的替代类型的过程宏。

此方法与任何Rust 1.31+版本兼容。

定义过程宏

定义过程宏需要两个crate。

实现crate

此crate必须只包含过程宏。私有辅助函数和私有模块是可以的,但不能有公共内容。

» 实现crate的示例

就像您会使用#[proc_macro]属性来定义原生支持的过程宏一样,使用proc-macro-hack的#[proc_macro_hack]属性来定义在表达式位置工作的过程宏。函数签名与普通类似函数的过程宏相同。

use proc_macro::TokenStream;
use proc_macro_hack::proc_macro_hack;
use quote::quote;
use syn::{parse_macro_input, Expr};

#[proc_macro_hack]
pub fn add_one(input: TokenStream) -> TokenStream {
    let expr = parse_macro_input!(input as Expr);
    TokenStream::from(quote! {
        1 + (#expr)
    })
}

声明crate

如果您需要,此crate可以包含其他公共内容,例如特质、函数或普通宏。

» 声明crate的示例

在声明crate中,需要从实现crate重新导出您的过程宏。重导出还携带了#[proc_macro_hack]属性。

use proc_macro_hack::proc_macro_hack;

/// Add one to an expression.
///
/// (Documentation goes here on the re-export, not in the other crate.)
#[proc_macro_hack]
pub use demo_hack_impl::add_one;

两个crate都依赖于 proc-macro-hack

[dependencies]
proc-macro-hack = "0.5"

此外,您的实现crate(而不是您的声明crate)是一个过程宏crate

[lib]
proc-macro = true

使用过程宏

您的crate的用户依赖于您的声明crate(而不是您的实现crate),然后像平常一样使用您的过程宏。

» 依赖crate的示例

use demo_hack::add_one;

fn main() {
    let two = 2;
    let nine = add_one!(two) + add_one!(2 + 3);
    println!("nine = {}", nine);
}

限制

  • 仅支持表达式位置的过程宏。模式位置的过程宏(#20)不受支持。

  • 默认情况下,不支持嵌套调用,即由 proc-macro-hack 宏调用生成的代码不能包含对该宏的递归调用,也不能调用其他任何 proc-macro-hack 宏。如果需要支持嵌套调用,请使用 proc-macro-nested

  • 默认情况下,卫生性(hygiene)结构使得扩展的代码不能引用除在宏输入中通过名称传递的局部变量以外的任何局部变量。如果您的宏必须引用在宏输入中未命名的 局部 变量,请在声明包中的重导出处使用 #[proc_macro_hack(fake_call_site)]大多数宏不需要这样做。

  • 对于足够新的支持在表达式位置上原生支持 proc 宏的编译器,proc-macro-hack 不会自动使用这种支持,因为两种实现之间的卫生性可能有所不同。要选择将您的宏编译为足够新的编译器上的本地 #[proc_macro],请在声明包中的重导出处使用 #[proc_macro_hack(only_hack_old_rustc)]


许可证

根据您的选择,许可协议为 Apache License, Version 2.0 或 MIT 许可证。
除非您明确声明,否则任何有意提交以包含在此 hack 中的贡献,根据 Apache-2.0 许可证定义,将按上述方式双重许可,不附加任何额外条款或条件。

依赖项

约 2MB
约 44K SLoC