blob: 8b709600ba2d6bc4e7717f4f6da6015e3d61e75f [file] [view] [edit]
# C++ bindings for Rust `enum`s
A Rust `enum` is mapped to an opaque C++ type.
To receive C++ bindings, the `enum` must be movable in C++. See
[Movable Types](movable_types.md).
## Example
Given the following Rust crate:
```
{{ #include ../../examples/rust/enum/example.rs }}
```
<!-- class:Color -->
Crubit will generate the following bindings:
<!-- Note: Kythe currently indexes this as class `CRUBIT_INTERNAL_RUST_TYPE` because it doesn't have a build rule. -->
```
{{ #include ../../examples/rust/enum/example_generated.h }}
```
<!-- class:CRUBIT_INTERNAL_RUST_TYPE|Color -->
## Why isn't it a C++ `enum`? {#cpp_enum}
A `repr(i32)` or fieldless `repr(C)` `enum` is very similar to a C++ `enum`.
However, Rust enums are exhaustive: any value not explicitly listed in the
`enum` declaration does not exist, and it is
[undefined behavior](https://doc.rust-lang.org/reference/behavior-considered-undefined.html)
to attempt to create one.
C++ `enum`s, in contrast, are "non-exhaustive": a C++ `enum` can have *any*
value supported by the underlying type, even one not listed in the enumerators.
For example, if the above example were a C++ enum, `static_cast<Color>(42)`
would be a valid instance of `Color`, even though neither `Red`, `Blue`, nor
`Green` have that value.
In order to prevent invalid Rust values from being produced by C++, a C++ `enum`
cannot be used to represent a Rust `enum`. Instead, the C++ bindings are a
`struct`, even for fieldless `enum`s.
## C++ movable {#cpp_movable}
To receive C++ bindings, the `enum` must be movable in C++. See
[Movable Types](movable_types.md).
## Enums with payload
Each variant of a Rust `enum` may contain an additional payload (a tuple or a
struct). C++ bindings for Rust `enum`s provide the following ways of working
with an `enum` payload:
* Constructing an `enum` variant with the given payload
by calling a `static` `Make<variant name>` method
(one such method is injected for each of `enum` variants).
The following bugs track future work in this area:
* b/487357254: Constructing variants with a struct payload
* b/489085607: Bindings for constructing enums should be `constexpr`
* TODO(b/262737383): Matching `enum` variants and inspecting their payload.
### Example
Given the following Rust crate:
<!-- b/487357254: Cover struct payload in this example. -->
```
{{ #include ../../examples/rust/enum_with_payload/example.rs }}
```
<!-- class:Color -->
Crubit will generate the following bindings:
<!-- Note: Kythe currently indexes this as class `CRUBIT_INTERNAL_RUST_TYPE` because it doesn't have a build rule. -->
```
{{ #include ../../examples/rust/enum_with_payload/example_generated.h }}
```
<!-- class:CRUBIT_INTERNAL_RUST_TYPE|Color -->