mozilla / mozilla/cbindgen

Use `Result` with stable size, alignment, and ABI guarantees ?

Open
#1,035 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

enhancement help wanted
Dominant language
Rust
Stars
3k
Forks
386
Avg merge
1h 43m
Merged PRs (30d)
1

Description

👋 Hi folks,

Since RFC 3391 (https://github.com/rust-lang/rfcs/pull/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!

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Rust may_fail example and compare cbindgen 0.27.0 output for Result<(), NonZeroU32> versus Option<NonZeroU32>. Trace how cbindgen represents Result and determine whether stable representation guarantees can be recognized; done means documenting a valid workaround or clearly scoping the required support.

Written by the indexing model from the issue text.

Assessment

Tech stack
rust
Domain
tooling
Issue type
Feature
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.