Skip to content
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

Implement Error for RustStringRef #282

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Conversation

jnbooth
Copy link
Contributor

@jnbooth jnbooth commented Jul 19, 2024

With the latest versions of Swift, using Result<_, String> causes two errors:

  • 'RustString' is not convertible to 'any Error'
  • Thrown expression type 'RustString' does not conform to 'Error

The solution to both errors is for RustStringRef to declare conformance to the Error protocol.

See: Swift Documentation - Error

Copy link
Owner

@chinedufn chinedufn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for making this contribution.

One question about why you introduced the LocalizedError implementation.

@chinedufn
Copy link
Owner

chinedufn commented Jul 31, 2024

Just needs an integration test.

Potential approach

Bridge a function that returns -> Result<(), String>. Somewhere in here

#[swift_bridge::bridge]
mod ffi {
struct UnitStruct;
extern "Rust" {
fn rust_func_reflect_result_opaque_rust(
arg: Result<ResultTestOpaqueRustType, ResultTestOpaqueRustType>,
) -> Result<ResultTestOpaqueRustType, ResultTestOpaqueRustType>;
fn rust_func_takes_result_string(arg: Result<String, String>);
fn rust_func_takes_result_opaque_swift(
arg: Result<ResultTestOpaqueSwiftType, ResultTestOpaqueSwiftType>,
);
fn rust_func_return_result_null_opaque_rust(
succeed: bool,
) -> Result<(), ResultTestOpaqueRustType>;
fn rust_func_return_result_unit_struct_opaque_rust(
succeed: bool,
) -> Result<UnitStruct, ResultTestOpaqueRustType>;
}
extern "Rust" {
type ResultTestOpaqueRustType;
#[swift_bridge(init)]
fn new(val: u32) -> ResultTestOpaqueRustType;
fn val(&self) -> u32;
}
extern "Swift" {
type ResultTestOpaqueSwiftType;
fn val(&self) -> u32;
}
enum ResultTransparentEnum {
NamedField { data: i32 },
UnnamedFields(u8, String),
NoFields,
}
extern "Rust" {
fn rust_func_return_result_opaque_rust_transparent_enum(
succeed: bool,
) -> Result<ResultTestOpaqueRustType, ResultTransparentEnum>;
fn rust_func_return_result_transparent_enum_opaque_rust(
succeed: bool,
) -> Result<ResultTransparentEnum, ResultTestOpaqueRustType>;
}
extern "Rust" {
fn rust_func_return_result_unit_type_enum_opaque_rust(
succeed: bool,
) -> Result<(), ResultTransparentEnum>;
}
enum SameEnum {
Variant1,
Variant2,
}
extern "Rust" {
fn same_custom_result_returned_twice_first() -> Result<SameEnum, SameEnum>;
fn same_custom_result_returned_twice_second() -> Result<SameEnum, SameEnum>;
}
extern "Rust" {
fn rust_func_return_result_of_vec_u32() -> Result<Vec<u32>, ResultTestOpaqueRustType>;
fn rust_func_return_result_of_vec_opaque(
) -> Result<Vec<ResultTestOpaqueRustType>, ResultTestOpaqueRustType>;
}
extern "Rust" {
fn rust_func_return_result_tuple_transparent_enum(
succeed: bool,
) -> Result<(i32, ResultTestOpaqueRustType, String), ResultTransparentEnum>;
}
}

Then add a test case that calls that function somewhere inside here

On the test case document that (I'm paraphrasing) around the time of Swift x.y returning -> Result<(), String> started giving errors like Thrown expression type 'RustString' does not conform to 'Error'. And that we solved that by implementing Swift's Error protocol for RustStringRef. And that the test is confirming that the Error protocol is indeed implemented.

Then confirm that if you comment out the extension RustStringRef: Error {} line then tests fail.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants