有哪些类型的宏/语法扩展/编译器插件?

时间:2016-12-18 21:33:56

标签: macros rust

我对Rust生态系统中用于几个宏观事物的许多术语感到非常困惑。有人可以澄清那些宏/语法扩展/编译插件,并解释这些术语之间的关系吗?

1 个答案:

答案 0 :(得分:15)

你是对的: 令人困惑。特别是,因为大多数这些功能都不稳定并经常变化。但我会尝试总结目前的情况( 2016年12月)。

Venn-diagram showing compiler-plugins and syntax-extensions

让我们从语法扩展开始:为了产生任何效果,必须手动“调用”或注释。有三种语法扩展,它们在注释它们的方式上有所不同:

  • 类似函数的语法扩展:这些可能是最常见的语法扩展,也称为“宏”。调用它们的语法是foo!(…)或(这是非常罕见的)foo! some_ident (…),其中foo是宏的名称。请注意,()括号可以替换为[]{}类似函数的语法扩展可以定义为“宏示例”或“过程宏”。

    < / LI>
  • 类似属性的语法扩展:这些调用类似于#[foo(…)],其中括号不是必需的,同样,foo是语法扩展名。然后,可以通过其他项目(装饰器)修改或扩展属性所属的项目。

  • 自定义派生:大多数Rust程序员已使用#[derive(…)]属性。当然,derive本身可以被视为属性类语法扩展。但它也可以扩展,然后像#[derive(Foo)]一样调用,其中Foo自定义派生的名称。

这些语法扩展中的大多数也是“编译器插件”。唯一的例外是类似函数的语法扩展,它们通过“宏示例”(意为macro_rules!语法)定义。可以在源代码中定义宏示例,而无需编写编译器插件

但也有编译器插件不是语法扩展。那些类型的编译器插件是在编译过程的某个阶段运行某些代码的linters或其他插件。它们不需要手动调用:一旦加载,编译器将在编译期间的某些点调用它们。

所有编译器插件需要加载 - 通过crate-root上的#![plugin(foo)]-Zextra-plugins=too,bar命令行参数 - 才能产生任何效果!< / p>

编译器插件目前不稳定,因此您需要夜间编译器才能使用它们。但是"Macro 1.1"-RFC很快就会稳定下来,这意味着编译器插件的一小部分子集可以与稳定的编译器一起使用。

有用的链接: