You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中零大小返回类型的FFI安全规则及合规实现问询

需求:定义FFI安全的零大小不变生命周期类型族

需要实现一个零大小类型族Invariant<'a>,满足以下要求:

  • 类型不变地依赖生命周期'a(通过PhantomData<Cell<&'a _>>实现不变性)
  • 严格FFI安全:可以安全地将返回Invariant<'a>的extern "C"函数指针转换为返回()的extern "C"函数指针(对应C端的void返回函数,无需C端存在该零大小类型)
  • 禁止公开构造Invariant<'a>,仅通过类型的存在证明已执行特定操作
  • 定义返回该类型的extern "C"函数时,必须通过#[deny(improper_ctypes_definitions)] lint(基于rustc 1.71.1版本)

尝试1

#[repr(transparent)]
pub struct Try1<'a>(PhantomData<Cell<&'a i32>>);
  • 未通过improper_ctypes_definitions lint,编译器提示:类型仅由PhantomData组成

尝试2

#[repr(transparent)]
pub struct Try2<'a>((), PhantomData<Cell<&'a i32>>);
  • 未通过lint,错误信息:此结构体仅包含零大小字段
  • 原本期望#[repr(transparent)]让结构体表现等同于(),但查阅文档发现,当结构体所有字段均为零大小时,#[repr(transparent)]的行为并未明确规定

尝试3

#[repr(transparent)]
pub struct GenericInvariant<'a, T>(T, PhantomData<Cell<&'a i32>>);
pub type Try3<'a> = GenericInvariant<'a, ()>;
  • 能够通过improper_ctypes_definitions lint,但会引入额外的公开泛型类型GenericInvariant<'a, T>,造成命名空间污染(实际仅需Try3<'a>)

尝试4

#[repr(transparent)]
struct GenericInvariant<'a, T>(T, PhantomData<Cell<&'a i32>>);

#[repr(transparent)]
pub struct Try4<'a>(GenericInvariant<'a, ()>);
  • 未通过lint,错误信息:此结构体仅包含零大小字段,与对#[repr(transparent)]的直觉预期不符

补充测试验证

编写以下测试代码并使用Miri运行:

extern "C" fn f(&()) -> Invariant {
    todo!()
}

let g: extern "C" fn(&()) -> () = unsafe {
    std::mem::transmute(f as extern "C" fn(&()) -> Invariant)
};

g(&())
  • Miri判定所有上述尝试的实现均会导致未定义行为

内容的提问来源于stack exchange,提问作者Mark Saving

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 19:57:50