Skip to content

Commit ecd3b97

Browse files
authored
Fix already_declared attribute for enums and structs (#226)
When generating the rust function wrappers for an extern swift function with an already_declared struct/enum the generated code used a locally defined struct/enum with this patch we add `super` to that function signature. An example of code that was previously not working: ```rs #[swift_bridge::bridge] mod ffi_i { enum Foo { Bar. } } use ffi_i::Foo; #[swift_bridge::bridge] mod ffi { #[swift_bridge(already_declared)] enum Foo {} extern "Rust" {} extern "Swift" { fn baz(a: Foo); } } ``` Previously the genrated function would be something like: ```rs mod ffi { fn baz(a: Foo) { // ... } } ``` now it's ```rs mod ffi { fn baz(a: super::Foo) { // ... } } ```
1 parent 7c14ea0 commit ecd3b97

File tree

8 files changed

+99
-22
lines changed

8 files changed

+99
-22
lines changed

SwiftRustIntegrationTestRunner/SwiftRustIntegrationTestRunner/SharedEnumAttributes.swift

+4
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ import Foundation
1010
func extern_swift_enum_rename(arg: EnumRename) -> EnumRename {
1111
arg
1212
}
13+
14+
func swift_reflect_already_declared_enum(arg: AlreadyDeclaredEnumTest) -> AlreadyDeclaredEnumTest {
15+
arg
16+
}

SwiftRustIntegrationTestRunner/SwiftRustIntegrationTestRunnerTests/SharedEnumAttributeTests.swift

+6-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ class SharedEnumAttributeTests: XCTestCase {
2121
}
2222

2323

24-
/// Verify that we can call a function that uses a type that was already declared in a different bridge module.
24+
/// Verify that we can call a rust function from swift that uses a type that was already declared in a different bridge module.
2525
func testSharedEnumAlreadyDeclared() throws {
2626
XCTAssertEqual(
2727
reflect_already_declared_enum(
@@ -31,11 +31,16 @@ class SharedEnumAttributeTests: XCTestCase {
3131
)
3232
}
3333

34+
/// Verify that we can call a swift function from rust that uses a type that was already declared in a different bridge module.
35+
func testSharedEnumAlreadyDeclared() throws {
36+
test_rust_calls_swift_already_declared()
37+
}
3438

3539
/// Verify that we can use the generated Debug impl.
3640
func testSharedEnumDeriveDebug() throws {
3741
let debugString = String(reflecting: DeriveDebugEnum.Variant)
3842
XCTAssertEqual(debugString, "Variant")
3943
}
44+
4045
}
4146

book/src/bridge-module/transparent-types/enums/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ mod ffi_2 {
5959
// The `already_declared` indicates that instead of creating a new enum
6060
// we should use super::SomeTransparentEnum;
6161
#[swift_bridge(already_declared)]
62-
enum SomeTransparentEnum;
62+
enum SomeTransparentEnum {}
6363

6464
extern "Rust" {
6565
fn some_function() -> SomeTransparentEnum;

crates/swift-bridge-ir/src/bridged_type.rs

+16-4
Original file line numberDiff line numberDiff line change
@@ -902,14 +902,26 @@ impl BridgedType {
902902
},
903903
BridgedType::Foreign(CustomBridgedType::Shared(SharedType::Struct(shared_struct))) => {
904904
let ty_name = &shared_struct.name;
905-
quote! {
906-
#ty_name
905+
if shared_struct.already_declared {
906+
quote! {
907+
super::#ty_name
908+
}
909+
} else {
910+
quote! {
911+
#ty_name
912+
}
907913
}
908914
}
909915
BridgedType::Foreign(CustomBridgedType::Shared(SharedType::Enum(shared_enum))) => {
910916
let enum_name = &shared_enum.name;
911-
quote! {
912-
#enum_name
917+
if shared_enum.already_declared {
918+
quote! {
919+
super::#enum_name
920+
}
921+
} else {
922+
quote! {
923+
#enum_name
924+
}
913925
}
914926
}
915927
}

crates/swift-bridge-ir/src/codegen/codegen_tests/already_declared_attribute_codegen_tests.rs

+43-12
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,35 @@ mod already_declared_struct {
110110
struct FfiSomeType;
111111

112112
extern "Rust" {
113-
fn some_function(arg: FfiSomeType) -> FfiSomeType;
113+
fn rust_some_function(arg: FfiSomeType) -> FfiSomeType;
114+
}
115+
116+
extern "Swift" {
117+
fn swift_some_function(arg: FfiSomeType) -> FfiSomeType;
114118
}
115119
}
116120
}
117121
}
118122

119123
fn expected_rust_tokens() -> ExpectedRustTokens {
120-
ExpectedRustTokens::DoesNotContain(quote! {
121-
struct FfiSomeType
122-
})
124+
ExpectedRustTokens::ContainsManyAndDoesNotContainMany {
125+
contains: vec![
126+
quote! {
127+
pub extern "C" fn __swift_bridge__rust_some_function(arg: <super::FfiSomeType as swift_bridge::SharedStruct>::FfiRepr) -> <super::FfiSomeType as swift_bridge::SharedStruct>::FfiRepr {
128+
super::rust_some_function(arg.into_rust_repr()).into_ffi_repr()
129+
}
130+
},
131+
quote! {
132+
extern "C" {
133+
#[link_name = "__swift_bridge__$swift_some_function"]
134+
fn __swift_bridge__swift_some_function(arg: <super::FfiSomeType as swift_bridge::SharedStruct>::FfiRepr) -> <super::FfiSomeType as swift_bridge::SharedStruct>::FfiRepr;
135+
}
136+
},
137+
],
138+
does_not_contain: vec![quote! {
139+
struct FfiSomeType
140+
}],
141+
}
123142
}
124143

125144
fn expected_swift_code() -> ExpectedSwiftCode {
@@ -129,7 +148,7 @@ mod already_declared_struct {
129148
fn expected_c_header() -> ExpectedCHeader {
130149
ExpectedCHeader::ExactAfterTrim(
131150
r#"
132-
struct __swift_bridge__$FfiSomeType __swift_bridge__$some_function(struct __swift_bridge__$FfiSomeType arg);
151+
struct __swift_bridge__$FfiSomeType __swift_bridge__$rust_some_function(struct __swift_bridge__$FfiSomeType arg);
133152
"#,
134153
)
135154
}
@@ -157,19 +176,31 @@ mod already_declared_enum {
157176
enum FfiSomeEnum {}
158177

159178
extern "Rust" {
160-
fn some_function(arg: FfiSomeEnum) -> FfiSomeEnum;
179+
fn rust_some_function(arg: FfiSomeEnum) -> FfiSomeEnum;
180+
}
181+
182+
extern "Swift" {
183+
fn swift_some_function(arg: FfiSomeEnum) -> FfiSomeEnum;
161184
}
162185
}
163186
}
164187
}
165188

166189
fn expected_rust_tokens() -> ExpectedRustTokens {
167190
ExpectedRustTokens::ContainsManyAndDoesNotContainMany {
168-
contains: vec![quote! {
169-
pub extern "C" fn __swift_bridge__some_function(arg: <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr) -> <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr {
170-
super::some_function(arg.into_rust_repr()).into_ffi_repr()
171-
}
172-
}],
191+
contains: vec![
192+
quote! {
193+
pub extern "C" fn __swift_bridge__rust_some_function(arg: <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr) -> <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr {
194+
super::rust_some_function(arg.into_rust_repr()).into_ffi_repr()
195+
}
196+
},
197+
quote! {
198+
extern "C" {
199+
#[link_name = "__swift_bridge__$swift_some_function"]
200+
fn __swift_bridge__swift_some_function(arg: <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr) -> <super::FfiSomeEnum as swift_bridge::SharedEnum>::FfiRepr;
201+
}
202+
},
203+
],
173204
does_not_contain: vec![quote! {
174205
enum FfiSomeEnum
175206
}],
@@ -183,7 +214,7 @@ mod already_declared_enum {
183214
fn expected_c_header() -> ExpectedCHeader {
184215
ExpectedCHeader::ExactAfterTrim(
185216
r#"
186-
struct __swift_bridge__$FfiSomeEnum __swift_bridge__$some_function(struct __swift_bridge__$FfiSomeEnum arg);
217+
struct __swift_bridge__$FfiSomeEnum __swift_bridge__$rust_some_function(struct __swift_bridge__$FfiSomeEnum arg);
187218
"#,
188219
)
189220
}

crates/swift-bridge-macro/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub fn bridge(
2121
let tokens = quote! {
2222
#module
2323
};
24+
2425
tokens.into()
2526
}
2627

crates/swift-integration-tests/src/enum_attributes/already_declared.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,26 @@ mod ffi2 {
1616
enum AlreadyDeclaredEnumTest {}
1717

1818
extern "Rust" {
19-
fn reflect_already_declared_enum(arg: AlreadyDeclaredEnumTest) -> AlreadyDeclaredEnumTest;
19+
fn rust_reflect_already_declared_enum(
20+
arg: AlreadyDeclaredEnumTest,
21+
) -> AlreadyDeclaredEnumTest;
22+
}
23+
24+
extern "Rust" {
25+
fn test_rust_calls_swift_already_declared();
26+
}
27+
28+
extern "Swift" {
29+
fn swift_reflect_already_declared_enum(
30+
arg: AlreadyDeclaredEnumTest,
31+
) -> AlreadyDeclaredEnumTest;
2032
}
2133
}
2234

23-
fn reflect_already_declared_enum(arg: AlreadyDeclaredEnumTest) -> AlreadyDeclaredEnumTest {
35+
fn rust_reflect_already_declared_enum(arg: AlreadyDeclaredEnumTest) -> AlreadyDeclaredEnumTest {
2436
arg
2537
}
38+
fn test_rust_calls_swift_already_declared() {
39+
let val = ffi2::swift_reflect_already_declared_enum(AlreadyDeclaredEnumTest::Variant);
40+
assert!(matches!(val, AlreadyDeclaredEnumTest::Variant));
41+
}

crates/swift-integration-tests/src/struct_attributes/already_declared.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,20 @@ mod ffi2 {
1717
struct AlreadyDeclaredStructTest;
1818

1919
extern "Rust" {
20-
fn reflect_already_declared_struct(
20+
fn rust_reflect_already_declared_struct(
21+
arg: AlreadyDeclaredStructTest,
22+
) -> AlreadyDeclaredStructTest;
23+
}
24+
25+
extern "Swift" {
26+
fn swift_reflect_already_declared_struct(
2127
arg: AlreadyDeclaredStructTest,
2228
) -> AlreadyDeclaredStructTest;
2329
}
2430
}
2531

26-
fn reflect_already_declared_struct(arg: AlreadyDeclaredStructTest) -> AlreadyDeclaredStructTest {
32+
fn rust_reflect_already_declared_struct(
33+
arg: AlreadyDeclaredStructTest,
34+
) -> AlreadyDeclaredStructTest {
2735
arg
2836
}

0 commit comments

Comments
 (0)