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 日

#4#proc-macro-hack

Download history 35/week @ 2024-03-31 18/week @ 2024-04-07 18/week @ 2024-04-14 23/week @ 2024-04-21 22/week @ 2024-04-28 23/week @ 2024-05-05 19/week @ 2024-05-12 12/week @ 2024-05-19 29/week @ 2024-05-26 42/week @ 2024-06-02 33/week @ 2024-06-09 33/week @ 2024-06-16 36/week @ 2024-06-23 38/week @ 2024-06-30 33/week @ 2024-07-07 21/week @ 2024-07-14

133 每月下载量
proc-macro-hack 中使用

MIT/Apache

6KB
85

Procedural macros in expression position

github crates.io docs.rs build status


(Rust 1.45 之后,该包已被表达式位置的过程宏的原生支持所取代。如果需要在 1.31 到 1.45 之间的编译器中支持,则应考虑使用此包。)

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

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

此方法适用于任何 Rust 1.31+ 版本。

定义过程宏

需要两个包来定义过程宏。

实现包

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

» 实现包的示例

就像你会使用 #[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)
    })
}

声明包

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

» 声明包的示例

在声明包中,需要从实现包重新导出你的过程宏。重新导出还携带了 #[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;

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

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

此外,你的实现包(但不是你的声明包)是一个过程宏包

[lib]
proc-macro = true

使用过程宏

如果你使用你的包,你的包的用户将依赖于你的声明包(而不是你的实现包),那么他们将像通常一样使用你的过程宏。

» 使用下游包的示例

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

  • 默认情况下,卫生性结构使得展开后的代码不能引用除在宏输入中以名称传递的变量以外的本地变量。如果您的宏必须引用在宏输入中没有命名的本地变量,请在您的声明包中重导出时使用#[proc_macro_hack(fake_call_site)]。大多数宏不需要这样做。

  • 在足够新的编译器中,对于那些原生支持表达式位置的proc宏的编译器,由于两种实现之间的卫生性可能存在细微差别,proc-macro-hack不会自动使用这种支持。为了在足够新的编译器中将您的宏编译为原生的#[proc_macro],请在您的声明包中的重导出时使用#[proc_macro_hack(only_hack_old_rustc)]


许可证

根据您的选择,在Apache License, Version 2.0MIT许可证下获得许可。
除非您明确表示,否则您提交的任何旨在包含在本hack中的贡献,如Apache-2.0许可证中定义的,应如上双许可,没有任何附加条款或条件。

依赖关系

~2MB
~46K SLoC