DAILY DOCDAILY DOC
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
Rust
Node
Notes
Ubuntu
Leetcode
  • it-tools
  • excalidraw
  • linux-command
  • rust

    • Rust
    • add
    • 属性(attributes)
    • cargo issue
    • cli
    • build.rs
    • Enums
    • eventEmitter(rust)
    • 格式化输出 std::fmt
    • rust iterator
    • rust 学习计划
    • 生命周期(lifetime)
    • Linked List
    • log
    • macros
    • mem::size_of
    • niche optimization
    • Rust 所有权
    • 模式匹配(pattern matching)
    • module system
    • result & option
    • .rust-analyzer.json
    • rust startup
    • rust-test
    • 可见性(visibility)
    • cargo
    • toml

属性(attributes)

1. 基本语法

属性通常用 #[...] 或 #![...] 语法表示。前者用于局部作用域(例如函数、模块、变量等),后者用于全局作用域(例如整个 crate)。

#[attribute]
fn function() {
    // ...
}

#![attribute]
mod module {
    // ...
}

2. 常见属性

2.1 #[derive]

自动为结构体或枚举生成特定的 trait 实现,例如 Debug、Clone、PartialEq 等。

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

2.2 #[cfg] 和 #[cfg_attr]

条件编译,根据指定条件编译特定代码。

#[cfg(target_os = "windows")]
fn do_something() {
    println!("Running on Windows");
}

#[cfg_attr(feature = "special_feature", derive(Debug))]
struct SpecialStruct {
    value: i32,
}

2.3 #[inline] 和 #[inline(always)]

建议编译器内联函数。

#[inline]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[inline(always)]
fn mul(a: i32, b: i32) -> i32 {
    a * b
}

2.4 #[allow] 和 #[deny]

控制警告和错误,允许或禁止特定的 lint。

#[allow(dead_code)]
fn unused_function() {
    // ...
}

#[deny(warnings)]
fn main() {
    // ...
}

2.5 #[test]

标记单元测试函数。

#[cfg(test)]
mod tests {
    #[test]
    fn it_works() {
        assert_eq!(2 + 2, 4);
    }
}

2.6 #[no_mangle] 和 extern "C"

防止编译器对函数名进行名称修饰,常用于与 C 语言的 FFI。

#[no_mangle]
pub extern "C" fn my_function() {
    // ...
}

2.7 #[repr]

控制结构体或枚举的内存布局。

#[repr(C)]
struct MyStruct {
    a: i32,
    b: i64,
}

3. 高级用法

3.1 自定义属性宏

使用过程宏定义自定义属性宏。这个功能需要在 Cargo.toml 中启用 proc-macro 功能。

Cargo.toml:

[dependencies]
proc-macro = "1.0"

lib.rs:

extern crate proc_macro;
use proc_macro::TokenStream;

#[proc_macro_attribute]
pub fn my_attribute(args: TokenStream, input: TokenStream) -> TokenStream {
    // 处理输入的 TokenStream 并生成新的 TokenStream
    input
}

main.rs:

use my_crate::my_attribute;

#[my_attribute]
fn my_function() {
    // ...
}

3.2 生命周期属性

控制生命周期参数的行为,例如 #[must_use] 确保返回值被使用。

#[must_use]
struct ImportantResult {
    value: i32,
}

fn calculate() -> ImportantResult {
    ImportantResult { value: 42 }
}

fn main() {
    let _result = calculate(); // 这里会有警告,因为必须使用返回值
}

3.3 #[panic_handler] 和 #[alloc_error_handler]

定义自定义的 panic 和内存分配错误处理器,常用于 #![no_std] 环境。

#![no_std]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

#[alloc_error_handler]
fn alloc_error(layout: core::alloc::Layout) -> ! {
    loop {}
}

4. 属性的组合使用

多个属性可以组合使用,以下是一个示例,展示了多种属性的组合使用:

#![allow(dead_code)]

#[repr(C)]
#[derive(Debug, Clone, Copy)]
struct MyStruct {
    a: i32,
    b: i64,
}

#[inline(always)]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn my_function() {
    let x = add(1, 2);
    println!("Result: {}", x);
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_add() {
        assert_eq!(super::add(1, 2), 3);
    }
}

5. 属性的作用范围

属性可以作用于不同的范围,包括整个 crate、模块、函数、结构体、枚举、字段等。例如:

#![crate_name = "my_crate"]

#[cfg(feature = "my_feature")]
mod my_module {
    #[derive(Debug)]
    struct MyStruct {
        a: i32,
        b: i32,
    }

    #[inline]
    fn my_function() {
        // ...
    }
}

6. 自定义属性宏示例

这里是一个简单的自定义属性宏示例,展示了如何创建并使用自定义属性宏。

Cargo.toml:

[dependencies]
proc-macro = "1.0"

lib.rs:

extern crate proc_macro;
use proc_macro::TokenStream;
use quote::quote;
use syn::{parse_macro_input, ItemFn};

