Open sax opened 7 months ago
Thanks for taking the time to make a detailed and easy to follow issue.
Glad you have a workaround. I'll explain the problem and solution in case someone needs the signature to work in the future.
Looks like the problem is that we're using ToRustStr
which takes a closure of type (RustStr) -> T
.
public protocol ToRustStr {
func toRustStr<T> (_ withUnsafeRustStr: (RustStr) -> T) -> T;
}
But the codegen is using a closure of that can throw, meaning it has type (RustStr) throws -> T
.
// The closure that is being passed into `toRustStr` can throw an exception,
// but `toRustStr` is defined to take a closure that does not throw an exception.
return receives.toRustStr({ receivesAsRustStr in
try {
let val = __swift_bridge__$RustApp$resultTest(ptr, receivesAsRustStr)
if val != nil { throw RustString(ptr: val!) } else { return }
}()
})
Here's a potential solution in case someone in the future needs this signature to work.
It boils down to making a toRustStrThrows
function and calling that instead of toRustStr
.
Review the documentation for supporting a new signature https://github.com/chinedufn/swift-bridge/blob/master/book/src/contributing/adding-support-for-a-signature/README.md
Add a func toRustStrThrows<T> (_ withUnsafeRustStr: (RustStr) throws -> T)
to the ToRustStr
protocol
Add a fn rust_fn_accepts_ref_str_returns_result(str: &str) -> Result<String, String>
. https://github.com/chinedufn/swift-bridge/blob/27246447b4ac741b8bf086d3dfca15b47558e44f/crates/swift-integration-tests/src/string.rs#L6
Add an implementation for rust_fn_accepts_ref_str_returns_result
fn rust_fn_accepts_ref_str_returns_result(str: &str) -> Result<String, String> {
if str == "should succeed" {
return Ok("ok".to_string())
} else {
return Err("error".to_string())
}
}
Add an integration test to StringTests.swift
that calls rust_fn_accepts_ref_str_returns_result
with "should_succeed" and confirms that it does not throw, then calls it with "fail" and confirms that it throws
rust_fn_accepts_ref_str_returns_result
https://github.com/chinedufn/swift-bridge/blob/27246447b4ac741b8bf086d3dfca15b47558e44f/SwiftRustIntegrationTestRunner/SwiftRustIntegrationTestRunnerTests/StringTests.swift#L24-L30Add a codegen test to string_codegen_tests.rs
with a function that accepts a string arg and returns a result. For example, fn some_function (arg: &str) -> Result<RustType, RustType>
.
toRustStrThrows
instead of toRustStr
Get tests passing
When given the following bridge definition:
The generated swift code produces a compiler error:
Invalid conversion from throwing function of type '(RustStr) throws -> ()' to non-throwing function type '(RustStr) -> ()'
I have included the following in my project:
If instead my bridge function is defined as follows, then the project compiles fine:
That generates the following Swift:
I'm not sure if this is expected behavior or not. So far I've been able to send Swift
String
values into Rust as&str
fine for any function that does not return a result.For my project, it's fine for it to use owned strings, but I did lose a bit of time before I tried switching the inputs. Even if there is no resulting change to swift-bridge, though, maybe at least having it documented in an issue will save others some heartache!