属性

语法

内部属性 :

   # ! [ Attr ]

外部属性 :

   # [ Attr ]

Attr :

   简单路径 AttrInput?

AttrInput :

      分隔符词法树

   | = 表达式

属性 是一种通用的、自由形式的元数据,根据名称、约定、语言和编译器版本进行解释。属性的模型是 ECMA-335 中的属性,语法来自 ECMA-334 (C#)。

内部属性,在井号 (#) 后面写一个感叹号 (!),应用于声明该属性的项。外部属性,在井号后面没有感叹号,应用于属性后面的内容。

属性由属性的路径组成,后面跟着一个可选的分隔符词法树,其解释由属性定义。宏属性以外的属性还允许输入是一个等号 (=),后面跟着一个表达式。有关更多详细信息,请参阅下面的 元项语法

属性可以分为以下几种

属性可以应用于语言中的许多内容

一些属性示例

#![allow(unused)]
fn main() {
// General metadata applied to the enclosing module or crate.
#![crate_type = "lib"]

// A function marked as a unit test
#[test]
fn test_foo() {
    /* ... */
}

// A conditionally-compiled module
#[cfg(target_os = "linux")]
mod bar {
    /* ... */
}

// A lint attribute used to suppress a warning/error
#[allow(non_camel_case_types)]
type int8_t = i8;

// Inner attribute applies to the entire function.
fn some_unused_variables() {
  #![allow(unused_variables)]

  let x = ();
  let y = ();
  let z = ();
}
}

元项属性语法

“元数据项”是大多数内置属性用于 Attr 规则的语法。它具有以下语法

语法

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] // expanded first
#[doc = mac!()] // `mac!` is expanded fourth.
#[macro_attr2] // expanded second
#[derive(MacroDerive1, MacroDerive2)] // expanded third
fn foo() {}

各种内置属性使用元数据项语法的不同子集来指定其输入。以下语法规则显示了一些常用形式

语法

MetaWord:

   IDENTIFIER

MetaNameValueStr:

   IDENTIFIER = (STRING_LITERAL | RAW_STRING_LITERAL)

MetaListPaths:

   IDENTIFIER ( ( SimplePath (, SimplePath)* ,? )? )

MetaListIdents:

   IDENTIFIER ( ( IDENTIFIER (, IDENTIFIER)* ,? )? )

MetaListNameValueStr:

   IDENTIFIER ( ( MetaNameValueStr (, MetaNameValueStr)* ,? )? )

以下是元数据项的一些示例

样式示例
MetaWordno_std
MetaNameValueStrdoc = "example"
MetaListPathsallow(unused, clippy::inline_always)
MetaListIdentsmacro_use(foo, bar)
MetaListNameValueStrlink(name = "CoreFoundation", kind = "framework")

活动和惰性属性

属性可以是活动的,也可以是惰性的。在属性处理过程中,活动属性会从它们所在的位置移除自身,而惰性属性则会保留。

cfgcfg_attr 属性是活动的。test 属性在编译测试时是惰性的,否则是活动的。属性宏是活动的。所有其他属性都是惰性的。

工具属性

编译器可以允许外部工具使用属性,其中每个工具都位于工具前奏中的自己的命名空间中。属性路径的第一段是工具的名称,后面是一个或多个附加段,其解释由工具决定。

当一个工具没有被使用时,该工具的属性会被接受,并且不会发出警告。当工具正在使用时,该工具负责处理和解释其属性。

如果使用了 no_implicit_prelude 属性,则工具属性不可用。

#![allow(unused)]
fn main() {
// Tells the rustfmt tool to not format the following element.
#[rustfmt::skip]
struct S {
}

// Controls the "cyclomatic complexity" threshold for the clippy tool.
#[clippy::cyclomatic_complexity = "100"]
pub fn f() {}
}

注意:rustc 当前识别工具“clippy”、“rustfmt”和“diagnostic”。

内置属性索引

以下是所有内置属性的索引。

  • 条件编译
    • cfg — 控制条件编译。
    • cfg_attr — 有条件地包含属性。
  • 测试
    • test — 将函数标记为测试。
    • ignore — 禁用测试函数。
    • should_panic — 指示测试应该生成一个恐慌。
  • 派生
  • 诊断
  • ABI、链接、符号和 FFI
    • link — 指定要与 extern 块链接的原生库。
    • link_name — 指定 extern 块中函数或静态变量的符号名称。
    • link_ordinal — 指定 extern 块中函数或静态变量的符号序号。
    • no_link — 防止链接外部箱。
    • repr — 控制类型布局。
    • crate_type — 指定箱的类型(库、可执行文件等)。
    • no_main — 禁用发出 main 符号。
    • export_name — 指定函数或静态变量的导出符号名称。
    • link_section — 指定用于函数或静态变量的目标文件部分。
    • no_mangle — 禁用符号名称编码。
    • used — 强制编译器在输出目标文件中保留静态项。
    • crate_name — 指定箱名称。
  • 代码生成
    • inline — 提示内联代码。
    • cold — 提示函数不太可能被调用。
    • no_builtins — 禁用某些内置函数的使用。
    • target_feature — 配置特定于平台的代码生成。
    • track_caller - 将父调用位置传递给 std::panic::Location::caller()
    • instruction_set - 指定用于生成函数代码的指令集
  • 文档
  • 前奏
  • 模块
    • path — 指定模块的文件名。
  • 限制
  • 运行时
  • 特性
    • feature — 用于启用不稳定或实验性的编译器特性。有关 rustc 中实现的特性,请参阅不稳定特性书籍
  • 类型系统
    • non_exhaustive — 指示类型将在将来添加更多字段/变体。
  • 调试器