-
Notifications
You must be signed in to change notification settings - Fork 63
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
Support RustString
in extern Swift functions
#225
Support RustString
in extern Swift functions
#225
Conversation
@@ -8,13 +8,19 @@ mod ffi { | |||
|
|||
extern "Swift" { | |||
fn create_swift_string() -> String; | |||
fn take_and_return_swift_string(arg: String) -> String; | |||
} | |||
} | |||
|
|||
fn run_string_tests() { | |||
let string = ffi::create_swift_string(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe, if this PR get merged, we could remove this from crates/swift-integration-tests/src/string.rs
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left one question.
Tests are failing, but it seems like it started here 7c14ea0
The PR was passing when I merged it so maybe it conflicted with something in the master branch..
crates/swift-bridge-ir/src/codegen/codegen_tests/string_codegen_tests.rs
Show resolved
Hide resolved
@@ -8,13 +8,19 @@ mod ffi { | |||
|
|||
extern "Swift" { | |||
fn create_swift_string() -> String; | |||
fn take_and_return_swift_string(arg: String) -> String; | |||
} | |||
} | |||
|
|||
fn run_string_tests() { | |||
let string = ffi::create_swift_string(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense
Mind adding an example bridge module to your PR body so that it's more clear that the bridge module uses |
Hmmm gotcha. I can't dive in for a couple days. Any idea where the issue might be stemming from? |
I don't understand what causes the failure. I'll investigate it this week. It might be a good idea to start by addressing the compiler warnings, like so:
|
I found that what cause the failure. I'll make a PR for fixing this problem tomorrow. |
YAYAYAYAYAYAYAYAYAYAYAY!!!!!!!!!! this made me so excited. Great thanks. |
I found that #213 causes the failure:
DetailLet's say that we have a tuple type and a result type, like so: mod ffi {
extern "Rust" {
type ResultTestOpaqueRustType;
}
extern "Rust" {
fn rust_func_return_result_tuple_transparent_enum(
succeed: bool,
) -> Result<(i32, ResultTestOpaqueRustType, String), i32>;
}
} Will potentiality generate: struct __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32 __swift_bridge__$rust_func_return_result_tuple_transparent_enum(bool succeed);
typedef enum __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag {__swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$ResultOk, __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$ResultErr} __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag;
union __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Fields {struct __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString ok; int32_t err;};
typedef struct __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32{__swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag tag; union __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Fields payload;} __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32;
typedef struct __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString { int32_t _0; void* _1; void* _2; } __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString; Or struct __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32 __swift_bridge__$rust_func_return_result_tuple_transparent_enum(bool succeed);
typedef struct __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString { int32_t _0; void* _1; void* _2; } __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString;
typedef enum __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag {__swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$ResultOk, __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$ResultErr} __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag;
union __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Fields {struct __swift_bridge__$tuple$I32ResultTestOpaqueRustTypeString ok; int32_t err;};
typedef struct __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32{__swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Tag tag; union __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32$Fields payload;} __swift_bridge__$ResultTupleI32ResultTestOpaqueRustTypeStringAndI32; The former causes the failure because The reason for the non-deterministic ordering is due to swift-bridge/crates/swift-bridge-ir/src/codegen/generate_c_header.rs Lines 367 to 370 in 7c14ea0
And
Potential Solution1
2Since Solution 1 might be complicated, so maybe we could stop support #213 to fix the failure. What do you think about this? |
Thanks for the detailed breakdown and links. This made it very easy for me to understand this complex issue. I don't think we need a complex solution. I think we can solve this with the approach described here #170 (comment) In essence, we use a We iterate over the types and push them to the parse queue. If the type contains other types we push those other types to the parse queue first, recursively. Each time we push a type we insert its C header code into the So, this guarantees that a type always appears after all of the types that we depend on. So, because the solution should be fairly self-contained and not require much code, I like potential solution 1 the best where we just fix the problem. Does that make sense? |
Thank you for your quick reply.
I guess that the contents order of |
Because we wouldn't be using the The So, essentially, we're building a Some pseudocode is in #170 (comment) Does that make sense? |
Yes. Thanks!! |
Related to #225. Before this commit, the integration tests sometimes fail, like so: ``` field has incomplete type 'struct swift_bridge$tuple$I32ResultTestOpaqueRustTypeString' ``` This PR fixes the issue.
ca92199
to
7bd75f3
Compare
|
||
func take_and_return_swift_string(arg: RustString) -> String { | ||
arg.toString() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create_swift_string
returns String
. To maintain consistency between this function and take_and_return_swift_string
, I changed take_and_return_swift_string
return value from RustString
to String
. But it is inefficient. what do you think about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here're create_swift_string
and take_and_return_swift_string
implementation.
//
// String.swift
// SwiftRustIntegrationTestRunner
//
// Created by Frankie Nwafili on 2/18/22.
//
import Foundation
func create_swift_string() -> String {
"hello"
}
func take_and_return_swift_string(arg: RustString) -> String {
arg.toString()
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah it looks like the code supports anything that implements IntoRustString
so I think both -> String
and -> RustString
would work
I might just make it func take_and_return_swift_string(arg: RustString) -> RustString {
so that the reader can learn that they can return both String
and RustString
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left minor feedback then looks good to me.
Can you
- Address feedback
- Update your PR body to show an example bridge module
After that you can merge this PR.
Thanks!
@@ -8,13 +8,19 @@ mod ffi { | |||
|
|||
extern "Swift" { | |||
fn create_swift_string() -> String; | |||
fn take_and_return_swift_string(arg: String) -> String; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's call this take_and_return_rust_string
and make the Swift function (arg: RustString) -> RustString
This way we have a test for both -> String
and -> RustString
7bd75f3
to
cf163b5
Compare
Addressed your review. Please let me know if there are any errors or omissions. |
Minor, but the function should be called After that LGTM |
Done. |
Thanks! |
Related to #201. This commit adds support
RustString
in extern Swift functions.Here's an example of using this.