/overview/status#types outlines the current and future status of Crubit's type support.
In brief, Crubit supports:
float or i32.float* or *const i32, including function pointers.Certain references to C++ or Rust types will not receive Crubit bindings. Some types may only be usable in certain locations due to current Crubit limitations, inherent properties of the type, or both. Supported types fall into one of three categories ranging from “most widely supported” to “most restricted”:
Box<i32> is not C++-movable because it has no nullptr / moved-from representation.std::tuple.| Level of Support | Example | Pass by-reference | Pass by-value | Return by-value | Fields | In Function Pointer Types |
|---|---|---|---|---|---|---|
| ABI Compatible | i32 | Y | Y | Y | Y | Y |
| Layout-compatible C++ type | absl::string_view | Y | if Rust-movable[^1] | if Rust-movable[^2] | Y | N |
| Layout-compatible Rust type | UserDefinedStruct | Y | if C++ movable[^3] | Y | Y | N |
| Bridged | (i32, i32) | N | Y | Y | N | N |
[^1]: See /cpp/classes_and_structs#trivially_relocatable [^2]: See /cpp/classes_and_structs#trivially_relocatable [^3]: See /rust/movable_types
NOTE: All primitive and pointer types are ABI-compatible. However, due to b/369895805, all non-bridged user-defined types are only layout-compatible.
In the following examples, foo receives bindings, but bad_foo will not receive bindings, because while the types it uses in its function signature are supported by Crubit, they are not supported in this particular context.
void foo(int32_t); void foo(void (*)(int32_t)); void foo(Status);
struct LayoutCompatibleType { UnsupportedType field; // or [[no_unique_addres]] int field; or... }; // foo cannot receive bindings, because the function pointer type // does not work with non-ABI-compatible types void bad_foo(void (*)(LayoutCompatibleType));
// foo cannot receive bindings, because bridged types cannot be passed // by reference void bad_foo(const Status&);
pub fn foo(_: i32) {} pub fn foo(_: fn(i32)) {} pub fn foo(_: Status) {}
struct LayoutCompatibleType { field: UnsupportedType } // foo cannot receive bindings, because the function pointer type // does not work with non-ABI-compatible types pub fn bad_foo(_: fn(LayoutCompatibleType)) {}
// foo cannot receive bindings, because bridged types cannot be passed // by reference fn bad_foo(_: &Status) {}
Usually, the mapping of types between languages is bidirectional. For example, a C++ function which returns an int32_t will become a Rust function returning an i32, and vice versa. In some sense, an i32 is an int32_t.
However, in other cases, the mapping is not reversible. C++ and Rust have types or aliases that the other language does not. For example, isize becomes intptr_t, but intptr_t is (on some platforms) the same type as int64_t, and so intptr_t becomes i64.