From ef1ed252fa2c7d6d7b71a88c6e4211f48f66c16d Mon Sep 17 00:00:00 2001 From: Mark Hammond Date: Sun, 5 Nov 2023 17:13:06 -0500 Subject: [PATCH] working except for custom types --- examples/custom-types/src/lib.rs | 5 + fixtures/metadata/src/lib.rs | 2 - fixtures/metadata/src/tests.rs | 3 +- .../reexport-scaffolding-macro/src/lib.rs | 6 +- uniffi/tests/ui/proc_macro_arc.rs | 3 - .../src/bindings/kotlin/templates/Types.kt | 2 +- .../src/bindings/python/templates/Types.py | 2 +- uniffi_bindgen/src/interface/mod.rs | 22 ---- uniffi_bindgen/src/scaffolding/mod.rs | 9 +- .../templates/CallbackInterfaceTemplate.rs | 4 +- .../templates/ExternalTypesTemplate.rs | 14 --- uniffi_core/src/ffi/callbackinterface.rs | 6 +- uniffi_core/src/ffi/rustcalls.rs | 16 +-- uniffi_core/src/ffi/rustfuture/future.rs | 42 +++---- uniffi_core/src/ffi/rustfuture/mod.rs | 8 +- uniffi_core/src/ffi/rustfuture/tests.rs | 20 +--- uniffi_core/src/ffi_converter_impls.rs | 107 +++++++++--------- uniffi_core/src/ffi_converter_traits.rs | 91 +++++++-------- uniffi_core/src/lib.rs | 98 ++-------------- uniffi_macros/src/custom.rs | 12 +- uniffi_macros/src/enum_.rs | 6 +- uniffi_macros/src/error.rs | 10 +- .../src/export/callback_interface.rs | 6 +- uniffi_macros/src/export/scaffolding.rs | 6 +- uniffi_macros/src/export/trait_interface.rs | 4 +- uniffi_macros/src/fnsig.rs | 16 +-- uniffi_macros/src/lib.rs | 27 +---- uniffi_macros/src/object.rs | 4 +- uniffi_macros/src/record.rs | 6 +- uniffi_macros/src/setup_scaffolding.rs | 6 +- uniffi_macros/src/util.rs | 30 ++--- uniffi_meta/src/group.rs | 5 - uniffi_meta/src/types.rs | 1 - uniffi_udl/src/finder.rs | 2 - 34 files changed, 207 insertions(+), 394 deletions(-) diff --git a/examples/custom-types/src/lib.rs b/examples/custom-types/src/lib.rs index 55c502cc5a..63db6bb1b8 100644 --- a/examples/custom-types/src/lib.rs +++ b/examples/custom-types/src/lib.rs @@ -118,4 +118,9 @@ pub fn get_example_custom_type() -> ExampleCustomType { ExampleCustomType("abadidea".to_string()) } +#[uniffi::export] +pub fn get_url(url: Option) -> Url { + url.unwrap_or_else(|| Url::parse("https://mozilla.org").unwrap()) +} + uniffi::include_scaffolding!("custom-types"); diff --git a/fixtures/metadata/src/lib.rs b/fixtures/metadata/src/lib.rs index 517f906304..c562e691b3 100644 --- a/fixtures/metadata/src/lib.rs +++ b/fixtures/metadata/src/lib.rs @@ -7,5 +7,3 @@ /// on all the functionality. #[cfg(test)] mod tests; - -pub struct UniFfiTag; diff --git a/fixtures/metadata/src/tests.rs b/fixtures/metadata/src/tests.rs index 8cf578cf4b..81f4c88922 100644 --- a/fixtures/metadata/src/tests.rs +++ b/fixtures/metadata/src/tests.rs @@ -5,7 +5,6 @@ /// This entire crate is just a set of tests for metadata handling. We use a separate crate /// for testing because the metadata handling is split up between several crates, and no crate /// owns all the functionality. -use crate::UniFfiTag; use uniffi_meta::*; mod person { @@ -90,7 +89,7 @@ mod test_type_ids { use std::sync::Arc; use uniffi_core::Lower; - fn check_type_id>(correct_type: Type) { + fn check_type_id(correct_type: Type) { let buf = &mut T::TYPE_ID_META.as_ref(); assert_eq!( uniffi_meta::read_metadata_type(buf).unwrap(), diff --git a/fixtures/reexport-scaffolding-macro/src/lib.rs b/fixtures/reexport-scaffolding-macro/src/lib.rs index 6bd04f2ccd..33c02f53f1 100644 --- a/fixtures/reexport-scaffolding-macro/src/lib.rs +++ b/fixtures/reexport-scaffolding-macro/src/lib.rs @@ -11,8 +11,6 @@ mod tests { use uniffi::{FfiConverter, ForeignCallback, RustBuffer, RustCallStatus, RustCallStatusCode}; use uniffi_bindgen::ComponentInterface; - struct UniFfiTag; - // Load the dynamic library that was built for this crate. The external functions from // `uniffi_callbacks' and `uniffi_coverall` should be present. pub fn load_library() -> Library { @@ -170,7 +168,7 @@ mod tests { let obj_id = unsafe { coveralls_new( - >::lower("TestName".into()), + ::lower("TestName".into()), &mut call_status, ) }; @@ -179,7 +177,7 @@ mod tests { let name_buf = unsafe { coveralls_get_name(obj_id, &mut call_status) }; assert_eq!(call_status.code, RustCallStatusCode::Success); assert_eq!( - >::try_lift(name_buf).unwrap(), + ::try_lift(name_buf).unwrap(), "TestName" ); diff --git a/uniffi/tests/ui/proc_macro_arc.rs b/uniffi/tests/ui/proc_macro_arc.rs index 9db3376594..80c7c81abd 100644 --- a/uniffi/tests/ui/proc_macro_arc.rs +++ b/uniffi/tests/ui/proc_macro_arc.rs @@ -2,9 +2,6 @@ use std::sync::Arc; fn main() {} -// Normally this is defined by the scaffolding code, manually define it for the UI test -pub struct UniFfiTag; - pub struct Foo; #[uniffi::export] diff --git a/uniffi_bindgen/src/bindings/kotlin/templates/Types.kt b/uniffi_bindgen/src/bindings/kotlin/templates/Types.kt index 5e8847e25f..b252289b33 100644 --- a/uniffi_bindgen/src/bindings/kotlin/templates/Types.kt +++ b/uniffi_bindgen/src/bindings/kotlin/templates/Types.kt @@ -124,7 +124,7 @@ inline fun T.use(block: (T) -> R) = {%- when Type::Custom { module_path, name, builtin } %} {% include "CustomTypeTemplate.kt" %} -{%- when Type::External { module_path, name, namespace, kind, tagged } %} +{%- when Type::External { module_path, name, namespace, kind } %} {% include "ExternalTypeTemplate.kt" %} {%- else %} diff --git a/uniffi_bindgen/src/bindings/python/templates/Types.py b/uniffi_bindgen/src/bindings/python/templates/Types.py index 84afa6bbff..9590c6b4bb 100644 --- a/uniffi_bindgen/src/bindings/python/templates/Types.py +++ b/uniffi_bindgen/src/bindings/python/templates/Types.py @@ -91,7 +91,7 @@ {%- when Type::Custom { name, module_path, builtin } %} {%- include "CustomType.py" %} -{%- when Type::External { name, module_path, namespace, kind, tagged } %} +{%- when Type::External { name, module_path, namespace, kind } %} {%- include "ExternalTemplate.py" %} {%- when Type::ForeignExecutor %} diff --git a/uniffi_bindgen/src/interface/mod.rs b/uniffi_bindgen/src/interface/mod.rs index 6cc15c950a..bdeccda960 100644 --- a/uniffi_bindgen/src/interface/mod.rs +++ b/uniffi_bindgen/src/interface/mod.rs @@ -265,28 +265,6 @@ impl ComponentInterface { self.is_name_used_as_error(&e.name) && (fielded || used_in_foreign_interface) } - /// Get details about all `Type::External` types. - /// Returns an iterator of (name, crate_name, kind) - pub fn iter_external_types( - &self, - ) -> impl Iterator { - self.types.iter_known_types().filter_map(|t| match t { - Type::External { - name, - module_path, - kind, - tagged, - .. - } => Some(( - name, - module_path.split("::").next().unwrap().to_string(), - *kind, - *tagged, - )), - _ => None, - }) - } - /// Get details about all `Type::Custom` types pub fn iter_custom_types(&self) -> impl Iterator { self.types.iter_known_types().filter_map(|t| match t { diff --git a/uniffi_bindgen/src/scaffolding/mod.rs b/uniffi_bindgen/src/scaffolding/mod.rs index f3759cf6fa..092103abf9 100644 --- a/uniffi_bindgen/src/scaffolding/mod.rs +++ b/uniffi_bindgen/src/scaffolding/mod.rs @@ -70,7 +70,7 @@ mod filters { // Map a type to Rust code that specifies the FfiConverter implementation. // - // This outputs something like `>` + // This outputs something like `` pub fn ffi_trait(type_: &Type, trait_name: &str) -> Result { Ok(match type_ { Type::External { @@ -78,12 +78,9 @@ mod filters { kind: ExternalKind::Interface, .. } => { - format!("<::std::sync::Arc as ::uniffi::{trait_name}>") + format!("<::std::sync::Arc as ::uniffi::{trait_name}>") } - _ => format!( - "<{} as ::uniffi::{trait_name}>", - type_rs(type_)? - ), + _ => format!("<{} as ::uniffi::{trait_name}>", type_rs(type_)?), }) } diff --git a/uniffi_bindgen/src/scaffolding/templates/CallbackInterfaceTemplate.rs b/uniffi_bindgen/src/scaffolding/templates/CallbackInterfaceTemplate.rs index 7be11554a4..37a2f454b4 100644 --- a/uniffi_bindgen/src/scaffolding/templates/CallbackInterfaceTemplate.rs +++ b/uniffi_bindgen/src/scaffolding/templates/CallbackInterfaceTemplate.rs @@ -40,7 +40,7 @@ impl {{ trait_impl }} { impl Drop for {{ trait_impl }} { fn drop(&mut self) { - {{ foreign_callback_internals }}.invoke_callback::<(), crate::UniFfiTag>( + {{ foreign_callback_internals }}.invoke_callback::<()>( self.handle, uniffi::IDX_CALLBACK_FREE, Default::default() ) } @@ -74,7 +74,7 @@ impl r#{{ trait_name }} for {{ trait_impl }} { let args_rbuf = uniffi::RustBuffer::from_vec(args_buf); {#- Calling into foreign code. #} - {{ foreign_callback_internals }}.invoke_callback::<{{ meth|return_type }}, crate::UniFfiTag>(self.handle, {{ loop.index }}, args_rbuf) + {{ foreign_callback_internals }}.invoke_callback::<{{ meth|return_type }}>(self.handle, {{ loop.index }}, args_rbuf) } {%- endfor %} } diff --git a/uniffi_bindgen/src/scaffolding/templates/ExternalTypesTemplate.rs b/uniffi_bindgen/src/scaffolding/templates/ExternalTypesTemplate.rs index ade1578897..ea6bc99b6e 100644 --- a/uniffi_bindgen/src/scaffolding/templates/ExternalTypesTemplate.rs +++ b/uniffi_bindgen/src/scaffolding/templates/ExternalTypesTemplate.rs @@ -1,19 +1,5 @@ // Support for external types. -// Types with an external `FfiConverter`... -{% for (name, crate_name, kind, tagged) in ci.iter_external_types() %} -// The FfiConverter for `{{ name }}` is defined in `{{ crate_name }}` -// If it has its existing FfiConverter defined with a UniFFITag, it needs forwarding. -{% if tagged %} -{%- match kind %} -{%- when ExternalKind::DataClass %} -::uniffi::ffi_converter_forward!(r#{{ name }}, ::{{ crate_name|crate_name_rs }}::UniFfiTag, crate::UniFfiTag); -{%- when ExternalKind::Interface %} -::uniffi::ffi_converter_arc_forward!(r#{{ name }}, ::{{ crate_name|crate_name_rs }}::UniFfiTag, crate::UniFfiTag); -{%- endmatch %} -{% endif %} -{%- endfor %} - // We generate support for each Custom Type and the builtin type it uses. {%- for (name, builtin) in ci.iter_custom_types() %} ::uniffi::custom_type!(r#{{ name }}, {{builtin|type_rs}}); diff --git a/uniffi_core/src/ffi/callbackinterface.rs b/uniffi_core/src/ffi/callbackinterface.rs index 7be66880bb..e0278ae128 100644 --- a/uniffi_core/src/ffi/callbackinterface.rs +++ b/uniffi_core/src/ffi/callbackinterface.rs @@ -167,9 +167,9 @@ impl ForeignCallbackInternals { } /// Invoke a callback interface method on the foreign side and return the result - pub fn invoke_callback(&self, handle: u64, method: u32, args: RustBuffer) -> R + pub fn invoke_callback(&self, handle: u64, method: u32, args: RustBuffer) -> R where - R: LiftReturn, + R: LiftReturn, { let mut ret_rbuf = RustBuffer::new(); let callback = self.callback_cell.get(); @@ -189,7 +189,7 @@ impl ForeignCallbackInternals { CallbackResult::Error => R::lift_callback_error(ret_rbuf), CallbackResult::UnexpectedError => { let reason = if !ret_rbuf.is_empty() { - match >::try_lift(ret_rbuf) { + match ::try_lift(ret_rbuf) { Ok(s) => s, Err(e) => { log::error!("{{ trait_name }} Error reading ret_buf: {e}"); diff --git a/uniffi_core/src/ffi/rustcalls.rs b/uniffi_core/src/ffi/rustcalls.rs index 53265393c0..fce80ccc21 100644 --- a/uniffi_core/src/ffi/rustcalls.rs +++ b/uniffi_core/src/ffi/rustcalls.rs @@ -11,7 +11,7 @@ //! - Adapting the result of `Return::lower_return()` into either a return value or an //! exception -use crate::{FfiDefault, Lower, RustBuffer, UniFfiTag}; +use crate::{FfiDefault, Lower, RustBuffer}; use std::mem::MaybeUninit; use std::panic; @@ -66,7 +66,7 @@ impl RustCallStatus { pub fn error(message: impl Into) -> Self { Self { code: RustCallStatusCode::UnexpectedError, - error_buf: MaybeUninit::new(>::lower(message.into())), + error_buf: MaybeUninit::new(::lower(message.into())), } } } @@ -172,7 +172,7 @@ where "Unknown panic!".to_string() }; log::error!("Caught a panic calling rust code: {:?}", message); - >::lower(message) + ::lower(message) })); if let Ok(buf) = message_result { unsafe { @@ -213,31 +213,31 @@ mod test { fn test_rust_call() { let mut status = create_call_status(); let return_value = rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(0)) + as LowerReturn>::lower_return(test_callback(0)) }); assert_eq!(status.code, RustCallStatusCode::Success); assert_eq!(return_value, 100); rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(1)) + as LowerReturn>::lower_return(test_callback(1)) }); assert_eq!(status.code, RustCallStatusCode::Error); unsafe { assert_eq!( - >::try_lift(status.error_buf.assume_init()).unwrap(), + ::try_lift(status.error_buf.assume_init()).unwrap(), TestError("Error".to_owned()) ); } let mut status = create_call_status(); rust_call(&mut status, || { - as LowerReturn>::lower_return(test_callback(2)) + as LowerReturn>::lower_return(test_callback(2)) }); assert_eq!(status.code, RustCallStatusCode::UnexpectedError); unsafe { assert_eq!( - >::try_lift(status.error_buf.assume_init()).unwrap(), + ::try_lift(status.error_buf.assume_init()).unwrap(), "Unexpected value: 2" ); } diff --git a/uniffi_core/src/ffi/rustfuture/future.rs b/uniffi_core/src/ffi/rustfuture/future.rs index fa53726389..2ff39ae1a9 100644 --- a/uniffi_core/src/ffi/rustfuture/future.rs +++ b/uniffi_core/src/ffi/rustfuture/future.rs @@ -89,12 +89,11 @@ use super::{RustFutureContinuationCallback, RustFuturePoll, Scheduler}; use crate::{rust_call_with_out_status, FfiDefault, LowerReturn, RustCallStatus}; /// Wraps the actual future we're polling -struct WrappedFuture +struct WrappedFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { // Note: this could be a single enum, but that would make it easy to mess up the future pinning // guarantee. For example you might want to call `std::mem::take()` to try to get the result, @@ -103,12 +102,11 @@ where result: Option>, } -impl WrappedFuture +impl WrappedFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { fn new(future: F) -> Self { Self { @@ -182,40 +180,38 @@ where // // Rust will not mark it Send by default when T::ReturnType is a raw pointer. This is promising // that we will treat the raw pointer properly, for example by not returning it twice. -unsafe impl Send for WrappedFuture +unsafe impl Send for WrappedFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { } /// Future that the foreign code is awaiting -pub(super) struct RustFuture +pub(super) struct RustFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { // This Mutex should never block if our code is working correctly, since there should not be // multiple threads calling [Self::poll] and/or [Self::complete] at the same time. - future: Mutex>, + future: Mutex>, continuation_data: Mutex, // UT is used as the generic parameter for [LowerReturn]. // Let's model this with PhantomData as a function that inputs a UT value. - _phantom: PhantomData ()>, + // ???? + _phantom: PhantomData ()>, } -impl RustFuture +impl RustFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { - pub(super) fn new(future: F, _tag: UT) -> Arc { + pub(super) fn new(future: F) -> Arc { Arc::new(Self { future: Mutex::new(WrappedFuture::new(future)), continuation_data: Mutex::new(Scheduler::new()), @@ -260,12 +256,11 @@ where } } -impl Wake for RustFuture +impl Wake for RustFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { fn wake(self: Arc) { self.deref().wake() @@ -295,12 +290,11 @@ pub trait RustFutureFfi { fn ffi_free(self: Arc); } -impl RustFutureFfi for RustFuture +impl RustFutureFfi for RustFuture where // See rust_future_new for an explanation of these trait bounds F: Future + Send + 'static, - T: LowerReturn + Send + 'static, - UT: Send + 'static, + T: LowerReturn + Send + 'static, { fn ffi_poll(self: Arc, callback: RustFutureContinuationCallback, data: *const ()) { self.poll(callback, data) diff --git a/uniffi_core/src/ffi/rustfuture/mod.rs b/uniffi_core/src/ffi/rustfuture/mod.rs index 4aaf013fd5..aa13945b85 100644 --- a/uniffi_core/src/ffi/rustfuture/mod.rs +++ b/uniffi_core/src/ffi/rustfuture/mod.rs @@ -40,7 +40,7 @@ pub struct RustFutureHandle(*const ()); /// /// For each exported async function, UniFFI will create a scaffolding function that uses this to /// create the [RustFutureHandle] to pass to the foreign code. -pub fn rust_future_new(future: F, tag: UT) -> RustFutureHandle +pub fn rust_future_new(future: F) -> RustFutureHandle where // F is the future type returned by the exported async function. It needs to be Send + `static // since it will move between threads for an indeterminate amount of time as the foreign @@ -49,13 +49,11 @@ where F: Future + Send + 'static, // T is the output of the Future. It needs to implement [LowerReturn]. Also it must be Send + // 'static for the same reason as F. - T: LowerReturn + Send + 'static, - // The UniFfiTag ZST. The Send + 'static bound is to keep rustc happy. - UT: Send + 'static, + T: LowerReturn + Send + 'static, { // Create a RustFuture and coerce to `Arc`, which is what we use to // implement the FFI - let future_ffi = RustFuture::new(future, tag) as Arc>; + let future_ffi = RustFuture::new(future) as Arc>; // Box the Arc, to convert the wide pointer into a normal sized pointer so that we can pass it // to the foreign code. let boxed_ffi = Box::new(future_ffi); diff --git a/uniffi_core/src/ffi/rustfuture/tests.rs b/uniffi_core/src/ffi/rustfuture/tests.rs index 1f68085562..02f381feec 100644 --- a/uniffi_core/src/ffi/rustfuture/tests.rs +++ b/uniffi_core/src/ffi/rustfuture/tests.rs @@ -60,7 +60,7 @@ fn channel() -> (Sender, Arc>) { result: None, waker: None, })); - let rust_future = RustFuture::new(Receiver(channel.clone()), crate::UniFfiTag); + let rust_future = RustFuture::new(Receiver(channel.clone())); (Sender(channel), rust_future) } @@ -106,10 +106,7 @@ fn test_success() { // Complete the future let (return_buf, call_status) = complete(rust_future); assert_eq!(call_status.code, RustCallStatusCode::Success); - assert_eq!( - >::try_lift(return_buf).unwrap(), - "All done" - ); + assert_eq!(::try_lift(return_buf).unwrap(), "All done"); } #[test] @@ -128,10 +125,8 @@ fn test_error() { assert_eq!(call_status.code, RustCallStatusCode::Error); unsafe { assert_eq!( - >::try_lift_from_rust_buffer( - call_status.error_buf.assume_init() - ) - .unwrap(), + ::try_lift_from_rust_buffer(call_status.error_buf.assume_init()) + .unwrap(), TestError::from("Something went wrong"), ) } @@ -207,7 +202,7 @@ fn test_wake_during_poll() { Poll::Ready("All done".to_owned()) } }); - let rust_future: Arc> = RustFuture::new(future, crate::UniFfiTag); + let rust_future: Arc> = RustFuture::new(future); let continuation_result = poll(&rust_future); // The continuation function should called immediately assert_eq!(continuation_result.get(), Some(&RustFuturePoll::MaybeReady)); @@ -216,8 +211,5 @@ fn test_wake_during_poll() { assert_eq!(continuation_result.get(), Some(&RustFuturePoll::Ready)); let (return_buf, call_status) = complete(rust_future); assert_eq!(call_status.code, RustCallStatusCode::Success); - assert_eq!( - >::try_lift(return_buf).unwrap(), - "All done" - ); + assert_eq!(::try_lift(return_buf).unwrap(), "All done"); } diff --git a/uniffi_core/src/ffi_converter_impls.rs b/uniffi_core/src/ffi_converter_impls.rs index af18f3873b..3ce6366b90 100644 --- a/uniffi_core/src/ffi_converter_impls.rs +++ b/uniffi_core/src/ffi_converter_impls.rs @@ -12,15 +12,11 @@ /// https://mozilla.github.io/uniffi-rs/internals/lifting_and_lowering.html#code-generation-and-the-fficonverter-trait, /// we use the following system: /// -/// - Each UniFFIed crate defines a unit struct named `UniFfiTag` -/// - We define an `impl FFIConverter for Type` for each type that we want to pass +/// - We define an `impl FFIConverter for Type` for each type that we want to pass /// across the FFI. -/// - When generating the code, we use the `>` impl +/// - When generating the code, we use the `` impl /// to lift/lower/serialize types for a crate. /// -/// This crate needs to implement `FFIConverter` on `UniFfiTag` instances for all UniFFI -/// consumer crates. To do this, it defines blanket impls like `impl FFIConverter for u8`. -/// "UT" means an abitrary `UniFfiTag` type. use crate::{ check_remaining, derive_ffi_traits, ffi_converter_rust_buffer_lift_and_lower, metadata, ConvertError, FfiConverter, ForeignExecutor, Lift, LiftReturn, Lower, LowerReturn, @@ -44,7 +40,7 @@ use std::{ macro_rules! impl_ffi_converter_for_num_primitive { ($T:ty, $type_code:expr) => { paste! { - unsafe impl FfiConverter for $T { + unsafe impl FfiConverter for $T { type FfiType = $T; fn lower(obj: $T) -> Self::FfiType { @@ -85,7 +81,7 @@ impl_ffi_converter_for_num_primitive!(f64, metadata::codes::TYPE_F64); /// /// Booleans are passed as an `i8` in order to avoid problems with handling /// C-compatible boolean values on JVM-based languages. -unsafe impl FfiConverter for bool { +unsafe impl FfiConverter for bool { type FfiType = i8; fn lower(obj: bool) -> Self::FfiType { @@ -101,12 +97,12 @@ unsafe impl FfiConverter for bool { } fn write(obj: bool, buf: &mut Vec) { - buf.put_i8(>::lower(obj)); + buf.put_i8(::lower(obj)); } fn try_read(buf: &mut &[u8]) -> Result { check_remaining(buf, 1)?; - >::try_lift(buf.get_i8()) + ::try_lift(buf.get_i8()) } const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_BOOL); @@ -123,7 +119,7 @@ unsafe impl FfiConverter for bool { /// When serialized in a buffer, strings are represented as a i32 byte length /// followed by utf8-encoded bytes. (It's a signed integer because unsigned types are /// currently experimental in Kotlin). -unsafe impl FfiConverter for String { +unsafe impl FfiConverter for String { type FfiType = RustBuffer; // This returns a struct with a raw pointer to the underlying bytes, so it's very @@ -183,8 +179,8 @@ unsafe impl FfiConverter for String { /// the sign of the seconds portion represents the direction of the offset /// overall. The sign of the seconds portion can then be used to determine /// if the total offset should be added to or subtracted from the unix epoch. -unsafe impl FfiConverter for SystemTime { - ffi_converter_rust_buffer_lift_and_lower!(UT); +unsafe impl FfiConverter for SystemTime { + ffi_converter_rust_buffer_lift_and_lower!(); fn write(obj: SystemTime, buf: &mut Vec) { let mut sign = 1; @@ -228,8 +224,8 @@ unsafe impl FfiConverter for SystemTime { /// magnitude in seconds, and a u32 that indicates the nanosecond portion /// of the magnitude. The nanosecond portion is expected to be between 0 /// and 999,999,999. -unsafe impl FfiConverter for Duration { - ffi_converter_rust_buffer_lift_and_lower!(UT); +unsafe impl FfiConverter for Duration { + ffi_converter_rust_buffer_lift_and_lower!(); fn write(obj: Duration, buf: &mut Vec) { buf.put_u64(obj.as_secs()); @@ -254,7 +250,7 @@ unsafe impl FfiConverter for Duration { // `None` option is represented as a null pointer and the `Some` as a valid pointer, // but that seems more fiddly and less safe in the short term, so it can wait. -unsafe impl> Lower for Option { +unsafe impl Lower for Option { type FfiType = RustBuffer; fn write(obj: Option, buf: &mut Vec) { @@ -275,7 +271,7 @@ unsafe impl> Lower for Option { MetadataBuffer::from_code(metadata::codes::TYPE_OPTION).concat(T::TYPE_ID_META); } -unsafe impl> Lift for Option { +unsafe impl Lift for Option { type FfiType = RustBuffer; fn try_read(buf: &mut &[u8]) -> Result> { @@ -305,7 +301,7 @@ unsafe impl> Lift for Option { // than serializing, and perhaps even pass other vector types using a // similar struct. But that's for future work. -unsafe impl> Lower for Vec { +unsafe impl Lower for Vec { type FfiType = RustBuffer; fn write(obj: Vec, buf: &mut Vec) { @@ -313,7 +309,7 @@ unsafe impl> Lower for Vec { let len = i32::try_from(obj.len()).unwrap(); buf.put_i32(len); // We limit arrays to i32::MAX items for item in obj { - >::write(item, buf); + ::write(item, buf); } } @@ -330,7 +326,7 @@ unsafe impl> Lower for Vec { /// We write a `i32` entries count followed by each entry (string /// key followed by the value) in turn. /// (It's a signed type due to limits of the JVM). -unsafe impl> Lift for Vec { +unsafe impl Lift for Vec { type FfiType = RustBuffer; fn try_read(buf: &mut &[u8]) -> Result> { @@ -338,7 +334,7 @@ unsafe impl> Lift for Vec { let len = usize::try_from(buf.get_i32())?; let mut vec = Vec::with_capacity(len); for _ in 0..len { - vec.push(>::try_read(buf)?) + vec.push(::try_read(buf)?) } Ok(vec) } @@ -351,10 +347,10 @@ unsafe impl> Lift for Vec { MetadataBuffer::from_code(metadata::codes::TYPE_VEC).concat(T::TYPE_ID_META); } -unsafe impl Lower for HashMap +unsafe impl Lower for HashMap where - K: Lower + std::hash::Hash + Eq, - V: Lower, + K: Lower + std::hash::Hash + Eq, + V: Lower, { type FfiType = RustBuffer; @@ -363,8 +359,8 @@ where let len = i32::try_from(obj.len()).unwrap(); buf.put_i32(len); // We limit HashMaps to i32::MAX entries for (key, value) in obj { - >::write(key, buf); - >::write(value, buf); + ::write(key, buf); + ::write(value, buf); } } @@ -377,10 +373,10 @@ where .concat(V::TYPE_ID_META); } -unsafe impl Lift for HashMap +unsafe impl Lift for HashMap where - K: Lift + std::hash::Hash + Eq, - V: Lift, + K: Lift + std::hash::Hash + Eq, + V: Lift, { type FfiType = RustBuffer; @@ -389,8 +385,8 @@ where let len = usize::try_from(buf.get_i32())?; let mut map = HashMap::with_capacity(len); for _ in 0..len { - let key = >::try_read(buf)?; - let value = >::try_read(buf)?; + let key = ::try_read(buf)?; + let value = ::try_read(buf)?; map.insert(key, value); } Ok(map) @@ -410,7 +406,7 @@ where /// These are passed over the FFI as opaque pointer-sized types representing the foreign executor. /// The foreign bindings may use an actual pointer to the executor object, or a usized integer /// handle. -unsafe impl FfiConverter for ForeignExecutor { +unsafe impl FfiConverter for ForeignExecutor { type FfiType = crate::ForeignExecutorHandle; // Passing these back to the foreign bindings is currently not supported @@ -439,7 +435,7 @@ unsafe impl FfiConverter for ForeignExecutor { 8 => buf.get_u64_ne() as usize, n => panic!("Invalid usize width: {n}"), }; - >::try_lift(crate::ForeignExecutorHandle(usize_val as *const ())) + ::try_lift(crate::ForeignExecutorHandle(usize_val as *const ())) } const TYPE_ID_META: MetadataBuffer = @@ -466,28 +462,27 @@ derive_ffi_traits!(blanket ForeignExecutor); // // Note that this means we don't get specialized return handling. For example, if we could return // an `Option>` we would always return that type directly and never throw. -derive_ffi_traits!(impl LowerReturn for Option where Option: Lower); -derive_ffi_traits!(impl LiftReturn for Option where Option: Lift); -derive_ffi_traits!(impl LiftRef for Option where Option: Lift); +derive_ffi_traits!(impl LowerReturn for Option where Option: Lower); +derive_ffi_traits!(impl LiftReturn for Option where Option: Lift); +derive_ffi_traits!(impl LiftRef for Option where Option: Lift); -derive_ffi_traits!(impl LowerReturn for Vec where Vec: Lower); -derive_ffi_traits!(impl LiftReturn for Vec where Vec: Lift); -derive_ffi_traits!(impl LiftRef for Vec where Vec: Lift); +derive_ffi_traits!(impl LowerReturn for Vec where Vec: Lower); +derive_ffi_traits!(impl LiftReturn for Vec where Vec: Lift); +derive_ffi_traits!(impl LiftRef for Vec where Vec: Lift); -derive_ffi_traits!(impl LowerReturn for HashMap where HashMap: Lower); -derive_ffi_traits!(impl LiftReturn for HashMap where HashMap: Lift); -derive_ffi_traits!(impl LiftRef for HashMap where HashMap: Lift); +derive_ffi_traits!(impl LowerReturn for HashMap where HashMap: Lower); +derive_ffi_traits!(impl LiftReturn for HashMap where HashMap: Lift); +derive_ffi_traits!(impl LiftRef for HashMap where HashMap: Lift); // For Arc we derive all the traits, but have to write it all out because we need an unsized T bound -derive_ffi_traits!(impl Lower for Arc where Arc: FfiConverter, T: ?Sized); -derive_ffi_traits!(impl Lift for Arc where Arc: FfiConverter, T: ?Sized); -derive_ffi_traits!(impl LowerReturn for Arc where Arc: Lower, T: ?Sized); -derive_ffi_traits!(impl LiftReturn for Arc where Arc: Lift, T: ?Sized); -derive_ffi_traits!(impl LiftRef for Arc where Arc: Lift, T: ?Sized); - +derive_ffi_traits!(impl Lower for Arc where Arc: FfiConverter, T: ?Sized); +derive_ffi_traits!(impl Lift for Arc where Arc: FfiConverter, T: ?Sized); +derive_ffi_traits!(impl LowerReturn for Arc where Arc: Lower, T: ?Sized); +derive_ffi_traits!(impl LiftReturn for Arc where Arc: Lift, T: ?Sized); +derive_ffi_traits!(impl LiftRef for Arc where Arc: Lift, T: ?Sized); // Implement LowerReturn/LiftReturn for the unit type (void returns) -unsafe impl LowerReturn for () { +unsafe impl LowerReturn for () { type ReturnType = (); fn lower_return(_: ()) -> Result { @@ -497,7 +492,7 @@ unsafe impl LowerReturn for () { const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_UNIT); } -unsafe impl LiftReturn for () { +unsafe impl LiftReturn for () { fn lift_callback_return(_buf: RustBuffer) -> Self {} const TYPE_ID_META: MetadataBuffer = MetadataBuffer::from_code(metadata::codes::TYPE_UNIT); @@ -506,10 +501,10 @@ unsafe impl LiftReturn for () { // Implement LowerReturn/LiftReturn for `Result`. This is where we handle exceptions/Err // results. -unsafe impl LowerReturn for Result +unsafe impl LowerReturn for Result where - R: LowerReturn, - E: Lower + Error + Send + Sync + 'static, + R: LowerReturn, + E: Lower + Error + Send + Sync + 'static, { type ReturnType = R::ReturnType; @@ -532,10 +527,10 @@ where .concat(E::TYPE_ID_META); } -unsafe impl LiftReturn for Result +unsafe impl LiftReturn for Result where - R: LiftReturn, - E: Lift + ConvertError, + R: LiftReturn, + E: Lift + ConvertError, { fn lift_callback_return(buf: RustBuffer) -> Self { Ok(R::lift_callback_return(buf)) diff --git a/uniffi_core/src/ffi_converter_traits.rs b/uniffi_core/src/ffi_converter_traits.rs index 3b5914e32f..cab694212d 100644 --- a/uniffi_core/src/ffi_converter_traits.rs +++ b/uniffi_core/src/ffi_converter_traits.rs @@ -32,11 +32,6 @@ //! * If a type needs special-case handling, like `Result<>` and `()`, we implement the traits //! directly. //! -//! FfiConverter has a generic parameter, that's filled in with a type local to the UniFFI consumer crate. -//! This allows us to work around the Rust orphan rules for remote types. See -//! `https://mozilla.github.io/uniffi-rs/internals/lifting_and_lowering.html#code-generation-and-the-fficonverter-trait` -//! for details. -//! //! ## Safety //! //! All traits are unsafe (implementing it requires `unsafe impl`) because we can't guarantee @@ -66,7 +61,7 @@ use crate::{FfiDefault, MetadataBuffer, Result, RustBuffer, UnexpectedUniFFICall /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait FfiConverter: Sized { +pub unsafe trait FfiConverter: Sized { /// The low-level type used for passing values of this type over the FFI. /// /// This must be a C-compatible type (e.g. a numeric primitive, a `#[repr(C)]` struct) into @@ -146,7 +141,7 @@ pub unsafe trait FfiConverter: Sized { /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait FfiConverterArc: Send + Sync { +pub unsafe trait FfiConverterArc: Send + Sync { type FfiType: FfiDefault; fn lower(obj: Arc) -> Self::FfiType; @@ -157,9 +152,9 @@ pub unsafe trait FfiConverterArc: Send + Sync { const TYPE_ID_META: MetadataBuffer; } -unsafe impl FfiConverter for Arc +unsafe impl FfiConverter for Arc where - T: FfiConverterArc + ?Sized, + T: FfiConverterArc + ?Sized, { type FfiType = T::FfiType; @@ -197,7 +192,7 @@ where /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait Lift: Sized { +pub unsafe trait Lift: Sized { type FfiType; fn try_lift(v: Self::FfiType) -> Result; @@ -233,7 +228,7 @@ pub unsafe trait Lift: Sized { /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait Lower: Sized { +pub unsafe trait Lower: Sized { type FfiType: FfiDefault; fn lower(obj: Self) -> Self::FfiType; @@ -262,7 +257,7 @@ pub unsafe trait Lower: Sized { /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait LowerReturn: Sized { +pub unsafe trait LowerReturn: Sized { /// The type that should be returned by scaffolding functions for this type. /// /// When derived, it's the same as `FfiType`. @@ -301,7 +296,7 @@ pub unsafe trait LowerReturn: Sized { /// or might not match with the corresponding code in the generated foreign-language bindings. /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. -pub unsafe trait LiftReturn: Sized { +pub unsafe trait LiftReturn: Sized { /// Lift a Rust value for a callback interface method result fn lift_callback_return(buf: RustBuffer) -> Self; @@ -343,11 +338,11 @@ pub unsafe trait LiftReturn: Sized { /// These traits should not be used directly, only in generated code, and the generated code should /// have fixture tests to test that everything works correctly together. /// `&T` using the Arc. -pub unsafe trait LiftRef { - type LiftType: Lift + Borrow; +pub unsafe trait LiftRef { + type LiftType: Lift + Borrow; } -pub trait ConvertError: Sized { +pub trait ConvertError: Sized { fn try_convert_unexpected_callback_error(e: UnexpectedUniFFICallbackError) -> Result; } @@ -372,14 +367,15 @@ pub trait ConvertError: Sized { #[allow(clippy::crate_in_macro_def)] macro_rules! derive_ffi_traits { (blanket $ty:ty) => { - $crate::derive_ffi_traits!(impl Lower for $ty); - $crate::derive_ffi_traits!(impl Lift for $ty); - $crate::derive_ffi_traits!(impl LowerReturn for $ty); - $crate::derive_ffi_traits!(impl LiftReturn for $ty); - $crate::derive_ffi_traits!(impl LiftRef for $ty); - $crate::derive_ffi_traits!(impl ConvertError for $ty); + $crate::derive_ffi_traits!(impl Lower for $ty); + $crate::derive_ffi_traits!(impl Lift for $ty); + $crate::derive_ffi_traits!(impl LowerReturn for $ty); + $crate::derive_ffi_traits!(impl LiftReturn for $ty); + $crate::derive_ffi_traits!(impl LiftRef for $ty); + $crate::derive_ffi_traits!(impl ConvertError for $ty); }; +/* (local $ty:ty) => { $crate::derive_ffi_traits!(impl Lower for $ty); $crate::derive_ffi_traits!(impl Lift for $ty); @@ -388,75 +384,76 @@ macro_rules! derive_ffi_traits { $crate::derive_ffi_traits!(impl LiftRef for $ty); $crate::derive_ffi_traits!(impl ConvertError for $ty); }; +*/ - (impl $(<$($generic:ident),*>)? $(::uniffi::)? Lower<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - unsafe impl $(<$($generic),*>)* $crate::Lower<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? Lower for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::Lower for $ty $(where $($where)*)* { - type FfiType = >::FfiType; + type FfiType = ::FfiType; fn lower(obj: Self) -> Self::FfiType { - >::lower(obj) + ::lower(obj) } fn write(obj: Self, buf: &mut ::std::vec::Vec) { - >::write(obj, buf) + ::write(obj, buf) } - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; + const TYPE_ID_META: $crate::MetadataBuffer = ::TYPE_ID_META; } }; - (impl $(<$($generic:ident),*>)? $(::uniffi::)? Lift<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - unsafe impl $(<$($generic),*>)* $crate::Lift<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? Lift for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::Lift for $ty $(where $($where)*)* { - type FfiType = >::FfiType; + type FfiType = ::FfiType; fn try_lift(v: Self::FfiType) -> $crate::deps::anyhow::Result { - >::try_lift(v) + ::try_lift(v) } fn try_read(buf: &mut &[u8]) -> $crate::deps::anyhow::Result { - >::try_read(buf) + ::try_read(buf) } - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; + const TYPE_ID_META: $crate::MetadataBuffer = ::TYPE_ID_META; } }; - (impl $(<$($generic:ident),*>)? $(::uniffi::)? LowerReturn<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - unsafe impl $(<$($generic),*>)* $crate::LowerReturn<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? LowerReturn for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::LowerReturn for $ty $(where $($where)*)* { - type ReturnType = >::FfiType; + type ReturnType = ::FfiType; fn lower_return(obj: Self) -> $crate::deps::anyhow::Result { - Ok(>::lower(obj)) + Ok(::lower(obj)) } - const TYPE_ID_META: $crate::MetadataBuffer =>::TYPE_ID_META; + const TYPE_ID_META: $crate::MetadataBuffer =::TYPE_ID_META; } }; - (impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftReturn<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - unsafe impl $(<$($generic),*>)* $crate::LiftReturn<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftReturn for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::LiftReturn for $ty $(where $($where)*)* { fn lift_callback_return(buf: $crate::RustBuffer) -> Self { - >::try_lift_from_rust_buffer(buf) + ::try_lift_from_rust_buffer(buf) .expect("Error reading callback interface result") } - const TYPE_ID_META: $crate::MetadataBuffer = >::TYPE_ID_META; + const TYPE_ID_META: $crate::MetadataBuffer = ::TYPE_ID_META; } }; - (impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftRef<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - unsafe impl $(<$($generic),*>)* $crate::LiftRef<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? LiftRef for $ty:ty $(where $($where:tt)*)?) => { + unsafe impl $(<$($generic),*>)* $crate::LiftRef for $ty $(where $($where)*)* { type LiftType = Self; } }; - (impl $(<$($generic:ident),*>)? $(::uniffi::)? ConvertError<$ut:path> for $ty:ty $(where $($where:tt)*)?) => { - impl $(<$($generic),*>)* $crate::ConvertError<$ut> for $ty $(where $($where)*)* + (impl $(<$($generic:ident),*>)? $(::uniffi::)? ConvertError for $ty:ty $(where $($where:tt)*)?) => { + impl $(<$($generic),*>)* $crate::ConvertError for $ty $(where $($where)*)* { fn try_convert_unexpected_callback_error(e: $crate::UnexpectedUniFFICallbackError) -> $crate::deps::anyhow::Result { $crate::convert_unexpected_error!(e, $ty) diff --git a/uniffi_core/src/lib.rs b/uniffi_core/src/lib.rs index 9003b08f9b..e6d618d4b3 100644 --- a/uniffi_core/src/lib.rs +++ b/uniffi_core/src/lib.rs @@ -131,9 +131,6 @@ macro_rules! assert_compatible_version { }; } -/// Struct to use when we want to lift/lower/serialize types inside the `uniffi` crate. -struct UniFfiTag; - /// A helper function to ensure we don't read past the end of a buffer. /// /// Rust won't actually let us read past the end of a buffer, but the `Buf` trait does not support @@ -158,19 +155,19 @@ pub fn check_remaining(buf: &[u8], num_bytes: usize) -> Result<()> { /// This macro implements the boilerplate needed to define `lower`, `lift` and `FFIType`. #[macro_export] macro_rules! ffi_converter_rust_buffer_lift_and_lower { - ($uniffi_tag:ty) => { + () => { type FfiType = $crate::RustBuffer; fn lower(v: Self) -> $crate::RustBuffer { let mut buf = ::std::vec::Vec::new(); - >::write(v, &mut buf); + ::write(v, &mut buf); $crate::RustBuffer::from_vec(buf) } fn try_lift(buf: $crate::RustBuffer) -> $crate::Result { let vec = buf.destroy_into_vec(); let mut buf = vec.as_slice(); - let value = >::try_read(&mut buf)?; + let value = ::try_read(&mut buf)?; match $crate::deps::bytes::Buf::remaining(&buf) { 0 => Ok(value), n => $crate::deps::anyhow::bail!( @@ -181,86 +178,17 @@ macro_rules! ffi_converter_rust_buffer_lift_and_lower { }; } -/// Macro to implement `FfiConverter` for a UniFfiTag using a different UniFfiTag -/// -/// This is used for external types -#[macro_export] -macro_rules! ffi_converter_forward { - // Forward a `FfiConverter` implementation - ($T:ty, $existing_impl_tag:ty, $new_impl_tag:ty) => { - ::uniffi::do_ffi_converter_forward!( - FfiConverter, - $T, - $T, - $existing_impl_tag, - $new_impl_tag - ); - - $crate::derive_ffi_traits!(local $T); - }; -} - -/// Macro to implement `FfiConverterArc` for a UniFfiTag using a different UniFfiTag -/// -/// This is used for external types -#[macro_export] -macro_rules! ffi_converter_arc_forward { - ($T:ty, $existing_impl_tag:ty, $new_impl_tag:ty) => { - ::uniffi::do_ffi_converter_forward!( - FfiConverterArc, - ::std::sync::Arc<$T>, - $T, - $existing_impl_tag, - $new_impl_tag - ); - - // Note: no need to call derive_ffi_traits! because there is a blanket impl for all Arc - }; -} - -// Generic code between the two macros above -#[doc(hidden)] -#[macro_export] -macro_rules! do_ffi_converter_forward { - ($trait:ident, $rust_type:ty, $T:ty, $existing_impl_tag:ty, $new_impl_tag:ty) => { - unsafe impl $crate::$trait<$new_impl_tag> for $T { - type FfiType = <$T as $crate::$trait<$existing_impl_tag>>::FfiType; - - fn lower(obj: $rust_type) -> Self::FfiType { - <$T as $crate::$trait<$existing_impl_tag>>::lower(obj) - } - - fn try_lift(v: Self::FfiType) -> $crate::Result<$rust_type> { - <$T as $crate::$trait<$existing_impl_tag>>::try_lift(v) - } - - fn write(obj: $rust_type, buf: &mut Vec) { - <$T as $crate::$trait<$existing_impl_tag>>::write(obj, buf) - } - - fn try_read(buf: &mut &[u8]) -> $crate::Result<$rust_type> { - <$T as $crate::$trait<$existing_impl_tag>>::try_read(buf) - } - - const TYPE_ID_META: ::uniffi::MetadataBuffer = - <$T as $crate::$trait<$existing_impl_tag>>::TYPE_ID_META; - } - }; -} - #[cfg(test)] mod test { - use super::{FfiConverter, UniFfiTag}; + use super::FfiConverter; use std::time::{Duration, SystemTime}; #[test] fn timestamp_roundtrip_post_epoch() { let expected = SystemTime::UNIX_EPOCH + Duration::new(100, 100); let result = - >::try_lift(>::lower(expected)) - .expect("Failed to lift!"); + ::try_lift(::lower(expected)) + .expect("Failed to lift!"); assert_eq!(expected, result) } @@ -268,10 +196,8 @@ mod test { fn timestamp_roundtrip_pre_epoch() { let expected = SystemTime::UNIX_EPOCH - Duration::new(100, 100); let result = - >::try_lift(>::lower(expected)) - .expect("Failed to lift!"); + ::try_lift(::lower(expected)) + .expect("Failed to lift!"); assert_eq!( expected, result, "Expected results after lowering and lifting to be equal" @@ -289,15 +215,15 @@ pub mod test_util { pub struct TestError(pub String); // Use FfiConverter to simplify lifting TestError out of RustBuffer to check it - unsafe impl FfiConverter for TestError { - ffi_converter_rust_buffer_lift_and_lower!(UniFfiTag); + unsafe impl FfiConverter for TestError { + ffi_converter_rust_buffer_lift_and_lower!(); fn write(obj: TestError, buf: &mut Vec) { - >::write(obj.0, buf); + ::write(obj.0, buf); } fn try_read(buf: &mut &[u8]) -> Result { - >::try_read(buf).map(TestError) + ::try_read(buf).map(TestError) } // Use a dummy value here since we don't actually need TYPE_ID_META diff --git a/uniffi_macros/src/custom.rs b/uniffi_macros/src/custom.rs index 9d8e5acde6..c207f4a88a 100644 --- a/uniffi_macros/src/custom.rs +++ b/uniffi_macros/src/custom.rs @@ -25,27 +25,27 @@ pub(crate) fn expand_ffi_converter_custom_type( // Note: the builtin type needs to implement both `Lower` and `Lift'. We use the // `Lower` trait to get the associated type `FfiType` and const `TYPE_ID_META`. These // can't differ between `Lower` and `Lift`. - type FfiType = <#builtin as ::uniffi::Lower>::FfiType; + type FfiType = <#builtin as ::uniffi::Lower>::FfiType; fn lower(obj: #ident ) -> Self::FfiType { - <#builtin as ::uniffi::Lower>::lower(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj)) + <#builtin as ::uniffi::Lower>::lower(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj)) } fn try_lift(v: Self::FfiType) -> uniffi::Result<#ident> { - <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_lift(v)?) + <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_lift(v)?) } fn write(obj: #ident, buf: &mut Vec) { - <#builtin as ::uniffi::Lower>::write(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj), buf); + <#builtin as ::uniffi::Lower>::write(<#ident as crate::UniffiCustomTypeConverter>::from_custom(obj), buf); } fn try_read(buf: &mut &[u8]) -> uniffi::Result<#ident> { - <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_read(buf)?) + <#ident as crate::UniffiCustomTypeConverter>::into_custom(<#builtin as ::uniffi::Lift>::try_read(buf)?) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_CUSTOM) .concat_str(#mod_path) .concat_str(#name) - .concat(<#builtin as ::uniffi::Lower>::TYPE_ID_META); + .concat(<#builtin as ::uniffi::Lower>::TYPE_ID_META); } #derive_ffi_traits diff --git a/uniffi_macros/src/enum_.rs b/uniffi_macros/src/enum_.rs index 32abfa08cc..e3a9514cb3 100644 --- a/uniffi_macros/src/enum_.rs +++ b/uniffi_macros/src/enum_.rs @@ -108,7 +108,7 @@ fn enum_or_error_ffi_converter_impl( quote! { #[automatically_derived] unsafe #impl_spec { - ::uniffi::ffi_converter_rust_buffer_lift_and_lower!(crate::UniFfiTag); + ::uniffi::ffi_converter_rust_buffer_lift_and_lower!(); fn write(obj: Self, buf: &mut ::std::vec::Vec) { #write_impl @@ -132,7 +132,7 @@ fn write_field(f: &Field) -> TokenStream { let ty = &f.ty; quote! { - <#ty as ::uniffi::Lower>::write(#ident, buf); + <#ty as ::uniffi::Lower>::write(#ident, buf); } } @@ -184,7 +184,7 @@ pub fn variant_metadata(enum_: &DataEnum) -> syn::Result> { .concat_value(#fields_len) #( .concat_str(#field_names) - .concat(<#field_types as ::uniffi::Lower>::TYPE_ID_META) + .concat(<#field_types as ::uniffi::Lower>::TYPE_ID_META) // field defaults not yet supported for enums .concat_bool(false) )* diff --git a/uniffi_macros/src/error.rs b/uniffi_macros/src/error.rs index a2ee7cf603..71c47c7fb8 100644 --- a/uniffi_macros/src/error.rs +++ b/uniffi_macros/src/error.rs @@ -102,7 +102,7 @@ fn flat_error_ffi_converter_impl( quote! { Self::#v_ident { .. } => { ::uniffi::deps::bytes::BufMut::put_i32(buf, #idx); - <::std::string::String as ::uniffi::Lower>::write(error_msg, buf); + <::std::string::String as ::uniffi::Lower>::write(error_msg, buf); } } }); @@ -118,7 +118,7 @@ fn flat_error_ffi_converter_impl( } fn lower(obj: Self) -> ::uniffi::RustBuffer { - >::lower_into_rust_buffer(obj) + ::lower_into_rust_buffer(obj) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_ENUM) @@ -150,10 +150,10 @@ fn flat_error_ffi_converter_impl( } fn try_lift(v: ::uniffi::RustBuffer) -> ::uniffi::deps::anyhow::Result { - >::try_lift_from_rust_buffer(v) + ::try_lift_from_rust_buffer(v) } - const TYPE_ID_META: ::uniffi::MetadataBuffer = >::TYPE_ID_META; + const TYPE_ID_META: ::uniffi::MetadataBuffer = ::TYPE_ID_META; } } @@ -178,7 +178,7 @@ fn flat_error_ffi_converter_impl( panic!("Can't lift flat errors") } - const TYPE_ID_META: ::uniffi::MetadataBuffer = >::TYPE_ID_META; + const TYPE_ID_META: ::uniffi::MetadataBuffer = ::TYPE_ID_META; } } }; diff --git a/uniffi_macros/src/export/callback_interface.rs b/uniffi_macros/src/export/callback_interface.rs index 85a8b0663a..c19b3d25be 100644 --- a/uniffi_macros/src/export/callback_interface.rs +++ b/uniffi_macros/src/export/callback_interface.rs @@ -56,7 +56,7 @@ pub(super) fn trait_impl( impl ::std::ops::Drop for #trait_impl_ident { fn drop(&mut self) { - #internals_ident.invoke_callback::<(), crate::UniFfiTag>( + #internals_ident.invoke_callback::<()>( self.handle, uniffi::IDX_CALLBACK_FREE, Default::default() ) } @@ -115,7 +115,7 @@ pub fn ffi_converter_callback_interface_impl( fn try_read(buf: &mut &[u8]) -> ::uniffi::deps::anyhow::Result { use uniffi::deps::bytes::Buf; ::uniffi::check_remaining(buf, 8)?; - >::try_lift(buf.get_u64()) + ::try_lift(buf.get_u64()) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code( @@ -173,7 +173,7 @@ fn gen_method_impl(sig: &FnSignature, internals_ident: &Ident) -> syn::Result(self.handle, #index, uniffi_args_rbuf) + #internals_ident.invoke_callback::<#return_ty>(self.handle, #index, uniffi_args_rbuf) } }) } diff --git a/uniffi_macros/src/export/scaffolding.rs b/uniffi_macros/src/export/scaffolding.rs index d00d8403bd..9bf38c6bc2 100644 --- a/uniffi_macros/src/export/scaffolding.rs +++ b/uniffi_macros/src/export/scaffolding.rs @@ -127,11 +127,11 @@ impl ScaffoldingBits { let ident = &sig.ident; let lift_impl = if is_trait { quote! { - <::std::sync::Arc as ::uniffi::Lift> + <::std::sync::Arc as ::uniffi::Lift> } } else { quote! { - <::std::sync::Arc<#self_ident> as ::uniffi::Lift> + <::std::sync::Arc<#self_ident> as ::uniffi::Lift> } }; let params: Vec<_> = iter::once(quote! { uniffi_self_lowered: #lift_impl::FfiType }) @@ -271,7 +271,6 @@ pub(super) fn gen_ffi_function( Ok(uniffi_args) => { ::uniffi::rust_future_new( async move { #future_expr.await }, - crate::UniFfiTag ) }, Err((arg_name, anyhow_error)) => { @@ -279,7 +278,6 @@ pub(super) fn gen_ffi_function( async move { #return_impl::handle_failed_lift(arg_name, anyhow_error) }, - crate::UniFfiTag, ) }, } diff --git a/uniffi_macros/src/export/trait_interface.rs b/uniffi_macros/src/export/trait_interface.rs index 53a7f78c17..4e9c97c69c 100644 --- a/uniffi_macros/src/export/trait_interface.rs +++ b/uniffi_macros/src/export/trait_interface.rs @@ -108,14 +108,14 @@ pub(crate) fn ffi_converter(mod_path: &str, trait_ident: &Ident, udl_mode: bool) ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::deps::bytes::BufMut::put_u64( buf, - >::lower(obj) as u64, + ::lower(obj) as u64, ); } fn try_read(buf: &mut &[u8]) -> ::uniffi::Result<::std::sync::Arc> { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::check_remaining(buf, 8)?; - >::try_lift( + ::try_lift( ::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) } diff --git a/uniffi_macros/src/fnsig.rs b/uniffi_macros/src/fnsig.rs index 69b6529d1e..ec7ddc0816 100644 --- a/uniffi_macros/src/fnsig.rs +++ b/uniffi_macros/src/fnsig.rs @@ -103,7 +103,7 @@ impl FnSignature { pub fn return_impl(&self) -> TokenStream { let return_ty = &self.return_ty; quote! { - <#return_ty as ::uniffi::LowerReturn> + <#return_ty as ::uniffi::LowerReturn> } } @@ -211,7 +211,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) }), FnKind::Method { self_ident } => { @@ -224,7 +224,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) }) } @@ -239,7 +239,7 @@ impl FnSignature { .concat_bool(#is_async) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) }) } @@ -252,7 +252,7 @@ impl FnSignature { .concat_str(#name) .concat_value(#args_len) #(#arg_metadata_calls)* - .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) + .concat(<#return_ty as ::uniffi::LowerReturn>::TYPE_ID_META) }) } } @@ -389,7 +389,7 @@ impl NamedArg { Self { name: ident_to_string(&ident), ident, - ty: quote! { <#inner as ::uniffi::LiftRef>::LiftType }, + ty: quote! { <#inner as ::uniffi::LiftRef>::LiftType }, ref_type: Some(*inner.clone()), } } @@ -404,12 +404,12 @@ impl NamedArg { pub(crate) fn lift_impl(&self) -> TokenStream { let ty = &self.ty; - quote! { <#ty as ::uniffi::Lift> } + quote! { <#ty as ::uniffi::Lift> } } pub(crate) fn lower_impl(&self) -> TokenStream { let ty = &self.ty; - quote! { <#ty as ::uniffi::Lower> } + quote! { <#ty as ::uniffi::Lower> } } /// Generate the parameter for this Arg diff --git a/uniffi_macros/src/lib.rs b/uniffi_macros/src/lib.rs index b7ba86ddc1..84112f5876 100644 --- a/uniffi_macros/src/lib.rs +++ b/uniffi_macros/src/lib.rs @@ -199,21 +199,8 @@ pub fn custom_newtype(tokens: TokenStream) -> TokenStream { // In UDL mode, we don't export the static metadata symbols or generate the checksum // functions. This could be changed, but there doesn't seem to be much benefit at this point. // -// ## The FfiConverter parameter -// -// In UDL-mode, we only implement `FfiConverter` for the local tag (`FfiConverter`) -// -// The reason for this split is remote types, i.e. types defined in remote crates that we -// don't control and therefore can't define a blanket impl on because of the orphan rules. -// -// With UDL, we handle this by only implementing `FfiConverter` for the -// type. This gets around the orphan rules since a local type is in the trait, but requires -// a `uniffi::ffi_converter_forward!` call if the type is used in a second local crate (an -// External typedef). This is natural for UDL-based generation, since you always need to -// define the external type in the UDL file. -// -// With proc-macros this system isn't so natural. Instead, we create a blanket implementation -// for all UT and support for remote types is still TODO. +// ## Blanket implementation +// TODO #[doc(hidden)] #[proc_macro_attribute] @@ -336,10 +323,8 @@ fn use_udl_simple_type(tokens: TokenStream) -> TokenStream { type_ident, .. } = parse_macro_input!(tokens); - quote! { - ::uniffi::ffi_converter_forward!(#type_ident, #crate_ident::UniFfiTag, crate::UniFfiTag); - } - .into() + // XXX + quote! {}.into() } #[proc_macro] @@ -349,9 +334,7 @@ pub fn use_udl_object(tokens: TokenStream) -> TokenStream { type_ident, .. } = parse_macro_input!(tokens); - quote! { - ::uniffi::ffi_converter_arc_forward!(#type_ident, #crate_ident::UniFfiTag, crate::UniFfiTag); - }.into() + quote! {}.into() } /// A helper macro to generate and include component scaffolding. diff --git a/uniffi_macros/src/object.rs b/uniffi_macros/src/object.rs index 697641c829..058482cfe1 100644 --- a/uniffi_macros/src/object.rs +++ b/uniffi_macros/src/object.rs @@ -101,7 +101,7 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { /// function for other types may lead to undefined behaviour. fn write(obj: ::std::sync::Arc, buf: &mut Vec) { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); - ::uniffi::deps::bytes::BufMut::put_u64(buf, >::lower(obj) as u64); + ::uniffi::deps::bytes::BufMut::put_u64(buf, ::lower(obj) as u64); } /// When reading as a field of a complex structure, we receive a "borrow" of the `Arc` @@ -112,7 +112,7 @@ pub(crate) fn interface_impl(ident: &Ident, udl_mode: bool) -> TokenStream { fn try_read(buf: &mut &[u8]) -> ::uniffi::Result<::std::sync::Arc> { ::uniffi::deps::static_assertions::const_assert!(::std::mem::size_of::<*const ::std::ffi::c_void>() <= 8); ::uniffi::check_remaining(buf, 8)?; - >::try_lift(::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) + ::try_lift(::uniffi::deps::bytes::Buf::get_u64(buf) as Self::FfiType) } const TYPE_ID_META: ::uniffi::MetadataBuffer = ::uniffi::MetadataBuffer::from_code(::uniffi::metadata::codes::TYPE_INTERFACE) diff --git a/uniffi_macros/src/record.rs b/uniffi_macros/src/record.rs index abf2743ec6..ca602158d4 100644 --- a/uniffi_macros/src/record.rs +++ b/uniffi_macros/src/record.rs @@ -50,7 +50,7 @@ pub(crate) fn record_ffi_converter_impl( Ok(quote! { #[automatically_derived] unsafe #impl_spec { - ::uniffi::ffi_converter_rust_buffer_lift_and_lower!(crate::UniFfiTag); + ::uniffi::ffi_converter_rust_buffer_lift_and_lower!(); fn write(obj: Self, buf: &mut ::std::vec::Vec) { #write_impl @@ -74,7 +74,7 @@ fn write_field(f: &Field) -> TokenStream { let ty = &f.ty; quote! { - <#ty as ::uniffi::Lower>::write(obj.#ident, buf); + <#ty as ::uniffi::Lower>::write(obj.#ident, buf); } } @@ -160,7 +160,7 @@ pub(crate) fn record_meta_static_var( // TYPE_ID_META should be the same for both traits. Ok(quote! { .concat_str(#name) - .concat(<#ty as ::uniffi::Lower>::TYPE_ID_META) + .concat(<#ty as ::uniffi::Lower>::TYPE_ID_META) #default }) }) diff --git a/uniffi_macros/src/setup_scaffolding.rs b/uniffi_macros/src/setup_scaffolding.rs index a21016e9ff..f573985113 100644 --- a/uniffi_macros/src/setup_scaffolding.rs +++ b/uniffi_macros/src/setup_scaffolding.rs @@ -27,14 +27,10 @@ pub fn setup_scaffolding(namespace: String) -> Result { Ok(quote! { // Unit struct to parameterize the FfiConverter trait. // - // We use FfiConverter to handle lowering/lifting/serializing types for this crate. See + // We use FfiConverter to handle lowering/lifting/serializing types for this crate. See // https://mozilla.github.io/uniffi-rs/internals/lifting_and_lowering.html#code-generation-and-the-fficonverter-trait // for details. // - // This is pub, since we need to access it to support external types - #[doc(hidden)] - pub struct UniFfiTag; - #[allow(clippy::missing_safety_doc, missing_docs)] #[doc(hidden)] #[no_mangle] diff --git a/uniffi_macros/src/util.rs b/uniffi_macros/src/util.rs index 9f213ea1d7..a8e20b436b 100644 --- a/uniffi_macros/src/util.rs +++ b/uniffi_macros/src/util.rs @@ -80,7 +80,7 @@ pub fn try_read_field(f: &syn::Field) -> TokenStream { let ty = &f.ty; quote! { - #ident: <#ty as ::uniffi::Lift>::try_read(buf)?, + #ident: <#ty as ::uniffi::Lift>::try_read(buf)?, } } @@ -209,37 +209,21 @@ pub(crate) fn tagged_impl_header( udl_mode: bool, ) -> TokenStream { let trait_name = Ident::new(trait_name, Span::call_site()); - if udl_mode { - quote! { impl ::uniffi::#trait_name for #ident } - } else { - quote! { impl ::uniffi::#trait_name for #ident } - } + quote! { impl ::uniffi::#trait_name for #ident } } pub(crate) fn derive_all_ffi_traits(ty: &Ident, udl_mode: bool) -> TokenStream { - if udl_mode { - quote! { ::uniffi::derive_ffi_traits!(local #ty); } - } else { - quote! { ::uniffi::derive_ffi_traits!(blanket #ty); } - } + quote! { ::uniffi::derive_ffi_traits!(blanket #ty); } } pub(crate) fn derive_ffi_traits(ty: &Ident, udl_mode: bool, trait_names: &[&str]) -> TokenStream { let trait_idents = trait_names .iter() .map(|name| Ident::new(name, Span::call_site())); - if udl_mode { - quote! { - #( - ::uniffi::derive_ffi_traits!(impl #trait_idents for #ty); - )* - } - } else { - quote! { - #( - ::uniffi::derive_ffi_traits!(impl #trait_idents for #ty); - )* - } + quote! { + #( + ::uniffi::derive_ffi_traits!(impl #trait_idents for #ty); + )* } } diff --git a/uniffi_meta/src/group.rs b/uniffi_meta/src/group.rs index ff011911fc..b31f6c0be1 100644 --- a/uniffi_meta/src/group.rs +++ b/uniffi_meta/src/group.rs @@ -189,7 +189,6 @@ impl<'a> ExternalTypeConverter<'a> { module_path, name, kind: ExternalKind::DataClass, - tagged: false, } } Type::Custom { @@ -202,7 +201,6 @@ impl<'a> ExternalTypeConverter<'a> { module_path, name, kind: ExternalKind::DataClass, - tagged: false, } } Type::Object { @@ -212,7 +210,6 @@ impl<'a> ExternalTypeConverter<'a> { module_path, name, kind: ExternalKind::Interface, - tagged: false, }, Type::CallbackInterface { module_path, name } if self.is_module_path_external(&module_path) => @@ -249,7 +246,6 @@ impl<'a> ExternalTypeConverter<'a> { module_path, name, kind, - tagged, } => { assert!(namespace.is_empty()); Type::External { @@ -257,7 +253,6 @@ impl<'a> ExternalTypeConverter<'a> { module_path, name, kind, - tagged, } } diff --git a/uniffi_meta/src/types.rs b/uniffi_meta/src/types.rs index 24f8a6f2a8..09cf7eebcd 100644 --- a/uniffi_meta/src/types.rs +++ b/uniffi_meta/src/types.rs @@ -117,7 +117,6 @@ pub enum Type { #[checksum_ignore] // The namespace is not known generating scaffolding. namespace: String, kind: ExternalKind, - tagged: bool, // does its FfiConverter use ? }, // Custom type on the scaffolding side Custom { diff --git a/uniffi_udl/src/finder.rs b/uniffi_udl/src/finder.rs index fd369f7ca6..1775ffdc94 100644 --- a/uniffi_udl/src/finder.rs +++ b/uniffi_udl/src/finder.rs @@ -148,13 +148,11 @@ impl TypeFinder for weedle::TypedefDefinition<'_> { // must be external None => { let kind = attrs.external_kind().expect("External missing kind"); - let tagged = attrs.external_tagged().expect("External missing tagged"); Type::External { name, namespace: "".to_string(), // we don't know this yet module_path: attrs.get_crate_name(), kind, - tagged, } } };