Skip to content

Feature request: transparent/erased typedefs #967

@scovich

Description

@scovich

Today, cbindgen has special-case handling for certain well-known standard types. For example:

  • NonNull<T> is erased as T*
  • Option<NonNull<T>> is erased as T*
  • Option<fn(i32) -> i64> is erased as int64_t (*)(int32_t)
  • Box<T> is erased as T* (but not in C++)

This is safe because of the semantics of those types (they somehow act transparent, even tho most of them are not actually #[repr(transparent)]).

Meanwhile, cbindgen supports user-defined #[repr(transparent)] structs by erasing them to typedefs:

#[repr(transparent)]
struct Foo(i32)

is (partly) erased to:

typedef int32_t Foo

However, typedefs (whether user-specified or replacing transparent structs) do not mix cleanly with special-case handling. So, for example, the following all cause cbindgen to emit opaque struct definitions for well-known types instead of optimizing them away correctly:

#[repr(transparent)]
struct Foo(NonNull<i32>);
type NullableFoo = Option<Foo>;

type Function = extern "C" fn(i: i32) -> i64;
type NullableFunction = Option<Function>;

This happens because simplify_standard_types only works for... well-known standard types. Users have no way to opt into similar semantics for their own typedefs and transparent structs.

One possible solution (prototyped as #966) is to introduce /// cbindgen:transparent-typedef annotation that causes cbindgen to replace transparent structs and typedefs with their underlying type. This allows the following:

/// cbindgen:transparent-typedef
#[repr(transparent)]
struct Foo(NonNull<i32>);

/// cbindgen:transparent-typedef
type Function = extern "C" fn(i: i32) -> i64;

type NullableFoo = Option<Foo>;
type NullableFunction = Option<Function>;

to export as

typedef i32 *NullableFoo;
typedef int64_t (*NullableFunction)(int32_t);

instead of today's output:

template<typename T = void>
struct Option;

using Foo = int32_t*;
using Function = int64_t(*)(int32_t i);

using NullableFoo = Option<Foo>;
using NullableFunction = Option<Function>;

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions