mozilla / uniffi-rs

a multi-language bindings generator for rust
https://mozilla.github.io/uniffi-rs/
Mozilla Public License 2.0
2.68k stars 219 forks source link

Override modifier in Kotlin #1286

Open kirillzh opened 2 years ago

kirillzh commented 2 years ago

Consider this UDL interface:

interface Test {
  string to_string();
};

This generates Kotlin code that does not compile because toString() function is missing an override modifier since this is an open, member function declared in the Any class, which all classes implement in Kotlin:

interface Test {
    // This won't compile: 'toString' hides member of supertype 'Any' and needs 'override' modifier
    fun toString(): String
}

Correct way to fix generated Kotlin code is to add missing override modifier:

interface Test {
    override fun toString(): String
}

As far as I can tell, uniffi doesn't currently provide a way to generate override modifier. Would it be reasonable to add support for it, perhaps, with an UDL syntax like this?

interface Test {
  override string to_string();
};

Here's a real use case for this problem: https://github.com/bitcoindevkit/bdk-ffi/pull/154/files#r907940746. Meanwhile, an alternative workaround here is to use different API naming.

┆Issue is synchronized with this Jira Task ┆friendlyId: UNIFFI-177

bendk commented 2 years ago

I don't know how to do this in general, since which functions need override is language-specific. However, a to_string method is very common and it could be nice to support. I think this would mean:

quad commented 2 years ago

@kirillzh Is there any situation in which toString wouldn't need an associated override in Kotlin?

If not, then @bendk, would you accept a PR that adds that behaviour to the Kotlin binding templates?

It would be akin to the existing code to do fixups for things like reserved words.

quad commented 2 years ago

There are only three methods on Kotlin's Any interface:

I strongly suspect that toString is the only reasonable method for an FFI definition to override.

quad commented 2 years ago

(Potential) Implementation notes

  1. Add a function to CodeOracle, perhaps something like fn_name_on_base_class
  2. Implement it for each binding; kotlin will use it, python and swift won't, ruby could but overriding methods is painless in it.
  3. Use fn_name_on_base to add an override as appropriate in:
mhammond commented 2 years ago

I don't have a strong opinion here, but have some contradictory thoughts:

It would be akin to the existing code to do fixups for things like reserved words.

tl;dr, my opinion is best summarized as: