属性 Attributes

如果属性对整个 crate 都有作用的话, 使用 #![crate_attribute] 写法; 如果只对当前 module, 某个函数等起作用的话, 使用 #[module_attribute] 写法.

设置整个 crate 的属性 #![crate_attribute]; 设置整个 module 的属性, #[crate_attribute], 少了一个 ! 号.

它多种语法形式:

语法描述示例
#[attribute = "value"]设定属性值#![crate_type = "lib"]
#[attribute(key = "value")]key-value 形式, 键值对#![cfg(target_os = "linux")]
#[attribute(value)]单个标识符#[allow(dead_code)], 对某个模块及函数禁用 dead_code lint

接下来, 我们介绍一些常用的属性设置.

inline

用于提示 rustc 编译器, 把该函数标记为内联函数(inline function).

所谓的内联函数, 就是把函数体内的代码直接插入到该函数的调用处, 这样可以在代码里减少一个函数调用的成本.

看下面的一个示例代码, 注释部分是编译器可能生成的代码, 它会将 Point 中定义的函数体直接展开:

#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub struct Point {
    x: i32,
    y: i32,
}

impl Default for Point {
    fn default() -> Self {
        Self::new()
    }
}

impl Point {
    #[must_use]
    #[inline]
    pub const fn new() -> Self {
        Self { x: 0, y: 0 }
    }

    #[must_use]
    #[inline]
    pub const fn from_xy(x: i32, y: i32) -> Self {
        Self { x, y }
    }

    #[inline]
    pub fn set_x(&mut self, x: i32) {
        self.x = x;
    }

    #[inline]
    pub fn set_y(&mut self, y: i32) {
        self.y = y;
    }

    #[must_use]
    #[inline]
    pub const fn x(&self) -> i32 {
        self.x
    }

    #[must_use]
    #[inline]
    pub const fn y(&self) -> i32 {
        self.y
    }
}

fn main() {
    // let mut point: Point = Point {x: 3, y: 4};
    let mut point: Point = Point::from_xy(3, 4);
    // point.x = 2;
    point.set_x(2);
    // let y: i32 = point.y;
    let y: i32 = point.y();
    println!("y: {y}");
}

除了上面的默认写法之外, 还有另外两种写法:

  • #[inline(always)], 建议编译器总是把该函数内联
  • #[inline(never)], 建议编译器不把该函数内联

比如标准库里的 Backtrace::capture() 函数, 它就提示编译器不要做内联.

// From: std/src/backtrace.rs

/// Capture a stack backtrace of the current thread.
///
/// ...
///
#[stable(feature = "backtrace", since = "1.65.0")]
#[inline(never)] // want to make sure there's a frame here to remove
pub fn capture() -> Backtrace {
    if !Backtrace::enabled() {
        return Backtrace { inner: Inner::Disabled };
    }
    Backtrace::create(Backtrace::capture as usize)
}

参考

相关知识