Rust 编译器错误 E0724:为什么 #[ffi_returns_twice] 不能用于普通函数(以及该特性的现状)
【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust
E0724 是 Rust 编译器历史上针对#[ffi_returns_twice]误用而定义的错误码:该属性只能出现在extern块中的外部函数声明上,用在普通 Rust 函数上会触发诊断。本篇基于rustc_error_codes中的官方错误码文档 E0724.md,完整还原其错误示例与修正方式,并结合当前仓库源码说明该特性已从编译器中移除(rustc_feature的 removed 列表中记录其于 1.78.0 被移除,理由是与 ffi-unwind 项目相关)、符号与错误码的残留状态,帮助读者判断在自己的代码库中遇到 E0724 时应如何处理。
错误码定位与现状:该错误码已不再由编译器发出
E0724 文档 开头即给出了最重要的事实声明:
Note: this error code is no longer emitted by the compiler.
也就是说,E0724 属于"文档保留但编译器不再实际产生"的错误码。这一声明在当前仓库源码中可以得到印证:
特性本身被移除。在 rustc_feature 的 removed.rs 中,可以看到该 feature gate 的正式登记:
/// Allows using `#[ffi_returns_twice]` on foreign functions. (removed, ffi_returns_twice, "1.78.0", Some(58314), Some("being investigated by the ffi-unwind project group"), 120502),其中
removed表明该 unstable feature 已被删除,"1.78.0"记录了移除发生的编译器版本,备注说明其后续工作已交由 ffi-unwind 项目组继续研究。因此,在 1.78.0 及之后的 nightly 上,#![feature(ffi_returns_twice)]本身就无法通过编译,E0724 自然也就失去了触发场景。错误码仍被登记在错误码索引中。在 rustc_error_codes 的 lib.rs 中,
0724依然出现在错误码清单里,保证错误码文档体系(即rustc_error_codes生成的rustc --explain内容)与文档文件保持一一对应。符号仍保留在 symbol 表中。在 rustc_span 的 symbol.rs 中,
ffi_returns_twice仍作为 Symbol 定义存在(第 959 行),这是编译器符号表按历史全量登记、而非按需生成的结果。从源码结构看,这意味着该名字的解析逻辑可能仍以残留形式存在,但它对应的语义检查路径已随 feature 移除而不再向用户产生 E0724 诊断。
原始错误场景复现:误把属性加在普通函数上
E0724 的触发条件,用一句话概括就是:#[ffi_returns_twice]was used on something other than a foreign function declaration(#[ffi_returns_twice]被用在了外部函数声明之外的东西上)。
原始文档给出的错误代码示例如下(该示例在当时的 nightly 下编译失败,故标注为compile_fail):
#![feature(ffi_returns_twice)] #![crate_type = "lib"] #[ffi_returns_twice] // error! pub fn foo() {}问题出在foo是一个普通的 Rust 本地函数,而#[ffi_returns_twice]的语义是针对 FFI 边界的:它标记一个从外部世界调用的函数可能通过两次不同的返回路径控制流(典型场景是 C 风格的可重入/二次返回机制,如异常路径与正常路径各返回一次)。这个语义只对extern声明有意义,用在本地函数上没有对应含义,编译器因此报 E0724。
修正方式:把函数声明放进 extern 块
文档给出的修正版本是把声明移入extern块中,让属性作用于外部函数声明:
#![feature(ffi_returns_twice)] extern "C" { #[ffi_returns_twice] // ok! pub fn foo(); }两个关键点对比如下:
| 要素 | 错误写法 | 正确写法 |
|---|---|---|
| 函数位置 | 模块顶层的普通fn定义 | extern "C" { ... }块内的声明 |
| 函数体 | 有函数体pub fn foo() {} | 无函数体,仅声明pub fn foo(); |
| 属性语义 | 无对应语义,触发 E0724 | 标记该外部函数可能二次返回,合法 |
需要说明的是:由于该 feature 已在 removed.rs 中登记移除,上面的"正确写法"在今天同样无法编译——ffi_returns_twice不再是可用的 feature gate。对于存量代码,实际的处理方式取决于代码来源:
- 如果项目中存在
#![feature(ffi_returns_twice)],在升级到移除该特性的工具链后,该 feature 声明本身会报"未知/已移除 feature"类错误;应删除该 feature 声明及相关属性,或维持使用引入它之前的旧工具链(例如在rust-toolchain中固定版本); - 如果是在排查历史诊断(如在旧日志、旧 issue 讨论中看到 E0724),按本文的"属性只能加在 extern 声明上"这一规则理解即可;
- 若确有需要表达"外部函数可二次返回"的场景,应关注源码备注中提到的 ffi-unwind 项目组的后续进展(见 removed.rs 中的备注 "being investigated by the ffi-unwind project group"),而不是自行拼凑替代写法。
适用前提与限制
- 适用前提:本文所述 E0724 的触发与修正规则对应的是
ffi_returns_twice尚存在的 nightly 时代(移除前);错误码文档 E0724.md 保留了完整的历史语义供rustc --explain E0724查询。 - 限制一:1.78.0 之后,
#[ffi_returns_twice]相关写法不再受编译器支持,任何以该属性为核心的新代码都应视为无效设计。 - 限制二:E0724 文档本身标注"不再由编译器发出",因此它不会出现在当前工具链的实际编译输出中;其价值在于错误码体系的完整性和历史可追溯性。
- 限制三:
ffi_returns_twice的 FFI 语义(外部函数二次返回)涉及跨语言 ABI 与异常/二次返回的底层约定,本文仅基于仓库内文档与源码登记信息说明其定位,不涉及具体 ABI 细节的展开。
小结
E0724 的核心规则只有一条:#[ffi_returns_twice]只能用于extern块内的外部函数声明,误用于本地函数即报错;而更现实的事实是,该 feature 已在 1.78.0 移除(见 rustc_feature/src/removed.rs),错误码本身也进入"只保留文档、不再发出"的状态(见 rustc_error_codes/src/lib.rs 的登记与 E0724.md 的开篇声明)。对开发者而言,遇到 E0724 相关代码的正确动作是清理该属性、固定旧工具链或等待 ffi-unwind 方向的后续方案,而不是在现有 nightly 上继续使用这一已废弃的写法。
【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考