14个版本
使用旧的Rust 2015
0.4.3 | 2021年3月19日 |
---|---|
0.4.2 | 2019年7月16日 |
0.4.1 | 2018年9月3日 |
0.4.0 | 2017年10月23日 |
0.1.0 | 2016年12月30日 |
#24 in #hack
19,155 下载量每月
4KB
73 行
表达式位置的过程宏
注意: 截至Rust 1.45,此包已被原生支持表达式位置中的#[proc_macro]所取代。只有在你关心支持1.31至1.45之间的编译器时,才应考虑使用此包。 |
自从Rust 1.30以来,语言支持用户定义的过程函数-like宏。然而,这些只能在项目位置调用,而不能在语句或表达式中调用。
此包实现了一种可以在语句或表达式位置调用的过程宏的替代类型。
此方法适用于任何1.31+的Rust版本。
定义过程宏
定义过程宏需要两个包。
实现包
此包必须只包含过程宏。私有辅助函数和私有模块是可以的,但不能有任何公共内容。
就像你会使用#[proc_macro]属性来定义原生支持的过程宏一样,使用proc-macro-hack的#[proc_macro_hack]属性来定义可以在表达式位置工作的过程宏。函数签名与普通函数-like过程宏相同。
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-hack 宏。如果您需要支持嵌套调用,请使用
proc-macro-nested
。 -
默认情况下, hygiene 结构使得展开的代码不能引用除宏输入中某处通过名称传递的本地变量以外的本地变量。如果您的宏必须引用在宏输入中未命名的 本地 变量,请在声明crate的重新导出中使用
#[proc_macro_hack(fake_call_site)]
。 大多数宏不需要这个。 -
在足够新的编译器上,对于能够原生支持表达式位置的 proc macros 的编译器,proc-macro-hack 不自动使用该支持,因为两个实现之间的 hygiene 可能会有细微的差别。要选择将您的宏编译为足够新的编译器上的本地
#[proc_macro]
,请在声明crate的重新导出中使用#[proc_macro_hack(only_hack_old_rustc)]
。
许可证
根据您的选择,在 Apache License, Version 2.0 或 MIT 许可证下许可。请参阅 Apache License, Version 2.0 或 MIT license。除非您明确声明,否则根据 Apache-2.0 许可证定义,您故意提交以包含在此 hack 中的任何贡献,将按上述方式双重许可,不附加任何额外条款或条件。