惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

A
Arctic Wolf
博客园 - 聂微东
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
小众软件
小众软件
V
Visual Studio Blog
博客园 - 三生石上(FineUI控件)
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
The Cloudflare Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The GitHub Blog
The GitHub Blog
Y
Y Combinator Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
L
LangChain Blog
A
About on SuperTechFans
阮一峰的网络日志
阮一峰的网络日志
I
Intezer
T
The Blog of Author Tim Ferriss
Security Latest
Security Latest
C
CXSECURITY Database RSS Feed - CXSecurity.com
Know Your Adversary
Know Your Adversary
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
P
Palo Alto Networks Blog
Scott Helme
Scott Helme
S
Secure Thoughts
Spread Privacy
Spread Privacy
T
Threat Research - Cisco Blogs
Attack and Defense Labs
Attack and Defense Labs
P
Privacy & Cybersecurity Law Blog
O
OpenAI News
H
Heimdal Security Blog
www.infosecurity-magazine.com
www.infosecurity-magazine.com
Help Net Security
Help Net Security
C
Cyber Attacks, Cyber Crime and Cyber Security
Blog — PlanetScale
Blog — PlanetScale
GbyAI
GbyAI
G
Google Developers Blog
博客园 - Franky
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
Kaspersky official blog
Recent Commits to openclaw:main
Recent Commits to openclaw:main
T
Tor Project blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
Tenable Blog
Google Online Security Blog
Google Online Security Blog
PCI Perspectives
PCI Perspectives

博客园 - PKICA

博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 博文阅读密码验证 - 博客园 rust线程-std::thread::park和unpark 配合Builder实现轻量级的线程挂起与唤醒 rust自定义线程属性std::thread::Builder rust线程 rust关联函数 rust高并发设计实践进阶 rust高并发设计实践 rust性能优化与安全边界 联合体union在rust和C语言中有什么区别 rust并发与异步编程 如何预防rust不良的代码设计总结 rust类型系统与零成本抽象 rust内存模型 告别大显存依赖!用 Rust 新一代深度学习框架 Burn 打造纯 CPU 文本分类推理引擎 编译配置解答 git实用命令 rust底层设计理念值得注意的几个地方总结 rust可变引用作为函数参数的机理详解 Rust内存重解释transmute C与Rust类型映射 Rust FFI 安全抽象范式 rust延迟初始化原语 rust重借用机制与原理 rust参数传递模型 汇编语言语法详解 gdb汇编调试 gdb-pwndbg的安装与使用指南 gdb调试插件gef C语言thread_local linux系统readelf命令使用指南 gcore转储进程内存 gdb查看命令 RGB与YUV颜色编码的区别 Rust原子类型 C++ STL求两个集合交集差集 gdb调试集锦 ubuntu24.0.4使用root用户登录 ubuntu24.0.4输入密码后跳回登录界面 AI内存压缩技术TurboQuant及存疑 ubuntu切换到指定内核版本 在没有顶级科技大佬直接背书的情况下deepseek为啥能够异军突起? HuggingFace和deepseek的关系 当前主流AI大模型 Rust写时克隆Cow系列2
rust类型系统标记
PKICA · 2026-07-21 · via 博客园 - PKICA

在 Rust 中,“类型系统标记”(Type System Markers)或 标记 trait(Marker Traits) 是一种非常独特的语言特性。

它们是一类内部没有任何方法(Method)或关联类型(Associated Types)的空 Trait。它们的存在不是为了提供具体的代码功能,而是像一个个“标签”贴在类型上,明确告知编译器该类型具备某些特殊的内存或并发属性。

以下为系统拆解 Rust 类型系统中的 4 类核心标记,以及它们如何协助编译器保障代码安全:


一、 核心四大内置标记 Trait (OIBIT)

这四个标记最广为人知,它们属于“自动 Trait”(Auto Traits),由编译器根据结构体内字段的属性自动“继承”,不需要你手动去实现。

1. Send —— 跨线程所有权转移标记

  • 含义:如果一个类型实现了 Send,意味着它的所有权可以安全地从一个线程传递到另一个线程。
  • 典型代表:几乎所有独占或基本类型(如 i32, String, Box<T>)都是 Send
  • 反例:裸指针 *mut T 不是 Send,因为跨线程操作裸指针极易引发数据竞争。

