matrix-org / matrix-rust-sdk

Matrix Client-Server SDK for Rust
Apache License 2.0
1.26k stars 246 forks source link

Propagate docstrings over the FFI #1534

Open poljar opened 1 year ago

poljar commented 1 year ago

We have a bunch of documentation, while not being perfect, is usable enough over at the matrix-sdk crate.

Sadly over after crossing the FFI boundary people on the Swift or Kotlin side of things won't see any of our docs. This will be the case even if we document the Uniffi based bindings.

Furthermore, it would be quite annoying to have to document things twice, once in the matrix-sdk crate, and once in the bindings.

A solution to this problem could be a uniffi macro that takes the docstring from another method and re-exposes it over the FFI. This would mean that the types wouldn't necessarily be the same, i.e. the Rust type bool would not be translated to Boolean on the Kotlin side. I think that this would be a tolerable situation.

The macro could look something like:


// `uniffi_docs` takes the docstring of the inner `Bar` struct and re-exposes it
// over the FFI.
#[uniffi_docs(transparent)]
struct Foo(Bar);

impl Foo {
    // `uniffi_docs` takes the docstring of explicitly defined `Bar::set_bar`
    // method.
    #[uniffi_docs(Bar::set_bar)]
    fn set_foo(&mut self) {
        self.0.set_bar()
    }

    // `uniffi_docs` takes the docstring of method with the same name defined on
    // the inner `Bar` struct.
    #[uniffi_docs(transparent)]
    fn get_x(&self) -> bool {
        self.0.get_x()
    }
}
jplatte commented 1 year ago

This is not possible, the macro can't access the docs of another item. What we could potentially do is use #[doc = include_str!("file.md")] to deduplicate, which should work as long as the bindings are never published to crates.io.

Theoretically it is possible with more macro attributes, placed on the items that hold the actual documentation, but it would get really really messy so I'm not sure about that.

poljar commented 1 year ago

This is not possible, the macro can't access the docs of another item. What we could potentially do is use #[doc = include_str!("file.md")] to deduplicate

I suggested this to @Hywan if the former is not possible, though he seemed to prefer the former. Not sure if he had some idea to make this work or if he's aware of the trouble.

jplatte commented 1 year ago

I think what would be the absolute best solution is making the UniFFI proc-macros powerful enough that you no longer need external binding crates that wrap the main crate at all, and can just put uniffi attributes on the regular Rust API to expose it to other languages, including documentation. But that's a ton of work.

Hywan commented 1 year ago

I'll work on that in UniFFI. I self-assign this issue to myself so that I don't forget :-).