Attributes
属性
attributes.md
commit: 51817951d0d213a0011f82b62aae02c3b3f2472e
本章译文最后维护日期:2024-05-02
句法
InnerAttribute :
#
!
[
Attr]
OuterAttribute :
#
[
Attr]
Attr :
SimplePath AttrInput?AttrInput :
DelimTokenTree
|=
Expression
属性是一种通用的、格式自由的元数据(free-form metadatum),这种元数据会(被编译器/解释器)依据名称、约定、语言和编译器版本进行解释。(Rust 语言中的)属性是根据 ECMA-335 标准中的属性规范进行建模的,其语法来自 ECMA-334 (C#)。
*内部属性(Inner attributes)*以 #!
开头的方式编写,应用于它在其中声明的程序项。*外部属性(Outer attributes)*以不后跟感叹号的(!
)的 #
开头的方式编写,应用于属性后面的内容。
属性由指向属性的路径和路径后跟的可选的带定界符的 token树(delimited token tree)(其解释由属性定义)组成。除了宏属性之外,其他属性的输入也允许使用等号(=
)后跟表达式的格式。更多细节请参见下面的元项属性句法(meta item syntax)。
属性可以分为以下几类:
属性可以应用于语言中的许多场景:
- 所有的程序项声明都可接受外部属性,同时外部块、函数、实现和模块都可接受内部属性。
- 大多数语句都可接受外部属性(参见表达式属性,了解表达式语句的限制)。
- 块表达式也可接受外部属性和内部属性,但只有当它们是另一个表达式语句的外层表达式时,或是另一个块表达式的最终表达式(final expression)时才有效。
- 枚举(
enum
)变体和结构体(struct
)、联合体(union
)的字段可接受外部属性。 - 匹配表达式的匹配臂(arms)可接受外部属性。
- 泛型生存期(Generic lifetime)或类型参数可接受外部属性。
- 表达式在有限的情况下可接受外部属性,详见表达式属性。
- 函数、闭包和函数指针的参数可接受外部属性。这包括函数指针和外部块中用
...
表示的可变参数上的属性。
属性的一些例子:
Meta Item Attribute Syntax
元项/元程序项属性句法
“元项(meta item)”是遵循 Attr 产生式(见本章头部)的句法,Rust 的大多数内置属性(built-in attributes)都使用了此句法。它有以下文法格式:
句法
MetaItem :
SimplePath
| SimplePath=
Expression
| SimplePath(
MetaSeq?)
MetaSeq :
MetaItemInner (,
MetaItemInner )*,
?MetaItemInner :
MetaItem
| Expression
元项中的表达式必须能宏展开为字面量表达式,且字面量表达式不得包含整型或浮点型后缀。现在,非字面量表达式的表达式可以在语法上被接受(并且可以传递给过程宏)了,但在解析后却被丢弃。
请注意,如果该属性出现在另一个宏中,它将在该外部宏展开之后再展开。例如,下面的代码将首先展开为名为 Serialize
的过程宏,在第一次展开时,它必须保留 include_str!
调用,以便将来再次展开:
#[derive(Serialize)]
struct Foo {
#[doc = include_str!("x.md")]
x: u32
}
此外,对与某个程序项来说,如果它的属性中用到了宏,那这个宏仅在所有其他相关属性都展开生效之后才展开:
#[macro_attr1] // 展开排序为第一
#[doc = mac!()] // `mac!` 展开排序为第四
#[macro_attr2] // 展开排序为第二
#[derive(MacroDerive1, MacroDerive2)] // 展开排序为第三
fn foo() {}
各种内置属性使用元项句法的不同子集来指定它们的输入。下面的文法规则展示了一些常用的使用形式:
句法
MetaWord:
IDENTIFIERMetaNameValueStr:
IDENTIFIER=
(STRING_LITERAL | RAW_STRING_LITERAL)MetaListPaths:
IDENTIFIER(
( SimplePath (,
SimplePath)*,
? )?)
MetaListIdents:
IDENTIFIER(
( IDENTIFIER (,
IDENTIFIER)*,
? )?)
MetaListNameValueStr:
IDENTIFIER(
( MetaNameValueStr (,
MetaNameValueStr)*,
? )?)
元项句法的一些例子是:
形式 | 示例 |
---|---|
MetaWord | no_std |
MetaNameValueStr | doc = "example" |
MetaListPaths | allow(unused, clippy::inline_always) |
MetaListIdents | macro_use(foo, bar) |
MetaListNameValueStr | link(name = "CoreFoundation", kind = "framework") |
Active and inert attributes
活跃属性和惰性属性
属性要么是活跃的,要么是惰性的。在属性处理过程中,活跃属性将自己从它们所在的对象上移除,而惰性属性依然保持原位置不变。
cfg
和 cfg_attr
属性是活跃的。test
属性在为测试所做的编译形式中是惰性的,在其他编译形式中是活跃的。宏属性是活跃的。所有其他属性都是惰性的。
Tool attributes
外部工具的属性
编译器可能允许和具体外部工具相关联的属性,但这些工具在编译和检查过程中必须存在并驻留在编译器提供的工具类预导入包下对应的命名空间中(才能让这些属性生效)。这种属性的(命名空间)路径的第一段是工具的名称,后跟一个或多个工具自己解释的附加段。
当工具在编译期不可用时,该工具的属性将被静默接受而不提示警告。当工具可用时,该工具负责处理和解释这些属性。
如果使用了 no_implicit_prelude
属性,则外部工具属性不可用。
注意:
rustc
目前能识别 “clippy” 、“rustfmt” 和 "diagnostic" 这些工具。
Built-in attributes index
内置属性的索引表
下面是所有内置属性的索引表:
- 条件编译(Conditional compilation)
- 测试(Testing)
test
— 将函数标记为测试函数。ignore
— 禁止测试此函数。should_panic
— 表示测试应该产生 panic。
- 派生(Derive)
derive
— 自动部署 trait实现automatically_derived
— 用在由derive
创建的实现上的标记。
- 宏(Macros)
macro_export
— 导出声明宏(macro_rules
宏),用于跨 crate 的使用。macro_use
— 扩展宏可见性,或从其他 crate 导入宏。proc_macro
— 定义类函数宏。proc_macro_derive
— 定义派生宏。proc_macro_attribute
— 定义属性宏。
- 诊断(Diagnostics)
allow
、warn
、deny
、forbid
— 更改默认的 lint检查级别。deprecated
— 生成弃用通知。must_use
— 为未使用的值生成 lint 提醒。diagnostic::on_unimplemented
— 如个某个 trait 没有被实现,则提醒编译器发射一个特定的错误消息。
- ABI、链接(linking)、符号(symbol)、和 FFI
link
— 指定要与外部(extern
)块链接的本地库。link_name
— 指定外部(extern
)块中的函数或静态项的符号(symbol)名。link_ordinal
— 指定外部(extern
)块中函数或静态符号的序号。no_link
— 防止链接外部crate。repr
— 控制类型的布局。crate_type
— 指定 crate 的类别(库、可执行文件等)。no_main
— 禁止发布main
符号(symbol)。export_name
— 指定函数或静态项导出的符号(symbol)名。link_section
— 指定用于函数或静态项的对象文件的部分。no_mangle
— 禁用对符号(symbol)名编码。used
— 强制编译器在输出对象文件中保留静态项。crate_name
— 指定 crate名。
- 代码生成(Code generation)
inline
— 内联代码提示。cold
— 提示函数不太可能被调用。no_builtins
— 禁用某些内置函数。target_feature
— 配置特定于平台的代码生成。track_caller
- 将父调用位置传递给std::panic::Location::caller()
。instruction_set
- 指定用于生成函数代码的指令集S
- 文档(Documentation)
doc
— 指定文档。更多信息见 The Rustdoc Book。Doc注释会被转换为doc
属性。
- 预导入包(Preludes)
no_std
— 从预导入包中移除 std。no_implicit_prelude
— 禁用模块内的预导入包查找。
- 模块(Modules)
path
— 指定模块的源文件名。
- 极限值设置(Limits)
recursion_limit
— 设置某些编译时操作的最大递归限制。type_length_limit
— 设置多态类型(polymorphic type)单态化过程中构造具体类型时所做的最大类型替换次数。
- 运行时(Runtime)
panic_handler
— 设置处理 panic 的函数。global_allocator
— 设置全局内存分配器。windows_subsystem
— 指定要链接的 windows 子系统。
- 特性(Features)
feature
— 用于启用非稳定的或实验性的编译器特性。参见 The Unstable Book 了解在rustc
中实现的特性。
- 类型系统(Type System)
non_exhaustive
— 表明一个类型将来会添加更多的字段/变体。
- 调试器
debugger_visualizer
— 嵌入一个文件,该文件指定类型的调试器输出。collapse_debuginfo
— 控制宏调用在调试信息中的编码方式。