Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow Rust traits to be exposed as an interface. #1457

Merged
merged 1 commit into from
Apr 30, 2023

Conversation

mhammond
Copy link
Member

This PR allows Rust traits to be exposed as interfaces, including when they have associated types. It supersedes #1308 (the memory leaks discussed there were easy to resolve once the other shoe dropped for me)

Instead of repeating what I hope are comprehensive docs and tests, please see the docs for this, see the new example (and the coveralls fixture exercises them quite thoroughly).

It has required zero changes to the generated bindings and it all fell out quite cleanly IMO. I've also got a POC in application-services for my specific use-case there, and it works perfectly!

Copy link
Contributor

@bendk bendk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very cool and I'm excited to start using it.

I think there's one FfiConverter issue to figure out before we can merge this, but everything else looks good to me.

docs/manual/src/udl/interfaces.md Show resolved Hide resolved
uniffi_bindgen/src/interface/attributes.rs Outdated Show resolved Hide resolved
@@ -999,7 +1007,12 @@ fn convert_type(s: &uniffi_meta::Type) -> Type {
convert_type(key_type).into(),
convert_type(value_type).into(),
),
Ty::ArcObject { object_name } => Type::Object(object_name.clone()),
Ty::ArcObject { object_name } => Type::Object {
// XXX - needs love for traits and associated types.
Copy link
Contributor

@bendk bendk Jan 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this comment line be removed?

uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs Outdated Show resolved Hide resolved
uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs Outdated Show resolved Hide resolved
uniffi_core/src/lib.rs Outdated Show resolved Hide resolved
bendk added a commit to bendk/uniffi-rs that referenced this pull request Jan 31, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Removed the blanket `Arc<T>` impl from `uniffi_core` and made it so we
  invoke a macro for each interface.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* Removing the blanket `Arc<T>` implementation allows us to customize
  the `FfiConverter` code for each interface.  I think this makes mozilla#1457
  easier.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs and add some features to them.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Jan 31, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Removed the blanket `Arc<T>` impl from `uniffi_core` and made it so we
  invoke a macro for each interface.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* Removing the blanket `Arc<T>` implementation allows us to customize
  the `FfiConverter` code for each interface.  I think this makes mozilla#1457
  easier.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs and add some features to them.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Jan 31, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Jan 31, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 1, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 1, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 2, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 2, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 3, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
bendk added a commit to bendk/uniffi-rs that referenced this pull request Feb 7, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
zduny pushed a commit to zduny/uniffi-rs that referenced this pull request Feb 10, 2023
* Split out the proc-macro code to generate `FfiConverter`
  implementations and added standalone macros for that.
* Removed the `FfiConverter` implementations from the Askama template
  code.  Instead, the templates now invoke the macros.
* Made the blanket `Arc<T>` impl in `uniffi_core` depend on a separate
  `Interface` trait that gets defined by macros.
* Added attribute to generate a `try_lift` method for flat errors.  This
  is required to support callback interface errors.

The reason for this is:

* I want to add some more functionality to `FfiConverter`, but don't
  want to implement it twice and test it two different ways.
* The Interface trait allows us to customize the `Arc<T>`
  implementation.  I plan to push some code that takes advantage of
  this and I also think it could be useful for mozilla#1457.
* Everything goes through one code path, which should give us some more
  confidence as we migrate to proc-macros.  This change caused me to fix
  some bugs with the macro-code and add some features.
@mhammond mhammond force-pushed the traits-types branch 2 times, most recently from b93fcb4 to d44dc2c Compare March 16, 2023 07:30
@mhammond
Copy link
Member Author

This seems so so close - cargo test -p uniffi-example-traits works, but somehow it has broken most other tests - eg, cargo test -p uniffi-fixture-coverall is failing with errors for plain old structs, eg:

error[E0277]: the trait bound `Patch: Interface<UniFfiTag>` is not satisfied
   --> /mnt/c/src/moz/uniffi-rs/target/debug/build/uniffi-fixture-coverall-82c9c761f5ae2c4d/out/coverall.uniffi.rs:166:1
    |
166 | #[::uniffi::ffi_converter_record(tag = crate::UniFfiTag)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Interface<UniFfiTag>` is not implemented for `Patch`
    |

Which confuses me. Out of time for today, but if anyone has a clue please share it with me :)

@mhammond mhammond force-pushed the traits-types branch 2 times, most recently from 37431e7 to edf92de Compare March 16, 2023 23:29
@mhammond mhammond marked this pull request as draft March 16, 2023 23:41
@mhammond mhammond force-pushed the traits-types branch 2 times, most recently from f73f4bc to 0dec0a6 Compare March 17, 2023 03:02
@mhammond
Copy link
Member Author

So this all works and now uses a macro to implement FfiConverter - however, it's a bit different from how objects are done and I haven't even tried to support traits with proc-macros yet as I still need to understand how that works for structs! But it does seem to be in a fairly good place.

@mhammond mhammond force-pushed the traits-types branch 2 times, most recently from dcf9e41 to b77c626 Compare March 17, 2023 03:06
@badboy badboy mentioned this pull request Mar 22, 2023
Copy link
Contributor

@bendk bendk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks great to me. I left a couple of small bikeshedding comments, but nothing big. I'd be happy to merge this as-is.

uniffi_bindgen/src/interface/object.rs Outdated Show resolved Hide resolved
uniffi_bindgen/src/scaffolding/templates/ObjectTemplate.rs Outdated Show resolved Hide resolved
@mhammond mhammond force-pushed the traits-types branch 3 times, most recently from b380a52 to 73f2428 Compare April 24, 2023 22:14
@mhammond mhammond marked this pull request as ready for review April 24, 2023 22:14
Copy link
Member Author

@mhammond mhammond left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is ready to roll! Ben already approved it, but I think it's worth taking another look given the number of changes which happened underneath me since the last version.

/// an object with the given name.
/// Includes `r#`, traits get a leading `dyn`. If we ever supported associated types, then
/// this would also include them.
pub fn rust_name_for(&self, name: &str) -> String {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems oddly named and vaguely mis-placed, but all other names and places seem worse :)

@mhammond mhammond merged commit b982143 into mozilla:main Apr 30, 2023
@mhammond mhammond deleted the traits-types branch April 30, 2023 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants