Skip to content

Result / Option of non-null / non-zero types are not FFI-safe #55615

Closed
@gnzlbg

Description

@gnzlbg

I am writing an FFI wrapper for a library that has a function returning an integer error code:

extern "C" fn foo() -> libc::c_int;

The error code of foo is 0 on success and non-zero on error. As suggested by @kennytm , I can do the following dance to obtain a NonZeroU{width} type that's suitable to hold a c_int (note: NonZero<libc::c_int> does not work anymore, and the NonZeroI{width} variants have been removed, so more extra dance is then necessary to convert the unsigned integers to a libc::c_int to be able to compare this with with std error codes like libc::EINVAL):

pub trait NonZeroUInt { type NonZero; }
impl NonZeroUInt for i32 { type NonZero = core::num::NonZeroU32; }
impl NonZeroUInt for i64 { type NonZero = core::num::NonZeroU64; }
impl NonZeroUInt for isize { type NonZero = core::num::NonZeroUsize; }

pub type NonZeroCInt = <libc::c_int as NonZeroUInt>::NonZero;

However, when I then try to use Result in FFI:

extern "C" fn foo() -> Result<(), NonZeroCInt>;

I get an error stating that Result is not FFI-safe. This type is really similar to an Option<&'static 32> which is FFI-safe: an enum with 2 variants, one is zero sized, and the other has niches.

Option<NonNull<*mut i32>>, Option<NonZeroU32>, and Result<(), NonZeroU32> are not, however, FFI safe.

Is this an oversight ?
cc @eddyb @SimonSapin

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-FFIArea: Foreign function interface (FFI)C-feature-requestCategory: A feature request, i.e: not implemented / a PR.T-langRelevant to the language team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions