-
Notifications
You must be signed in to change notification settings - Fork 214
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
Can't use procmacro derived types as external types #1531
Comments
The issue here is that we're generating this in One solution is to change the generated code to only implement it for the local crate ( The drawback to is that we now need to also generate One complication is external types from a remote crate. In this case, we must use a local type in the My feeling is that crate mode could solve a lot of these issues and provide a very nice experience. I'm not 100% confident that's true though. In the meantime, If there's a need to mix external types, UDL, and proc-macros, then I think we should go with the quick solution I mentioned at the top. |
@jplatte, for this issue, I naively thought that the issue was simply that the recent work Ben did with Re (a), I don't understand what other tags make any sense here - ie, why isn't a bool better here? Re (b), IIUC, this means that there's a "global" However, the downside of this is that it's effectively impossible to expose types from crates which are not UniFFI aware - eg, it would be impossible to expose, say, IIUC, in the current world, it means the consumer would need to "opt in" to this via something like:
but this needs to be done where the enum is defined - someone who wants to consume it might not control the original crate, so would be unable to specify this. However, also IIUC, if procmacros unconditionally used
which is done by the consumer - no change needs to be made to the original enum to enable its consumption by other crates. Doing this seems like it might work and would close the gap between procmacros and UDL and seems easier to understand. I suspect I'm missing something, but is there a good reason to not do this? |
A bool for whether the given impl is global? I don't see how that would be possible.
Yes, that's exactly why the default is to use a generic impl where the tag can be anything. Unfortunately I don't really understand the rest of your comment. I'll add some of my own comments to hopefully move this forward.. First, I don't think Something I've also had it in the back of my mind for a long time but that isn't implemented yet, is that the proc-macros ought to work with conditional compilation for crates that want to conditionally support UniFFI in the same way many crates conditionally support serde. Luckily, Finally, for truly non-cooperative external crates, |
I don't think The current existing enum/record proc-macros generate an However, with a non-cooperative external type, we wouldn't be able to generate In either case I think we need bindings code to handle the external type. I think that provides some more motivation for something like So, maybe we should use a system like this:
What do you think about this? I think you may have an existing multi-crate setup, how disruptive would this change be? |
Yes, |
If One option to handle this would be to remove support for the generic impl. I'm not sure if this is a good idea or not though, I'm hoping to understand how that would impact other UniFFI users. |
Right.. Well I don't foresee needing to import external |
You've convinced me (maybe again?, sorry about going back and forth on this one so much). We should generate the generic impl in all cases, there shouldn't even be a flag. This keeps things simple and consistent. The concern about remote/external types can still be handled:
|
These are some small changes related to a couple PRs: I was hoping to implement the system described in mozilla#1531, but I realized that wouldn't be easy for UDL files. Currently, any `record` or `enum` defined in a UDL file can be a remote type and there's no distiction made between the two. I don't want to put in the work to change that, so I just tried to document things and explain the differences. I realized that we introduced a couple breaking changes in corner cases with external types and documented them: - We discussed this some in mozilla#1516 (comment), but I realize that the `ExternalTypes.rs` template also uses the external type crate name. So I decided that it does deserve a line in the changelog and that line can be worded a bit simpler since it applies to current usage, not only to users that switch to library mode. - I realized we added the requirement for exteranl types type in the crate root when I tried using the new UniFFI code with app-services.
These are some small changes related to a couple PRs: I was hoping to implement the system described in mozilla#1531, but I realized that wouldn't be easy for UDL files. Currently, any `record` or `enum` defined in a UDL file can be a remote type and there's no distiction made between the two. I don't want to put in the work to change that, so I just tried to document things and explain the differences. I realized that we introduced a couple breaking changes in corner cases with external types and documented them: - We discussed this some in mozilla#1516 (comment), but I realize that the `ExternalTypes.rs` template also uses the external type crate name. So I decided that it does deserve a line in the changelog and that line can be worded a bit simpler since it applies to current usage, not only to users that switch to library mode. - I realized we added the requirement for exteranl types type in the crate root when I tried using the new UniFFI code with app-services.
@bendk I tried using your new Does this sound like user error on my part or is that expected? |
I put together a minimal repro here: https://github.com/stan-irl/external-procmacro-repro |
I don't think library mode solves all of these problems, so it's still expected. But thank you for putting together that example. I hope to fix this soon and I'll make sure I check against that. |
Is correct at this point to say that there is no way to return an external UDL defined dict/object from a procmacro defined function? |
Unfortunately, that's the current state. |
no worries. i just wanted to clarify because i've been playing around with these for a couple of days |
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
#1600 should fix this. |
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait.
Moved the FfiConverter implementation for callback interfaces and traits from a declarative macro in `uniffi_core` to a proc-macro in `uniffi_macros`. This offers better `UniFfiTag` handling. Now `FfiConverter` is implemented for all tags for callback interfaces/traits that are wrapped with the proc-macro attributes. This matches the behavior for other types and will help fix mozilla#1531. Changed the object FfiConverter to be inside a proc-macro, rather than using the `Interface` trait. This more flexibility and avoids conflicting impls. For example, this allows for both the objects and trait interface `FfiConverters`s to be implemented on `Arc<T>`. I also think it's nicer with less indirection. One drawback is that libraries can't implement `FfiConverter` on Arc<T> because of the orphan rules. To get around this, I added the `FfiConverterArc` trait. Other changes: - Adding `module_path` to the user type metadata - Added an proc-macro -> proc-macro external type test by copying the ext-types fixture into another one that uses proc macros.
I started looking at this but need to put it down for a while - so throwing this up in case anyone can offer clues.
With the patch at the end, I get:
I doubt this is limited to enums, but this is as far as I got.
┆Issue is synchronized with this Jira Task
┆Issue Number: UNIFFI-257
The text was updated successfully, but these errors were encountered: