-
Notifications
You must be signed in to change notification settings - Fork 234
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
Make the proc-macro FfiConverter impls canonical #1464
Conversation
| | ); | ||
| |_^ | ||
| | ||
= note: this error originates in the macro `::uniffi::ffi_converter_flat_error_with_read` (in Nightly builds, run with -Z macro-backtrace for more info) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These error messages aren't very good, but they don't seem any worse that the previous ones.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Took a quick peek at the macro code, this is not a comprehensive review.
uniffi_macros/src/error.rs
Outdated
unsafe impl<T> ::uniffi::FfiConverter<T> for #ident { | ||
::uniffi::ffi_converter_rust_buffer_lift_and_lower!(T); | ||
unsafe impl ::uniffi::FfiConverter<crate::UniFfiTag> for #ident { | ||
::uniffi::ffi_converter_rust_buffer_lift_and_lower!(crate::UniFfiTag); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This changes the code to only implement FfiConverter<crate::UniFffiTag>
, meaning other crates don't get an automatic implementation. I made the change because:
- I want to move the interface
FfiConverter
impls to the generate code, but that can't be a blanket impl sinceArc<T>
is not a local type - The blanket impl doesn't work for remote types and this is currently a requirement for the UDL-based code
- I think we can still make sharing types between crates ergonomic. What if the requirement was that users needed to write
uniffi_use!(external_crate::ExternalType)
? That seems reasonable to me. I hope to have another PR, based on top of this, that implements this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still against changing the default. How about having UDL codegen communicate to the proc-macro that it wants this sort of impl? Something like
#[derive(uniffi::Enum)]
#[uniffi(tag = crate::UniFfiTag)]
enum Foo { ... }
as discussed previously.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can do that.
4925ba9
to
a7d26b1
Compare
}) | ||
} else { | ||
Err(lookahead.error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is my best guess at how to handle more attributes here, please tell me if there's a better way to do this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly what I would have written 👍🏼
a7d26b1
to
c87b2fd
Compare
Pushed an update based on the comments from @jplatte:
|
bfbd1ae
to
99a71e9
Compare
}) | ||
} else { | ||
Err(lookahead.error()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly what I would have written 👍🏼
} | ||
} | ||
|
||
impl TryFrom<AttributeArgs> for FfiConverterTagHandler { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why use syn's Meta
types instead of parsing the attributes using syn::parse::Parse
like elsewhere? I already added a bunch of helpers to make that easier.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is also the reason you didn't do tag = crate::Tag
syntax, because syn::Meta
doesn't support that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried, but couldn't figure out a good way to get from a TokenStream
to an [Attribute]
slicte to use with parse_uniffi_attributes()
. Maybe we could handle this as a follow-up.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I think I can take care of that next week.
99a71e9
to
407aed6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a great improvement, thanks.
= note: required for `Arc<Foo>` to implement `FfiConverter<UniFfiTag>` | ||
= note: this error originates in the attribute macro `uniffi::export` (in Nightly builds, run with -Z macro-backtrace for more info) | ||
|
||
error[E0277]: the trait bound `child::Foo: Interface<UniFfiTag>` is not satisfied |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This change is a little unfortunate as the compiler gave much better diagnostics previously. However, at least it will lists the incorrect type name, so this seems OK if there's really nothing that can be done to improve it (and if you think there might be, maybe open a new issue?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'm missing something because both error messages don't seem very clear to me. I'm happy to work on improving these as a followup though.
/// | ||
/// Like, FfiConverter this has a generic parameter, that's filled in with a type local to the | ||
/// UniFFI consumer crate. | ||
pub trait Interface<UT>: Send + Sync + Sized {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interface
will end up being an unfortunate name in the future if macros end up being the preferred/only way of exposing items. I'm fine with crossing that bridge when we come to it, mainly because I can't quickly think of a better name :)
* 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.
407aed6
to
1d6c384
Compare
FfiConverter
implementations and added standalone macros for that.FfiConverter
implementations from the Askama template code. Instead, the templates now invoke the macros.Arc<T>
impl fromuniffi_core
and made it so we invoke a macro for each interface.The reason for this is:
FfiConverter
, but don't want to implement it twice and test it two different ways.Arc<T>
implementation allows us to customize theFfiConverter
code for each interface. I think this makes Allow Rust traits to be exposed as an interface. #1457 easier.