Remote types present an issue because we can't implement FFI traits like Lower and Lift on them directly. The workaround is to only implement the FFI trait for the current crate. If another crate wants to use that impl, we need to implement it again by forwarding to the initial implementation.
Historically, UDL and proc-macros have approached this differently which has lead to a lot of extra complexity and confusion. This change aligns them on a common system: By default, we implement traits for all crates (a "blanket impl"). However, users can opt-in to only implementing it for the current crate ("a local impl`)
See the doc changes for a description of the new system.
This required a bunch of changes:
UDL now creates a blanket impl by default. The [Remote] attribute can be used to switch to a local impl.
Proc-macros get the #[remote] attribute macro, which allows users to create a local impl.
Custom types now create a blanket impl by default. The remote parameter can be used to create a local impl.
Added the remote_type! macro to which handles the case where you want to use a remote type and another crate has already created a local impl. This creates a local impl for your crate by forwarding to the other impl. Removed the use_udl_* macros, which were a kludge for doing the same thing.
Added a motivating example where anyhow::Error is used as an error type. Changed the error type bound to Display + Debug rather than Error. For some reason anyhow::Error doesn't actually implement error.
One feature that we've lost in defining callback/trait interfaces using traits defined in a remote crate. I think this is okay because I doubt anyone is using that feature.
There are some docs/changelog/upgrading changes we can make before we release, but that's polish.
Sounds good to me, let's merge now and follow-up on this later.
Remote types present an issue because we can't implement FFI traits like
Lower
andLift
on them directly. The workaround is to only implement the FFI trait for the current crate. If another crate wants to use that impl, we need to implement it again by forwarding to the initial implementation.Historically, UDL and proc-macros have approached this differently which has lead to a lot of extra complexity and confusion. This change aligns them on a common system: By default, we implement traits for all crates (a "blanket impl"). However, users can opt-in to only implementing it for the current crate ("a local impl`)
See the doc changes for a description of the new system.
This required a bunch of changes:
#[remote]
attribute macro, which allows users to create a local impl.remote
parameter can be used to create a local impl.remote_type!
macro to which handles the case where you want to use a remote type and another crate has already created a local impl. This creates a local impl for your crate by forwarding to the other impl. Removed theuse_udl_*
macros, which were a kludge for doing the same thing.Added a motivating example where
anyhow::Error
is used as an error type. Changed the error type bound toDisplay + Debug
rather thanError
. For some reasonanyhow::Error
doesn't actually implement error.One feature that we've lost in defining callback/trait interfaces using traits defined in a remote crate. I think this is okay because I doubt anyone is using that feature.