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

Kotlin: Conflicting type names for enum variant and variant data

Open chris13524 opened this issue 11 months ago • 5 comments

We have an enum like so:

#[cfg_attr(feature = "uniffi", derive(uniffi::Enum))]
pub enum SignOutputEnum {
    Signature(Bytes),
    SignOutput(SignOutput),
}

But we get this error:

yttrium.kt:4352:17 Type mismatch: inferred type is uniffi.yttrium.SignOutput but uniffi.yttrium.SignOutputEnum.SignOutput was expected
public object FfiConverterTypeSignOutputEnum : FfiConverterRustBuffer<SignOutputEnum>{
    override fun read(buf: ByteBuffer): SignOutputEnum {
        return when(buf.getInt()) {
            1 -> SignOutputEnum.Signature(
                FfiConverterTypeBytes.read(buf),
                )
            2 -> SignOutputEnum.SignOutput(
                FfiConverterTypeSignOutput.read(buf), // == error on this line ==
                )
            else -> throw RuntimeException("invalid enum value, something is very wrong!!")
        }
    } 
}

We renamed the SignOutput struct to SignOutputObject for now as a workaround, but it would be nice to not have this conflict in the first place as this is a convenient pattern to have the variant data type name match the enum variant name when there are deeply nested types.

We are currently using commit rev e796e00ad150f8b14b61a859a2e8c6497b35074e and have also encountered the same issue on the latest rev, c7c4809ed0e6bb9195b58855cc7cb211eac13290.

chris13524 avatar Jan 14 '25 16:01 chris13524

I think this is a dupe of #1137, even though that issue mentions UDL.

mhammond avatar Jan 14 '25 17:01 mhammond

Turns out this is Kotlin specific, Python and Swift are fine with it.

mhammond avatar Jan 19 '25 02:01 mhammond

Just ran into this for the second or third time! Curious if any plans for a fix

chris13524 avatar Apr 11 '25 01:04 chris13524

No plans, we'd love a PR from experienced Kotlin users though!

mhammond avatar Apr 11 '25 13:04 mhammond

Just had the same problem, to explain the problem in a different way since this might be helpful for others: The Kotlin definition gets generated here https://github.com/mozilla/uniffi-rs/blob/73619b2043c8f6d1b9563a6843ccfa3d633f3196/uniffi_bindgen/src/bindings/kotlin/templates/EnumTemplate.kt#L60 and for the enum posted in this issue it generates a class like this

sealed class SignOutputEnum {
    
    data class Signature(
        val v1: Bytes) : SignOutputEnum() {
        companion object
    }

    data class SignOutput(
        val v1: SignOutput) : SignOutputEnum() {
        companion object
    }

so the problem is that each enum variant is defined as class and the param of it is also a class with the same name SignOutput

I think in theory one might be able to make this work by creating another file and then using a type alias for the class that's used as parameter, but this doesn't seem to be compatible with how the binding is generated (just a single file) The other options I see are:

  1. Modify the name of the enum variant class (only if a param has the same name), for example with the enum class name combined like SignOutputEnumSignOutput or just come up with something new like Variant, so SignOutputVariant. This is a mismatch between Rust and Kotlin and also doesn't look great, but at least it would work out of the box
  2. As Chris mentioned, rename the variant or value on the Rust side
  3. modify the name of the class that's provided as parameter (just listed for completeness, doing that would be bad) But I'm also not a Kotlin dev, so there might be some other way I missed, maybe one can even use the enum type from Kotlin https://kotlinlang.org/docs/enum-classes.html ?

Thoralf-M avatar Jun 11 '25 14:06 Thoralf-M

I haven't looked into the code that generates these files but would it be easier to just always use the fully qualified name? Is this something that would be worth me looking into? @mhammond ?

Like here: https://github.com/mozilla/uniffi-rs/issues/2697#issue-3505250982

praveenperera avatar Oct 11 '25 14:10 praveenperera

but would it be easier to just always use the fully qualified name?

That sounds like it could work. I've no idea how easy that will be, but maybe quite easy.

mhammond avatar Oct 11 '25 18:10 mhammond

@mhammond Opened a PR, it was a pretty small change and I tried it out in my project and its working: https://github.com/mozilla/uniffi-rs/pull/2698

praveenperera avatar Oct 12 '25 14:10 praveenperera