uniffi-rs
uniffi-rs copied to clipboard
Support for opaque type aliases in generated bindings
With the current type alias implementation, the generated bindings contain transparent type aliases, i.e. new type is not created, its a different name for the underlying type, the alias and the underlying type are the same, and both type alias and the underlying type can be used interchangeably. In Rust, transparent type alias is type A = B;.
It would be useful to also support opaque types, i.e. type alias is an entirely new type, type alias and the underlying type can't be used interchangeably. In Rust, opaque type alias is struct B(A);.
We ran into this in https://github.com/NordSecurity/uniffi-bindgen-cs/issues/40 and https://github.com/NordSecurity/uniffi-bindgen-cs/issues/54, where it would be preferrable to only support opaque type aliases, because transparent type aliases don't work across source files, so transparent type aliases can't be used as External types.
Sorry for being so dense on a Monday morning, but what exactly would you like to see changed here? Or point to exactly what the "current type alias implementation" is? I understand that we do use the Rust newtype idiom when defining external types, but don't see how that impacts what binding generators need to do with them.
On the user guide, on custom types section, the following example is given:
pub struct Handle(i64);
On Python, this is generated as:
# Type alias
Handle = int
Kotlin:
public typealias Handle = Long
Swift:
public typealias Handle = Int64
While on Rust side, we do have a new type. On the generated languages, we have type-aliases. This is undesired on certain API designs were one would like to hide the details.
For instance, suppose you want to expose UUID using uniffi as [Custom] typedef string Uuid. Not any string is a valid UUID. Only those returned by some Uuid generate_v4(); function. And it is very easy to accidentally for the user to provide any string where the original API was expecting an UUID.
For that kind of scenarios, opaque typedef would be more desirable.
The bindgen implementations could make the breaking change of doing opaque typedef anyway. Or alternatively, a new decorator (perhaps [Opaque]) could be added.
It would really be helpful it those were represented as value classes in Kotlin.