mozilla / uniffi-rs

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

Issue using only a few types from a uniffi dependency in a uniffi library #2282

Open thunderbiscuit opened 1 week ago

thunderbiscuit commented 1 week ago

Hi there. I maintain a uniffi-based library which we have recently broken into two (I'll call them main and low-level-types). Our main library imports some of the types defined in this lower-level library we maintain to offer those lower-level types to other libraries that use uniffi.

I recently found an issue where types defined in my main library that are also defined in the lowe-level-types dependency name clash in Swift because Swift imports all types at once. This lead me to look into the glue code generated for the lower-level dependency, and notice that all types in that library are added to the glue code even though our library only imports some of them.

I'm wondering if I am maybe not configuring the dependency correctly, or if there is something I misunderstood.

Here is an example udl from the lower-level-types library:

interface Script {
  constructor(sequence<u8> raw_output_script); 
  sequence<u8> to_bytes();
};

dictionary OutPoint {
  Txid txid;
  u32 vout;
};

And our use of the Script type in the main library:

[ExternalInterface="core_types_ffi"]
typedef extern Script;

Again our issue is that the OutPoint type will appear in the glue code for the lower-level-types even though we do not need it there. Moreover, because we do have an OutPoint type in the main library, the two Outpoints will clash and runtime tests/code will fail.

mhammond commented 1 week ago

This does seem like a bug, but I can't repro it. eg, in our repo and the following patch:

--- a/fixtures/ext-types/uniffi-one/src/lib.rs
+++ b/fixtures/ext-types/uniffi-one/src/lib.rs
@@ -49,4 +49,9 @@
     fn hello(&self) -> String;
 }

+// A "local" type - not referenced by consumers of our crate,
+// so we test support for it is *not* generated for those consumers.
+#[derive(uniffi::Record)]
+pub struct LocalType {}
+
 uniffi::include_scaffolding!("uniffi-one");

This is your "low level" crate. I run the command cargo test -p uniffi-fixture-ext-types (which is your main crate), and the generated code doesn't reference the type. If I add the following patch:

--- a/fixtures/ext-types/lib/src/lib.rs
+++ b/fixtures/ext-types/lib/src/lib.rs
@@ -203,4 +203,8 @@
     t
 }

+#[uniffi::export]
+fn get_local_type(_t: uniffi_one::LocalType) {
+}
+
 uniffi::include_scaffolding!("ext-types-lib");

(which is your "main" crate, the crate we are testing) it does.