Rust 编译器错误码 E0092 解析:声明未定义原子操作 intrinsic 的历史报错与现行 atomic intrinsic 对照
本文聚焦 Rust 编译器错误码手册中的 E0092(位于 E0092.md),讲解这个"声明了未定义的原子操作函数"报错的来龙去脉、它为何在现行编译器中不再触发,以及如何对照 library/core/src/intrinsics/mod.rs 中当前生效的原子 intrinsic 声明来排查同类问题。读完后可掌握 Rust 错误码归档机制(退役错误码如何保留文档)以及原子操作 intrinsic 的正确命名与签名形态。
1. E0092 是什么:声明了不存在的原子操作函数
E0092 对应一个非常具体的历史编译错误:当你在开启 #![feature(intrinsics)] 后,用 #[rustc_intrinsic] 声明一个原子操作 intrinsic,但函数名不在编译器识别的"原子操作函数"白名单中时,编译器会报出类似 unrecognized atomic operation function 的错误。
原文档给出的错误示例如下(注意其已被标记为不再编译):
#![feature(intrinsics)]
#![allow(internal_features)]
#[rustc_intrinsic]
unsafe fn atomic_foo(); // error: unrecognized atomic operation
// function
文档给出的排查建议只有一句话,但很关键:检查函数名是否拼写错误,所有 intrinsic 函数定义在 Rust 源码的 library/core/src/intrinsics 中。这句话把排查路径从"猜编译器规则"收敛到了"对着标准库声明清单核对",这也是处理一切 intrinsic 命名问题的通用方法。
2. 为什么文档标注"this error code is no longer emitted"
E0092.md 的第一行就写着:
Note: this error code is no longer emitted by the compiler.
这不是文档疏漏,而是 rustc 错误码体系的一条明确维护规则。在 compiler/rustc_error_codes/src/lib.rs 的注释中可以看到这条规范:
Do not remove entries from this list. Instead, just add a note to the corresponding markdown file saying that this error is not emitted by the compiler any more (see E0001.md for an example), and remove all code examples that do not build any more by marking them with
ignore (no longer emitted).
也就是说:错误码编号一旦分配就永不回收,代码示例不再可编译时改用 ignore (no longer emitted) 标记,文档本身保留作为历史档案。E0092 正是按这个流程处理的——0092 仍出现在 error_codes 宏列表中,文档保留但标注退役。
从源码结构看,该错误不再触发与 atomic intrinsic 的声明方式演进有关:早期用户需要手写 #[rustc_intrinsic] 声明并逐名匹配编译器内置的原子操作清单,名字对不上就报 E0092;而当前仓库中,原子操作 intrinsic 已经以完整的泛型签名形式预定义在标准库 core 中(见下文),用户不再通过"声明一个新名字的原子函数"来使用原子操作,因此这条历史检查路径随之退役。
3. 当前有效的原子 intrinsic 清单(对照排查用)
E0092 文档指引的 library/core/src/intrinsics 在仓库中对应 library/core/src/intrinsics/mod.rs,其中每个原子操作都带有 #[rustc_intrinsic] 与 #[rustc_nounwind] 属性,并且给出了完整的类型参数与文档说明。以下是该文件中当前生效的原子操作 intrinsic 全集(摘自源码,行号供定位):
| intrinsic 名称 | 签名要点 | 对应的稳定 API(文档中的说明) |
|---|---|---|
atomic_cxchg |
<T, const ORD_SUCC, const ORD_FAIL>(dst, old, src) -> (T, bool) |
compare_exchange 系列方法 |
atomic_cxchgweak |
同上,但"比较可能虚假失败" | compare_exchange_weak 系列方法 |
atomic_load |
<T, const ORD, const VOLATILE>(src) -> T |
各 atomic 类型的 load |
atomic_store |
<T, const ORD, const VOLATILE>(dst, val) |
各 atomic 类型的 store |
atomic_xchg |
<T, const ORD>(dst, src) -> T |
swap 系列方法 |
atomic_xadd / atomic_xsub |
<T, U, const ORD>(dst, src) -> T |
fetch_add / fetch_sub |
atomic_and / atomic_nand / atomic_or / atomic_xor |
<T, U, const ORD>(dst, src) -> T |
fetch_and / fetch_nand / fetch_or / fetch_xor |
atomic_max / atomic_min |
要求有符号整数类型 | fetch_max / fetch_min |
atomic_umin / atomic_umax |
要求无符号整数类型 | 无符号类型的 fetch_min / fetch_max |
atomic_fence |
<const ORD>() |
atomic::fence |
atomic_singlethreadfence |
<const ORD>() |
atomic::compiler_fence |
例如 atomic_load 的声明:
#[rustc_intrinsic]
#[rustc_nounwind]
pub const unsafe fn atomic_load<T: Copy, const ORD: AtomicOrdering, const VOLATILE: bool>(
src: *const T,
) -> T;
可以观察到两个与旧 E0092 场景直接相关的演进点:
- 原子 intrinsic 不再依赖裸函数名白名单,而是依赖带类型与序(
AtomicOrdering常量参数)的完整签名。T限定为Copy,U与T的约束(整数类型相同、指针类型用usize)也写进了每个函数的文档注释,拼写之外的签名错误会在类型检查阶段被直接发现。 - 每个 atomic intrinsic 的文档注释都显式指向其稳定版本,如 "
The stabilized version of this intrinsic is available on the [atomic] types via theloadmethod"。这印证了文档中"检查函数名"建议的现实意义:绝大多数代码应直接使用std::sync::atomic中的稳定 API,而非自行声明 intrinsic。
4. 实操要点:遇到类似 intrinsic 声明错误如何排查
综合 E0092 的原始指引与当前仓库结构,给出可操作的排查步骤:
- 确认你在做什么:如果你只是想在应用代码里做原子操作,直接使用
std::sync::atomic(如AtomicUsize::load、fetch_add、compare_exchange等),不需要任何#![feature(intrinsics)]。 - 核对函数名与签名:如果你确实在维护/试验 intrinsic 声明(编译器或系统级开发),到 library/core/src/intrinsics/ 目录下逐一对照:
- 函数名是否与上表完全一致(区分
atomic_cxchg与atomic_cxchgweak这类前缀相近的项); - 泛型参数与常量参数(
ORD、VOLATILE等)是否与当前声明形态一致; - 是否遗漏
#[rustc_intrinsic]/#[rustc_nounwind]属性。
- 函数名是否与上表完全一致(区分
- 理解错误码文档的时效性:若你在旧版编译器报错信息或历史 issue 中看到 E0092,但当前工具链中再也无法复现,不必困惑——这正是 lib.rs 所描述的"退役错误码保留文档"机制在起作用,错误码编号永久保留以便旧资料仍可检索。
5. 小结
- E0092 的历史含义:
#[rustc_intrinsic]声明了一个编译器不识别的原子操作函数名,报unrecognized atomic operation function;排查方法是核对 library/core/src/intrinsics/ 中的声明清单。 - 该错误码现已退役,文档按 compiler/rustc_error_codes/src/lib.rs 中"只标注、不删除"的规范保留为历史档案,示例代码标记为
ignore (no longer emitted)。 - 当前仓库中全部 16 个原子 intrinsic(
atomic_cxchg、atomic_load、atomic_store、atomic_xadd等)以带AtomicOrdering常量参数的完整签名预定义于 library/core/src/intrinsics/mod.rs,且每个都注明了对应的稳定 API——这既是理解 E0092 为何消失的钥匙,也是日常开发中直接使用稳定原子操作的依据。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00