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

Invalid Kotlin codegen for an error named "Error"

Open rfk opened this issue 2 years ago • 3 comments

The application-services autofill component defines an error enum named "Error", like this:

[Error]
enum Error {
   "OpenDatabaseError", "SqlError", ...
};

When we generate the Kotlin bindings from such a definition, we convert the name "Error" into "Exception" and end up trying to do this:

// Error Error
sealed class Exception: Exception()  {
    // Each variant is a nested class
    class OpenDatabaseException : Exception()
    class SqlException : Exception()
    ...
}

Which doesn't end well. It's confusing, but also it shadows the builtin name Exception which breaks our attempts to subclass Exception in other parts of the helper code.

A workaround is to not do that, changing the autofill component to use a more descriptive name. But this is a bad user experience, and we should either fix the codegen to work in this case, or error out cleanly.

┆Issue is synchronized with this Jira Task ┆Issue Number: UNIFFI-80

rfk avatar Aug 10 '21 03:08 rfk

(Previously we would define an exception named Error, which also shadows a Java buitlin of the same name, but we don't use that name in our generated code anywhere so it never caused us any issues)

rfk avatar Aug 10 '21 03:08 rfk

The way we have currently solved this in our repo is to use a type alias in the rust code and use the type alias name in the udl

type CustomError = custom::Error

This helped us work with minimal changes to our source.

But I agree this is an issue.

artfuldev avatar Oct 15 '21 08:10 artfuldev

A similar error happens with swift as well, and I also had to use a type alias in lib.rs and had to refer to that alias in the UDL to solve this.

enricozb avatar Jun 19 '22 17:06 enricozb

@jhugman It seems like using fully qualified names in the templates for builtin types (e.g. kotlin.Exception) would solve this relatively easily. Is there something I'm missing?

I'm hitting the same issue for code like:

[Enum]
interface ScalarValue {
  String(string value);
  Boolean(bool value);
  // ...
}

which ends up like this

sealed class ScalarValue {
    data class String(val `value`: String) : ScalarValue() // Infinitely recursive type
    data class Boolean(val `value`: Boolean) : ScalarValue()
}

ecstatic-morse avatar Apr 23 '23 04:04 ecstatic-morse