Rust: 属性(attribute)的含义及文档大全

Rust中满地都是属性,对于这些,我们是需要有所了解,否则会感觉 到晕:

#[lang=“copy”] :表示Rust语言本身使用
#[lang =“drop”]
#[derive(Debug,Copy,Clone)]:自动实现这些trait
#![feature(never_type)] :标明是只能在nightly版本使用,此特性目前还是实验性质
#![feature(feature1)]:来源于rust函数,特性有实验、beta、稳定版本等不同阶段,如果打上这个标签,就是让尽管可能是非稳定版,编译器你帮我带上这个特性,开个绿灯,有我用到。
#![feature(async_await,await_macro,pin)]:标明是只能在nightly版本使用
#![feature(specialization)]:只能在nightly版本实现的特化规则
#[allow(dead_code)]: 对于没有用上的代码,不用提示warning
#![feature(try_trait)]:表明是实验特性
#![crate_type = “lib”] :说明一下,这个crate类型是lib
#![crate_name = “rary”]:说明一下,这个crate的名字为rary
#[fundamental]:告诉编译器不必遵守孤儿规则(Box,Fn,FnMut,FnOnce,Sized)
#[rustc_paren_sugar]:表示对括号语法特别解析:Option<&str>>,进行特别解析
#[must_use=“iterator adaptors are lazy…”]:提示开发者相关信息:比如该属性是惰性的
#[must_use]:对相关对象要进行处理,否则会报错,比如用在Result上面,
#[macro_use]:导出相应模块中的宏;
#[macro_export]:表示宏定义的部分,对外面也是可见的。
#[fail(display=“IoErrorKind”)]:自动实现fail,并且所有的错误都需要实现Display
#[cause]:指定标准库中内置的基础错误类型
#[cfg(test)]:只有在执地cargo test时才编译下面的模块
#[cfg(target_arch =“x86”)]:条件编译属性,如果是x86架构的条件,则会进行编译
#[cfg(any(target_arch=“x86”,target_arch=“x86_64”))]:符合这两种的条件,则会进行编译
#[bench]:标注为基础测试,如函数
#[doc=“some desc”]
#[test]:测试函数
#[inline(always)]
#[no_mangle]:告诉编译器,兄弟,你别我整重名了,往往是在ffi时,需要与人交互,一一对应上。
#[repr©] :加上了这个标签的结构体,在内存中的布局和对齐就和 C 一样了,便于安全地传递给 C ABI。
#[link(name = “snappy”)] #[link(…)]属性用来指示链接器链接snappy库来解析符号。
#[cfg(feature =“pattern”)] : 表示当执行cargo build --feature "pattern“命令时,在cargo内部调用rust编译器rustc时,会传"pattern"标记,在输出中也会包含pattern模块。

#[foo]
struct Foo;

mod bar {
    #![bar]
}

#[foo]作用于下一个项,在这就是struct声明。#![bar]作用于包含它的项,在这是mod声明。否则,它们是一样的。它们都以某种方式改变它们附加到的项的意义。

三类:container attribute、field attribute、variant attribute

#[derive(Serialize, Deserialize)]
#[serde(deny_unknown_fields)]  // <-- this is a container attribute
struct S {
    #[serde(default)]  // <-- this is a field attribute
    f: i32,
}

#[derive(Serialize, Deserialize)]
#[serde(rename = "e")]  // <-- this is also a container attribute
enum E {
    #[serde(rename = "a")]  // <-- this is a variant attribute
    A(String),
}

https://doc.rust-lang.org/1.24.1/reference/attributes.html

Attributes

Syntax
Attribute :
   InnerAttribute | OuterAttribute

InnerAttribute :
   #![ MetaItem ]

OuterAttribute :
   #[ MetaItem ]

MetaItem :
      IDENTIFIER
   | IDENTIFIER = LITERAL
   | IDENTIFIER ( MetaSeq )
   | IDENTIFIER ( MetaSeq , )

MetaSeq :
      EMPTY
   | MetaItem
   | MetaSeq , MetaItem

