Skip to content

Use Result with stable size, alignment, and ABI guarantees ? #1035

Description

@cpu

👋 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, NonZeroI32 qualifies for the Option representation guarantees, and () is a zero-sized type with alignment 1, no fields, and it isn’t non_exhaustive. This means that both Result<NonZeroI32, ()> and Result<(), NonZeroI32> have the same size, alignment, and ABI guarantees as Option<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!

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Fields

    Priority

    None yet

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions