diff --git a/docs/manual/src/proc_macro/index.md b/docs/manual/src/proc_macro/index.md index ed1bee5979..7dda831944 100644 --- a/docs/manual/src/proc_macro/index.md +++ b/docs/manual/src/proc_macro/index.md @@ -43,12 +43,28 @@ struct MyObject { #[uniffi::export] impl MyObject { - // All methods must have a `self` argument + // Constructors need to be annotated as such. + // As of right now, they must return `Arc`, this might change. + // If the constructor is named `new`, it is treated as the primary + // constructor, so in most languages this is invoked with `MyObject()`. + #[uniffi::constructor] + fn new(argument: String) -> Arc { + // ... + } + + // Constructors with different names are also supported, usually invoked + // as `MyObject.named()` (depending on the target language) + #[uniffi::constructor] + fn named() -> Arc { + // ... + } + + // All functions that are not constructors must have a `self` argument fn method_a(&self) { // ... } - // Arc is also supported + // `Arc` is also supported fn method_b(self: Arc) { // ... } diff --git a/fixtures/proc-macro/src/lib.rs b/fixtures/proc-macro/src/lib.rs index 99a7888b86..c5f18c2a98 100644 --- a/fixtures/proc-macro/src/lib.rs +++ b/fixtures/proc-macro/src/lib.rs @@ -32,8 +32,14 @@ pub struct Object; #[uniffi::export] impl Object { #[uniffi::constructor] - fn new() -> Arc { - Arc::new(Object) + fn new() -> Arc { + Arc::new(Self) + } + + #[uniffi::constructor] + fn named_ctor(arg: u32) -> Arc { + _ = arg; + Self::new() } fn is_heavy(&self) -> MaybeBool { diff --git a/fixtures/proc-macro/tests/bindings/test_proc_macro.kts b/fixtures/proc-macro/tests/bindings/test_proc_macro.kts index 221a2f3d4e..9bf540fc29 100644 --- a/fixtures/proc-macro/tests/bindings/test_proc_macro.kts +++ b/fixtures/proc-macro/tests/bindings/test_proc_macro.kts @@ -10,7 +10,8 @@ assert(one.inner == 123) val two = Two("a", null) assert(takeTwo(two) == "a") -val obj = Object() +var obj = Object() +obj = Object.namedCtor(1u) assert(obj.isHeavy() == MaybeBool.UNCERTAIN) assert(enumIdentity(MaybeBool.TRUE) == MaybeBool.TRUE) diff --git a/fixtures/proc-macro/tests/bindings/test_proc_macro.py b/fixtures/proc-macro/tests/bindings/test_proc_macro.py index dc50881eeb..9b53d02eba 100644 --- a/fixtures/proc-macro/tests/bindings/test_proc_macro.py +++ b/fixtures/proc-macro/tests/bindings/test_proc_macro.py @@ -11,6 +11,7 @@ assert take_two(two) == "a" obj = Object() +obj = Object.named_ctor(1) assert obj.is_heavy() == MaybeBool.UNCERTAIN assert enum_identity(MaybeBool.TRUE) == MaybeBool.TRUE diff --git a/fixtures/proc-macro/tests/bindings/test_proc_macro.swift b/fixtures/proc-macro/tests/bindings/test_proc_macro.swift index a6ffa9eafb..ed423ed9d4 100644 --- a/fixtures/proc-macro/tests/bindings/test_proc_macro.swift +++ b/fixtures/proc-macro/tests/bindings/test_proc_macro.swift @@ -10,7 +10,8 @@ assert(one.inner == 123) let two = Two(a: "a", b: nil) assert(takeTwo(two: two) == "a") -let obj = Object() +var obj = Object() +obj = Object.namedCtor(arg: 1) assert(obj.isHeavy() == .uncertain) assert(enumIdentity(value: .true) == .true) diff --git a/uniffi_macros/src/export/scaffolding.rs b/uniffi_macros/src/export/scaffolding.rs index 19933d0c62..89b457f653 100644 --- a/uniffi_macros/src/export/scaffolding.rs +++ b/uniffi_macros/src/export/scaffolding.rs @@ -55,7 +55,7 @@ pub(super) fn gen_constructor_scaffolding( const RECEIVER_ERROR: &str = "constructors must not have a self parameter"; let mut bits = ScaffoldingBits::new(); - bits.collect_params(sig.inputs.iter().skip(1), RECEIVER_ERROR); + bits.collect_params(&sig.inputs, RECEIVER_ERROR); bits.set_rust_fn_call(quote! { #self_ident::#ident }); let metadata_var = bits.gen_constructor_meta_static_var(self_ident, &sig, mod_path);