Any item declaration may have an attribute applied to it. Attributes in Rust are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334 (C#). An attribute is a general, free-form metadatum that is interpreted according to name, convention, and language and compiler version. Attributes may appear as any of:

A single identifier, the attribute name
An identifier followed by the equals sign '=' and a literal, providing a key/value pair
An identifier followed by a parenthesized list of sub-attribute arguments

Attributes with a bang ("!") after the hash ("#") apply to the item that the attribute is declared within. Attributes that do not have a bang after the hash apply to the item that follows the attribute.

An example of attributes:

// 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;

Crate-only attributes

crate_name - specify the crate's crate name.
crate_type - see linkage.
no_builtins - disable optimizing certain code patterns to invocations of library functions that are assumed to exist
no_main - disable emitting the main symbol. Useful when some other object being linked to defines main.
no_start - disable linking to the native crate, which specifies the "start" language item.
no_std - disable linking to the std crate.
recursion_limit - Sets the maximum depth for potentially infinitely-recursive compile-time operations like auto-dereference or macro expansion. The default is #![recursion_limit="64"].
windows_subsystem - Indicates that when this crate is linked for a Windows target it will configure the resulting binary's subsystem via the linker. Valid values for this attribute are console and windows, corresponding to those two respective subsystems. More subsystems may be allowed in the future, and this attribute is ignored on non-Windows targets.

Module-only attributes

no_implicit_prelude - disable injecting use std::prelude:? in this module.
path - specifies the file to load the module from. #[path=“foo.rs”] mod bar; is equivalent to mod bar { /* contents of foo.rs */ }. The path is taken relative to the directory that the current module is in.

Function-only attributes

main - indicates that this function should be passed to the entry point, rather than the function in the crate root named main.
test - indicates that this function is a test function, to only be compiled in case of --test.
ignore - indicates that this test function is disabled.
should_panic - indicates that this test function should panic, inverting the success condition.
cold - The function is unlikely to be executed, so optimize it (and calls to it) differently.

FFI attributes

On an extern block, the following attributes are interpreted:

link_args - specify arguments to the linker, rather than just the library name and type. This is feature gated and the exact behavior is implementation-defined (due to variety of linker invocation syntax).
link - indicate that a native library should be linked to for the declarations in this block to be linked correctly. link supports an optional kind key with three possible values: dylib, static, and framework. See external blocks for more about external blocks. Two examples: #[link(name = “readline”)] and #[link(name = “CoreFoundation”, kind = “framework”)].
linked_from - indicates what native library this block of FFI items is coming from. This attribute is of the form #[linked_from = “foo”] where foo is the name of a library in either #[link] or a -l flag. This attribute is currently required to export symbols from a Rust dynamic library on Windows, and it is feature gated behind the linked_from feature.

On declarations inside an extern block, the following attributes are interpreted:

link_name - the name of the symbol that this function or static should be imported as.
linkage - on a static, this specifies the linkage type.

On enums:

repr - on C-like enums, this sets the underlying type used for representation. Takes one argument, which is the primitive type this enum should be represented for, or C, which specifies that it should be the default enum size of the C ABI for that platform. Note that enum representation in C is undefined, and this may be incorrect when the C code is compiled with certain flags.

On structs:

repr - specifies the representation to use for this struct. Takes a list of options. The currently accepted ones are C and packed, which may be combined. C will use a C ABI compatible struct layout, and packed will remove any padding between fields (note that this is very fragile and may break platforms which require aligned access).

On unions:

repr - Same as per struct.

Macro-related attributes

macro_use on a mod — macros defined in this module will be visible in the module’s parent, after this module has been included.

macro_use on an extern crate — load macros from this crate. An optional list of names #[macro_use(foo, bar)] restricts the import to just those macros named. The extern crate must appear at the crate root, not inside mod, which ensures proper function of the $crate macro variable.

macro_reexport on an extern crate — re-export the named macros.

macro_export - export a macro for cross-crate usage.

no_link on an extern crate — even if we load this crate for macros, don’t link it into the output.

See the macros section of the book for more information on macro scope.
Miscellaneous attributes

deprecated - mark the item as deprecated; the full attribute is #[deprecated(since = “crate version”, note = “…”), where both arguments are optional.
export_name - on statics and functions, this determines the name of the exported symbol.
link_section - on statics and functions, this specifies the section of the object file that this item’s contents will be placed into.
no_mangle - on any item, do not apply the standard name mangling. Set the symbol for this item to its identifier.
must_use - on structs and enums, will warn if a value of this type isn’t used or assigned to a variable. You may also include an optional message by using #[must_use = “message”] which will be given alongside the warning.

Documentation

The doc attribute is used to document items and fields. Doc comments are transformed into doc attributes.

See The Rustdoc Book for reference material on this attribute.
Conditional compilation

Sometimes one wants to have different compiler outputs from the same code, depending on build target, such as targeted operating system, or to enable release builds.

Configuration options are boolean (on or off) and are named either with a single identifier (e.g. foo) or an identifier and a string (e.g. foo = “bar”; the quotes are required and spaces around the = are unimportant). Note that similarly-named options, such as foo, foo=“bar” and foo=“baz” may each be set or unset independently.

Configuration options are either provided by the compiler or passed in on the command line using --cfg (e.g. rustc main.rs --cfg foo --cfg ‘bar=“baz”’). Rust code then checks for their presence using the #[cfg(…)] attribute:

// The function is only included in the build when compiling for macOS
#[cfg(target_os = "macos")]
fn macos_only() {
  // ...
}

// This function is only included when either foo or bar is defined
#[cfg(any(foo, bar))]
fn needs_foo_or_bar() {
  // ...
}

// This function is only included when compiling for a unixish OS with a 32-bit
// architecture
#[cfg(all(unix, target_pointer_width = "32"))]
fn on_32bit_unix() {
  // ...
}

// This function is only included when foo is not defined
#[cfg(not(foo))]
fn needs_not_foo() {
  // ...
}

This illustrates some conditional compilation can be achieved using the #[cfg(…)] attribute. any, all and not can be used to assemble arbitrarily complex configurations through nesting.

The following configurations must be defined by the implementation:

target_arch = “…” - Target CPU architecture, such as “x86”, “x86_64” “mips”, “powerpc”, “powerpc64”, “arm”, or “aarch64”. This value is closely related to the first element of the platform target triple, though it is not identical.
target_os = “…” - Operating system of the target, examples include “windows”, “macos”, “ios”, “linux”, “android”, “freebsd”, “dragonfly”, “bitrig” , “openbsd” or “netbsd”. This value is closely related to the second and third element of the platform target triple, though it is not identical.
target_family = “…” - Operating system family of the target, e. g. “unix” or “windows”. The value of this configuration option is defined as a configuration itself, like unix or windows.
unix - See target_family.
windows - See target_family.
target_env = “…” - Further disambiguates the target platform with information about the ABI/libc. Presently this value is either “gnu”, “msvc”, “musl”, or the empty string. For historical reasons this value has only been defined as non-empty when needed for disambiguation. Thus on many GNU platforms this value will be empty. This value is closely related to the fourth element of the platform target triple, though it is not identical. For example, embedded ABIs such as gnueabihf will simply define target_env as “gnu”.
target_endian = “…” - Endianness of the target CPU, either “little” or “big”.
target_pointer_width = “…” - Target pointer width in bits. This is set to “32” for targets with 32-bit pointers, and likewise set to “64” for 64-bit pointers.
target_has_atomic = “…” - Set of integer sizes on which the target can perform atomic operations. Values are “8”, “16”, “32”, “64” and “ptr”.
target_vendor = “…” - Vendor of the target, for example apple, pc, or simply “unknown”.
test - Enabled when compiling the test harness (using the --test flag).
debug_assertions - Enabled by default when compiling without optimizations. This can be used to enable extra debugging code in development but not in production. For example, it controls the behavior of the standard library’s debug_assert! macro.

You can also set another attribute based on a cfg variable with cfg_attr:

#[cfg_attr(a, b)]

This is the same as #[b] if a is set by cfg, and nothing otherwise.

Lastly, configuration options can be used in expressions by invoking the cfg! macro: cfg!(a) evaluates to true if a is set, and false otherwise.
Lint check attributes

A lint check names a potentially undesirable coding pattern, such as unreachable code or omitted documentation, for the static entity to which the attribute applies.

For any lint check C:

allow© overrides the check for C so that violations will go unreported,
deny© signals an error after encountering a violation of C,
forbid© is the same as deny©, but also forbids changing the lint level afterwards,
warn© warns about violations of C but continues compilation.

The lint checks supported by the compiler can be found via rustc -W help, along with their default settings. [Compiler plugins][unstable book plugin] can provide additional lint checks.

pub mod m1 {
    // Missing documentation is ignored here
    #[allow(missing_docs)]
    pub fn undocumented_one() -> i32 { 1 }

    // Missing documentation signals a warning here
    #[warn(missing_docs)]
    pub fn undocumented_too() -> i32 { 2 }

    // Missing documentation signals an error here
    #[deny(missing_docs)]
    pub fn undocumented_end() -> i32 { 3 }
}

This example shows how one can use allow and warn to toggle a particular check on and off:

#[warn(missing_docs)]
pub mod m2{
    #[allow(missing_docs)]
    pub mod nested {
        // Missing documentation is ignored here
        pub fn undocumented_one() -> i32 { 1 }

        // Missing documentation signals a warning here,
        // despite the allow above.
        #[warn(missing_docs)]
        pub fn undocumented_two() -> i32 { 2 }
    }

    // Missing documentation signals a warning here
    pub fn undocumented_too() -> i32 { 3 }
}

This example shows how one can use forbid to disallow uses of allow for that lint check:

#[forbid(missing_docs)]
pub mod m3 {
    // Attempting to toggle warning signals an error here
    #[allow(missing_docs)]
    /// Returns 2.
    pub fn undocumented_too() -> i32 { 2 }
}

Inline attribute

The inline attribute suggests that the compiler should place a copy of the function or static in the caller, rather than generating code to call the function or access the static where it is defined.

The compiler automatically inlines functions based on internal heuristics. Incorrectly inlining functions can actually make the program slower, so it should be used with care.

#[inline] and #[inline(always)] always cause the function to be serialized into the crate metadata to allow cross-crate inlining.

There are three different types of inline attributes:

#[inline] hints the compiler to perform an inline expansion.
#[inline(always)] asks the compiler to always perform an inline expansion.
#[inline(never)] asks the compiler to never perform an inline expansion.

derive

The derive attribute allows certain traits to be automatically implemented for data structures. For example, the following will create an impl for the PartialEq and Clone traits for Foo, the type parameter T will be given the PartialEq or Clone constraints for the appropriate impl:

#[derive(PartialEq, Clone)]
struct Foo {
    a: i32,
    b: T,
}

The generated impl for PartialEq is equivalent to

impl PartialEq for Foo {
    fn eq(&self, other: &Foo) -> bool {
        self.a == other.a && self.b == other.b
    }

    fn ne(&self, other: &Foo) -> bool {
        self.a != other.a || self.b != other.b
    }
}

You can implement derive for your own type through procedural macros.

你可能感兴趣的:(Rust)