#[proc_macro_attribute]
pub fn my_attribute(_attr: TokenStream, item: TokenStream) -> TokenStream {
    let input = parse_macro_input!(item as ItemFn);
    let name = &input.sig.ident;
    let block = &input.block;

    let expanded = quote! {
        fn #name() {
            println!("Function {} is called", stringify!(#name));
            #block
        }
    };

    TokenStream::from(expanded)
}

main.rs:

use my_crate::my_attribute;

#[my_attribute]
fn my_function() {
    println!("Hello, world!");
}

fn main() {
    my_function();
}

7. 更多常见属性

7.1 #[macro_use]

启用一个模块中的宏定义,使其在整个 crate 中都可用。

#[macro_use]
extern crate my_crate;

mod my_module {
    macro_rules! say_hello {
        () => {
            println!("Hello!");
        };
    }
}

fn main() {
    say_hello!();  // 现在可以在 main 函数中使用 my_module 中定义的宏
}

7.2 #[path]

指定模块的路径,通常用于自定义模块文件的位置。

#[path = "custom/path/to/module.rs"]
mod my_module;

fn main() {
    my_module::my_function();
}

7.3 #[global_allocator]

指定全局分配器,用于替换默认的内存分配策略。

use std::alloc::System;

#[global_allocator]
static A: System = System;

fn main() {
    let x = Box::new(42);
    println!("{}", x);
}

7.4 #[panic_handler]

自定义 panic 处理函数,通常在 #![no_std] 环境中使用。

#![no_std]
#![no_main]

use core::panic::PanicInfo;

#[panic_handler]
fn panic(_info: &PanicInfo) -> ! {
    loop {}
}

7.5 #[link]

链接外部库,通常用于与 C 语言库进行交互。

#[link(name = "mylib")]
extern "C" {
    fn my_function();
}

fn main() {
    unsafe {
        my_function();
    }
}

8. 特殊属性

8.1 #[must_use]

标记一个类型或函数的返回值,要求调用者必须使用该返回值,否则会有编译器警告。

#[must_use]
struct ImportantResult {
    value: i32,
}

#[must_use]
fn calculate() -> ImportantResult {
    ImportantResult { value: 42 }
}

fn main() {
    let _ = calculate();  // 没有使用返回值,编译器会发出警告
}

8.2 #[doc]

用于文档注释,可以在生成的文档中展示额外的信息。

/// This is a function that adds two numbers.
#[doc = "This attribute adds additional documentation."]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

9. 高级属性

9.1 #[cold]

提示编译器这是一个很少调用的函数,优化时会考虑该信息。

#[cold]
fn rarely_called_function() {
    // ...
}

9.2 #[target_feature]

指定函数使用的 CPU 特性。

#[target_feature(enable = "sse2")]
unsafe fn add_sse2(a: f32, b: f32) -> f32 {
    // 使用 SSE2 特性实现的加法
}

9.3 #[proc_macro]

定义过程宏,用于编写自定义的编译时代码生成逻辑。

use proc_macro::TokenStream;

#[proc_macro]
pub fn my_macro(input: TokenStream) -> TokenStream {
    // 实现宏的逻辑
    input
}

10. 属性组合示例

以下是一个结合多个属性的复杂示例,展示了如何在实际项目中综合运用这些属性。

#![crate_name = "my_crate"]
#![feature(proc_macro)]

extern crate proc_macro;
use proc_macro::TokenStream;
use std::fmt::{self, Write};

#[macro_export]
macro_rules! my_macro {
    ($arg:expr) => {
        println!("{}", $arg);
    };
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
struct MyStruct {
    a: i32,
    b: i64,
}

#[inline(always)]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

#[no_mangle]
pub extern "C" fn my_function() {
    let x = add(1, 2);
    println!("Result: {}", x);
}

#[cfg(test)]
mod tests {
    #[test]
    fn test_add() {
        assert_eq!(super::add(1, 2), 3);
    }
}

#[proc_macro]
pub fn my_custom_macro(input: TokenStream) -> TokenStream {
    // 自定义宏的实现
    input
}

#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    loop {}
}

1. 常见属性

这些属性通常用于控制编译器行为、优化、条件编译等。

  • #[cfg]: 根据条件编译代码块。
  • #[derive]: 自动生成 trait 实现,如 Debug、Clone、Copy 等。
  • #[inline]: 建议编译器内联函数。
  • #[no_mangle]: 防止函数名被编译器修改。
  • #[repr]: 控制结构体或枚举的内存布局。
  • #[test]: 标记单元测试函数。
  • #[allow] 和 #[deny]: 控制编译器警告和错误。
  • #[macro_export]: 允许宏在其他 crate 中使用。
  • #[doc]: 用于文档生成的注释。

2. 特定配置和目标属性

这些属性用于特定的配置和目标环境。

  • #[no_std]: 禁用标准库。
  • #[no_main]: 禁用主函数入口点。
  • #[cfg_attr]: 在特定条件下应用其他属性。
  • #[target_feature]: 指定使用的 CPU 特性。

3. 函数和类型处理属性

这些属性用于函数和类型处理。

  • #[must_use]: 标记返回值必须被使用。
  • #[deprecated] 和 #[deprecated(since)]: 标记弃用的函数或类型。
  • #[panic_handler]: 自定义 panic 处理函数。
  • #[global_allocator]: 指定全局内存分配器。
  • #[proc_macro]: 定义过程宏。

4. 平台和外部接口属性

这些属性用于平台特定和外部接口。

  • #[link]: 链接外部库。
  • #[repr(transparent)]: 指定类型的布局与单个字段完全相同。
  • #[cfg(target_arch)]: 根据目标架构选择性地编译代码。

5. 自定义属性宏

自定义属性宏允许创建自定义的编译时代码生成逻辑。

  • 自定义属性宏的实现使用 proc_macro crate,可以定义各种复杂的代码转换和生成逻辑,对于元编程非常有用。

这些属性和更多的特性使得 Rust 成为一个非常灵活和强大的编程语言,可以根据不同的需求和场景进行高度定制和优化。如果你有特定的属性或需求,也可以考虑使用过程宏来创建定制的属性和代码生成逻辑。

Last Updated:
Contributors: rosendo
Prev
add
Next
cargo issue