uniffi-rs icon indicating copy to clipboard operation
uniffi-rs copied to clipboard

Support constructors returning `Option<>`?

Open AdinAck opened this issue 1 year ago • 6 comments

It seems that a constructor returning Option<Self> is not supported.

I am embedding Rust in a Swift project and of course Swift has init? so I'm thinking in the UDL it could be constructor?(). Not sure about Python and Kotlin though...

AdinAck avatar Dec 03 '23 17:12 AdinAck

I'd consider "fallible" something which returns Result<T>, not Option<T> - but yeah, this isn't a pattern which will work with all bindings and really isn't what could reasonably be called a "constructor" - can you just use a namespace function for this?

mhammond avatar Dec 04 '23 14:12 mhammond

I am not sure what a namespace function is but for all of my types I made a standalone function called try_new_{type name}(buf: Vec<u8>) -> Option<{type}> and it worked, but it was annoying to have to make standalone functions for each type rather than putting it in an impl block (since associated functions are not supported yet).

AdinAck avatar Dec 04 '23 17:12 AdinAck

@mhammond in Swift init? (which corresponds to Rust -> Option<Self>) is called Failable Initializers

I think those are quite reasonable to have in uniffi!

But even more important to get support for throwing initializers (-> Result<Self, SomeError>) IMO! It is a very common pattern both in Rust (with TryFrom) and in Swift!

Sajjon avatar Dec 22 '23 12:12 Sajjon

Ah seem like the macro #[uniffi::constructor] already supports this, and that we at RDX Works / Radix DLT are using it:

https://github.com/radixdlt/radix-engine-toolkit/blob/main/crates/radix-engine-toolkit-uniffi/src/common/access_rules.rs#L27-L30

Only that it generates a static func rather than on init, which is OK I guess! See: https://github.com/radixdlt/swift-engine-toolkit/blob/main/Sources/EngineToolkit/radix_engine_toolkit_uniffi.swift#L534-L539

Sajjon avatar Dec 22 '23 12:12 Sajjon

No way! I could have sworn the docs explicitly said this was a limitation, but I will try this, thanks! (still want init? but this is a good step in that direction).

AdinAck avatar Dec 22 '23 17:12 AdinAck

Sorry for the confusion - I meant to suggest that what I'd call fallible is indeed Result<Self> rather than Option<Self> - but didn't mean to imply Result<Self> wasn't supported - eg, there's an internal test for it using UDL at https://github.com/mozilla/uniffi-rs/blob/63098f9eb10e35fd5f685de3768a11c7c161c084/fixtures/coverall/src/coverall.udl#L125-L126

I'm still not quite convinced that something called a constructor can return Option<Self> (or Result<Option<Self>>) though, but don't feel that strongly about it, and as mentioned, a work-around is to expose a namespace function rather than a "constructor".

mhammond avatar Dec 22 '23 19:12 mhammond