Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

属性

Syntax
InnerAttribute# ! [ Attr ]

OuterAttribute# [ Attr ]

Attr
      SimplePath AttrInput?
    | unsafe ( SimplePath AttrInput? )

AttrInput
      DelimTokenTree
    | = Expression

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

内部属性,写在哈希符号 (#) 后带一个感叹号 (!),适用于声明该属性的所在形式。

例子

#![allow(unused)]
fn main() {
// 适用于 enclosing 模块或 crate 的通用元数据。
#![crate_type = "lib"]

// 内部属性适用于整个函数。
fn some_unused_variables() {
  #![allow(unused_variables)]

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

外部属性,写在哈希符号后不带感叹号,适用于属性后面的形式。

例子

#![allow(unused)]
fn main() {
// 标记为单元测试的函数
#[test]
fn test_foo() {
    /* ... */
}

// 有条件编译的模块
#[cfg(target_os = "linux")]
mod bar {
    /* ... */
}

// 用于抑制警告/错误的 lint 属性
#[allow(non_camel_case_types)]
type int8_t = i8;
}

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

属性的应用可能不安全。为避免在使用这些属性时出现未定义行为,必须满足某些编译器无法检查的义务。为了声明这些义务已满足,属性被 unsafe(..) 包裹,例如 #[unsafe(no_mangle)]

以下属性是不安全的:

属性可以分为以下几种:

属性可以应用于语言中的多种形式:

元项属性语法

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

Syntax
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() {}

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

Syntax
MetaWord
    IDENTIFIER

MetaNameValueStr
    IDENTIFIER = ( STRING_LITERAL | RAW_STRING_LITERAL )

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

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

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

一些元项的示例如下:

样式示例
元字no_std
元名称值字符串doc = "example"
元列表路径allow(unused, clippy::inline_always)
元列表标识符macro_use(foo, bar)
元列表名称值字符串link(name = "CoreFoundation", kind = "framework")

活跃属性和惰性属性

属性要么是活跃的,要么是惰性的。在属性处理期间,活跃属性 会从它们所在的表单中移除自己,而 惰性属性 则保留在表单上。

cfgcfg_attr 属性是活跃的。属性宏 是活跃的。所有其他属性都是惰性的。

工具属性

编译器可能允许外部工具的属性,其中每个工具都位于 工具预导入 中的自己的模块中。属性路径的第一个段是工具的名称,带有一个或多个额外段,其解释由工具决定。

当工具未使用时,工具的属性会被接受,而不会发出警告。当工具在使用时,工具负责处理和解释其属性。

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

#![allow(unused)]
fn main() {
// 告诉 rustfmt 工具不要格式化以下元素。
#[rustfmt::skip]
struct S {
}

// 控制 clippy 工具的“圈复杂度”阈值。
#[clippy::cyclomatic_complexity = "100"]
pub fn f() {}
}

注意

rustc 目前识别的工具包括 “clippy”, “rustfmt”, “diagnostic”, “miri” 和 “rust_analyzer”。

内置属性索引

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

  • 条件编译

    • cfg — 控制条件编译。
    • cfg_attr — 有条件地包含属性。
  • 测试

    • test — 将函数标记为测试。
    • ignore — 禁用测试函数。
    • should_panic — 表示测试应生成一个 恐慌。
  • 派生

  • 诊断

  • ABI、链接、符号和 FFI

    • link — 指定要与 extern 块链接的本地库。
    • link_name — 指定 extern 块中函数或静态变量的符号名称。
    • link_ordinal — 指定 extern 块中函数或静态变量的符号序号。
    • no_link — 阻止链接外部 crate。
    • repr — 控制类型布局。
    • crate_type — 指定 crate 的类型(库、可执行文件等)。
    • no_main — 禁用发出 main 符号。
    • export_name — 指定函数或静态变量的导出符号名称。
    • link_section — 指定函数或静态变量要使用的对象文件节。
    • no_mangle — 禁用符号名称编码。
    • used — 强制编译器将静态 项 保留在输出对象文件中。
    • crate_name — 指定 crate 名称。
  • 代码生成

    • inline — 提示内联代码。
    • cold — 提示函数不太可能被调用。
    • naked — 阻止编译器发出函数序言和尾声。
    • no_builtins — 禁用使用某些内置函数。
    • target_feature — 配置特定于平台的代码生成。
    • track_caller — 将父调用位置传递给 std::panic::Location::caller()
    • instruction_set — 指定用于生成函数代码的指令集。
  • 文档

  • 预导入

  • 模块

    • path — 指定模块的文件名。
  • 限制

  • 运行时

  • 特性

    • feature — 用于启用不稳定或实验性编译器 特性。有关 rustc 中实现的 特性,请参阅 The Unstable Book
  • 类型系统

    • non_exhaustive — 指示将来会为类型添加更多字段/变体。
  • 调试器