-
Notifications
You must be signed in to change notification settings - Fork 61
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 throwing initializers #287
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||
---|---|---|---|---|
|
@@ -527,3 +527,82 @@ void* __swift_bridge__$Foo$new(void); | |||
.test(); | ||||
} | ||||
} | ||||
|
||||
/// Verify that we can use a Swift class with a throwing init. | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||||
mod extern_rust_class_with_throwing_init { | ||||
use super::*; | ||||
|
||||
fn bridge_module_tokens() -> TokenStream { | ||||
quote! { | ||||
mod foo { | ||||
enum SomeErrEnum { | ||||
Variant1, | ||||
Variant2, | ||||
} | ||||
extern "Rust" { | ||||
type Foo; | ||||
|
||||
#[swift_bridge(init)] | ||||
fn new() -> Result<Foo, SomeErrEnum>; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
|
||||
fn expected_rust_tokens() -> ExpectedRustTokens { | ||||
ExpectedRustTokens::Contains(quote! { | ||||
# [export_name = "__swift_bridge__$Foo$new"] | ||||
pub extern "C" fn __swift_bridge__Foo_new() -> ResultFooAndSomeErrEnum{ | ||||
match super :: Foo :: new() { | ||||
Ok(ok) => ResultFooAndSomeErrEnum::Ok(Box::into_raw(Box::new({ | ||||
let val: super::Foo = ok; | ||||
val | ||||
})) as *mut super::Foo), | ||||
Err(err) => ResultFooAndSomeErrEnum::Err(err.into_ffi_repr()), | ||||
} | ||||
} | ||||
}) | ||||
} | ||||
|
||||
const EXPECTED_SWIFT: ExpectedSwiftCode = ExpectedSwiftCode::ContainsAfterTrim( | ||||
r#" | ||||
public class Foo: FooRefMut { | ||||
var isOwned: Bool = true | ||||
|
||||
public override init(ptr: UnsafeMutableRawPointer) { | ||||
super.init(ptr: ptr) | ||||
} | ||||
|
||||
deinit { | ||||
if isOwned { | ||||
__swift_bridge__$Foo$_free(ptr) | ||||
} | ||||
} | ||||
} | ||||
extension Foo { | ||||
public convenience init() throws { | ||||
let val = __swift_bridge__$Foo$new(); switch val.tag { case __swift_bridge__$ResultFooAndSomeErrEnum$ResultOk: self.init(ptr: val.payload.ok) case __swift_bridge__$ResultFooAndSomeErrEnum$ResultErr: throw val.payload.err.intoSwiftRepr() default: fatalError() } | ||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's use an The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. However, I don't address the others yet. For example:
I'll address this in the next PR, or we can open it as good first issue. |
||||
} | ||||
} | ||||
"#, | ||||
); | ||||
|
||||
const EXPECTED_C_HEADER: ExpectedCHeader = ExpectedCHeader::ContainsAfterTrim( | ||||
r#" | ||||
typedef enum __swift_bridge__$ResultFooAndSomeErrEnum$Tag {__swift_bridge__$ResultFooAndSomeErrEnum$ResultOk, __swift_bridge__$ResultFooAndSomeErrEnum$ResultErr} __swift_bridge__$ResultFooAndSomeErrEnum$Tag; | ||||
union __swift_bridge__$ResultFooAndSomeErrEnum$Fields {void* ok; struct __swift_bridge__$SomeErrEnum err;}; | ||||
typedef struct __swift_bridge__$ResultFooAndSomeErrEnum{__swift_bridge__$ResultFooAndSomeErrEnum$Tag tag; union __swift_bridge__$ResultFooAndSomeErrEnum$Fields payload;} __swift_bridge__$ResultFooAndSomeErrEnum; | ||||
"#, | ||||
); | ||||
|
||||
#[test] | ||||
fn extern_rust_class_with_throwing_init() { | ||||
CodegenTest { | ||||
bridge_module: bridge_module_tokens().into(), | ||||
expected_rust_tokens: expected_rust_tokens(), | ||||
expected_swift_code: EXPECTED_SWIFT, | ||||
expected_c_header: EXPECTED_C_HEADER, | ||||
} | ||||
.test(); | ||||
} | ||||
} |
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.
I guess that it's not suitable because the
convert_ffi_value_to_swift_value
method returns a expression.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.
I'm not sure what you're communicating?
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.
I think you're asking whether it's okay to return two statements here instead of a single expression?
This should be fine since the
ThrowingInit
code here is only ever used inside of an initializer and isn't ever embedded inside of another expression.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.
The other return values of
convert_ffi_value_to_swift_value
return closures, but this case doesn't return a closure. This means a simple statement, not expression.For examples:
swift-bridge/crates/swift-bridge-ir/src/bridged_type/bridgeable_result.rs
Line 286 in 495611b
swift-bridge/crates/swift-bridge-ir/src/bridged_type/bridgeable_result.rs
Line 247 in 495611b
The above examples return closures.