2. Sync —— 跨线程并发引用标记

  • 含义:如果一个类型实现了 Sync,意味着多个线程可以同时持有它的不安全/安全引用(&T)。
  • 规则判定:如果 &TSend,那么 T 就是 Sync
  • 典型代表:原子操作类型 AtomicBool、带互斥锁的包装类 Mutex<T>
  • 反例:Rc<T>(引用计数器)。由于内部的非原子计数加减未加锁,多线程共享引用会导致计数错乱,因此它既不是 Send 也不是 Sync

3. Copy —— 内存按位复制标记

  • 含义:改变赋值语义。通常 Rust 赋值是“移动(Move)”所有权,但贴上 Copy 标签后,赋值或传参会触发隐式的内存按位复制(Bitwise Copy,等同于 C 语言的 memcpy)。
  • 前提条件:该类型必须先实现 Clone,且其内部绝不能包含任何管理堆内存或资源的智能指针(如 StringBox,否则会导致双重释放 Double Free)。

4. Sized —— 编译期大小确定标记

  • 含义:告知编译器该类型在编译期间其占用的内存字节数是明确固定的。
  • 默认行为:泛型函数如 fn func<T>(arg: T) 默认隐含了 T: Sized 约束。如果是动态大小类型(DST,如 str[u32]),则必须写作 T: ?Sized(表示大小可能不确定)。

二、 逻辑标记:生命周期与虚无标记 (PhantomData)

有时候,你定义了一个泛型结构体,但由于特定的底层设计(如处理 FFI 或裸指针),结构体的内部字段中并没有真正用到这个泛型参数。此时编译器会直接报错:parameter is never used

为了给编译器“贴个假标签”满足类型检查,就需要用到 std::marker::PhantomData(幽灵数据)。

use std::marker::PhantomData;

// 我们在做 C 语言 FFI 时,PowerState 实际上是一个裸指针,但在 Rust 里它想和某个生命周期 'a 绑定
struct PowerState<'a> {
    raw_ptr: *mut std::os::raw::c_void,
    _marker: PhantomData<&'a ()>, // 显式标记:虽然没存引用,但逻辑上告知编译器该结构体受到生命周期 'a 的约束
}
  • PhantomData 占用 0 字节 内存,在编译后会彻底消失。
  • 它纯粹是提供给 Rust 借用检查器(Borrow Checker)的视觉标记,防止你在生命周期结束后继续使用该裸指针。

三、 零大小标记类型(ZST)与状态机

在更高阶的 Rust 架构设计中,标记经常被用作类型状态模式(Type-State Pattern)。通过定义一系列 0 字节的空结构体作为标记,可以在编译期强制约束对象的行为状态。

// 定义一组状态标记
struct Initializing;
struct Connected;
struct Disconnected;

// 状态机结构体
struct NetworkConnection<State> {
    address: String,
    _state: std::marker::PhantomData<State>,
}

impl NetworkConnection<Initializing> {
    // 只有在 Initializing 状态标记下,才能调用 connect 方法
    pub fn connect(self) -> NetworkConnection<Connected> {
        NetworkConnection { address: self.address, _state: PhantomData }
    }
}

这种标记系统让逻辑错误(如“在未连接时发送数据”)直接在编译阶段暴露,而不是在运行时崩溃。


四、 如何手动操控标记?(Negative Impls)

由于像 SendSync 是由编译器自动推导的,如果你用 transmute 包装了一些底层指针,或者想强制让一个原本安全的结构体变成不支持跨线程,可以利用独占写法将其移除:

#![feature(negative_impls)] // 当前需要不稳定特性支持

struct MySensitiveData {
    secret: i32,
}

// 显式告诉编译器:强行剥离该类型的 Send 标记!
impl !Send for MySensitiveData {}

这样一来,一旦有其他开发者尝试把 MySensitiveData 扔进多线程的 thread::spawn 中,Rust 编译器就会直接拒绝编译。

总结

Rust 的类型标记系统是其实现无畏并发(Fearless Concurrency)和内存零成本抽象的基石。它不增加运行负担,而是将原本需要靠程序员口头承诺或文档规范的“线程安全性”、“内存可复制性”,统统转产为编译期死守的类型标签。

结合最开始问到的 transmute 裸指针操作,在使用裸指针时,正是因为裸指针不具备任何默认的标记(非 Send/非 Sync),才迫使我们必须使用 unsafe 并在外层手动为其包装安全的标记组件。

参考资料

rust并发安全特性