属性(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 成为一个非常灵活和强大的编程语言,可以根据不同的需求和场景进行高度定制和优化。如果你有特定的属性或需求,也可以考虑使用过程宏来创建定制的属性和代码生成逻辑。