我们平常在阅读别人的rust代码常常会在结构体或者是函数中出现属性,例如在结构体中我们常见的#[derive(Debug)],这种叫做派生宏辅助属性,还有我们单元测试中会遇到#[test]这个属性,注解在函数中用来标识是个测试函数,当我们x运行cargo test的时候就会被扫描到从而进行测试操作。属性是一种通用的,格式自由的元数据,这种元数据会被编译器或者解释器一句名称,约定,语言和编译器版本进行解释。内部属性(inner attributes)#!开头方式编写,应用于它在其中声明的程序项中。外部属性(outer attri) 以后面不跟感叹号的#开头的方式编写,应用于属性后面的内容。
属性由指向属性的路径和路径后跟的可选的带界定符的token树组成。除了宏属性之外,其它属性的输入也允许使用等号(=)后跟文字表达式的格式。

属性分类

  • 内置属性
  • 宏属性
  • 派生宏辅助属性
  • 外部工具属性

属性应用场景

  • 所有的程序项声明都可以接受外部属性,同时外部块,函数,实现和模块都可以接受内部属性。
  • 大多数语句都可以接受外部属性。
  • 块表达式也可以接受外部属性和内部属性,但只有当它们是另一个表达式语句的外层表达式时,或是另一个块表达式的最终表达式时才有效。
  • 枚举(enum)变体和结构体(struct),联合体(union)的字段可接受外部属性。
  • 匹配表达式的匹配可接受外部属性。
  • 泛生存期或类型参数可接受外部属性。
  • 表达式在有限的情况下可接受外部属性。
  • 函数,闭包和函数指针的参数都可以接受外部属性。这包括函数指针和外部块中用...表示的可变参数上的属性。

    例子

    应用于当前模块或者crate的一般性元数据

    #![crate_type = "lib"]

    标记为单元测试的函数

    #[test]
    fn test_foo(){
    // snip
    }

    条件编译模块

    #[cfg(target_os = "MacOs")]
    mod bar{
    // snip
    }

    用于静音lint检查后报告的告警和错误提醒

    #[allow(non_camel_case_types)]
    type int8_t = i8;

适用于整个函数的内部属性

fn fn_inner_attri(){
  #![allow(unused_variable)]
  let x = ();
  let y = 4;
  let z = 4.45;
}

活跃属性和惰性属性

属性要么是活跃的,要么是惰性的。在属性处理过程中,活跃属性 将自己从它们所在的对象上移除。而惰性属性仍然保持原位置不变。

cfgcfg_attr属性是活跃的。test属性在为测试所做的编译形式是惰性的,在其它编译形式中是活跃的。宏属性是活跃的。所有其它属性都是惰性的。

外部工具属性

编译器可能允许和具体外部工具相关联的属性,但这些工具在编译和检查过程中必须存在驻留在编译器提供的工具类预导入包下对应的命名空间中。这种属性的路径的第一段工具的名称,后跟一个或多个工具自己解释的附加段。

当工具在编译期不可用时,该工具的属性将被静默接受而不提示警告。当工具可用时,该工具负责处理和解释这些属性。

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

#[rustfmt::skip]
struct S{}
// 控制clippy工具的“圈复杂度(cyclomatic complexity)”极限值。
#[clippy::cycomatic_complexity = "100"]
pub fn f(){}

内置属性的索引表

  • 条件编译(Conditional compilation)

    • cfg:控制条件编译。
    • cfg_attr:选择性包哈属性。
  • 测试(Testing)

    • test:将函数标记为测试函数。
    • ignore:禁止测试次函数。
    • should_panic:表示测试应该产生panic。
  • 派生(Derive)

    • derive:自动部署trait实现。
    • automatically_derived:用在由derive创建的实现上的标记。
  • 宏(Macros)

    • macro_export:导出宏声明,用于跨crate的使用。
    • macro_use:可扩展可见性,或从其它crate导入宏。
    • proc_macro: 定义类函数宏。
    • proc_macro_derive:定义派生宏。
    • proc_macro_attribute:定义属性宏。
  • 诊断(Diagnostics)

    • allow,warn,deny,forbid:更改默认的lint检查级别。
    • deprecated: 生成弃用通知。
    • must_use:为未使用的值生成lint提醒。
  • ABI,链接(linking),符号(symbol)和FFI

    • link:指定要与外部(extern)块链接的本地库。
    • link_name: 指定外部(extern)块中的函数或静态项的符号名。
    • no_link:防止链接外部crate。
    • repr:控制类型的布局。
    • crate_type:指定crate的类别(库,可执行文件等)。
    • no_main:禁止发布main符号。
    • export_name:指定函数或静态项导出的符号名。
    • link_section:指定用于函数或静态项的对象文件的部分。
    • no_mangle:禁用对符号名编码
    • used:强制编译器在输出对象文件中保留静态项。
    • crate_name:指定crate名。
  • 代码生成(Code generation)

    • inline:內联代码提示。
    • clod:提示函数不太可能被调用。
    • no_builtins:禁用某些内置函数。
    • target_feature:配置特定于平台的代码生成。
    • track_caller:将父调用位置传递给std::panic::location::clear().
  • 文档(Documentation)

    • doc:指定文档。
  • 预导入包(Preludes)

    • no_std:从预导入包中衣橱std。
    • no_implicit_prelude:禁用模块内的预导入包查找。
  • 模块(Modules)

    • path:指定模块的源文件名。
  • 极限值设置(limits)

    • recursion_limit:设置某些编译时操作的最大递归限制。
    • type_length_limit:设置多态类型单态化过程中构造具体类型时所作的最大类型替换次数。
  • 运行时(Runtime)

    • panic_handler:设置处理panic的函数。
    • global_allocator:设置全局内存分配器。
    • windows_subsystem:指定要链接的windows子系统。
  • 特性(Feature)

    • feature:用于启用非稳定的或实现性的编译器特性。
  • 类型系统(Type System)

    • non_exhaustive: 表明一个类型将来会添加更多的字段/变体。

最后欢迎大家关注我的公众号:花说编程


lizehucoder
1 声望0 粉丝