-
Couldn't load subscription status.
- Fork 357
Description
👋 Hi folks,
Since RFC 3391 (rust-lang/rfcs#3391) the Result type's documentation has a Representation section that describes conditions where Result<T, E> can have the same size, alignment and ABI guarantees as Option<U>.
E.g.
For example,
NonZeroI32qualifies for theOptionrepresentation guarantees, and()is a zero-sized type with alignment 1, no fields, and it isn’tnon_exhaustive. This means that bothResult<NonZeroI32, ()>andResult<(), NonZeroI32>have the same size, alignment, and ABI guarantees asOption<NonZeroI32>. The only difference is the implied semantics:
Option<NonZeroI32>is “a non-zero i32 might be present”
Result<NonZeroI32, ()>is “a non-zero i32 success result, if any”
Result<(), NonZeroI32>is “a non-zero i32 error result, if any”
I'm trying to lean on this guarantee to implement FFI for a Rust function that wants to use the implied semantics of returning Result<(), NonZeroU32> to mean "a non-zero u32 error result, if any":
pub const MAY_FAIL_ARG_ZERO_ERR: u32 = 99;
#[no_mangle]
extern "C" fn may_fail(arg: u32) -> Result<(), NonZeroU32> {
match arg == 0 {
true => Err(NonZeroU32::new(MAY_FAIL_ARG_ZERO_ERR).unwrap()),
false => Ok(()),
}
}This code compiles, and generates no warnings about unsafe FFI type usage with rust stable.
However, the cbindgen (0.27.0) result is not what I expect:
#define MAY_FAIL_ARG_ZERO_ERR 99
typedef struct Result_u32 Result_u32;
struct Result_u32 may_fail(uint32_t arg);If I change may_fail to return Option<NonZeroU32>, I get the results I expected, but I've lost the implied semantics I want to maintain on the Rust-side:
#define MAY_FAIL_ARG_ZERO_ERR 99
uint32_t may_fail(uint32_t arg);Is there a workaround I could use to get cbindgen to play nice with "stable representation" Result instances? Is my understanding flawed in some other way?
Thanks!