-
Notifications
You must be signed in to change notification settings - Fork 64
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
Adding Vec support for transparent structs #193
Conversation
Thanks for putting this together! I'll review this either tonight or tomorrow. In the meantime, can you update your PR body to include an example of what this PR now enables? These examples help with:
Here's an example of a PR that has an example in its body. |
As you alluded to, requiring Right now transparent structs can't be passed by reference. This is because neither I, nor any other contributor, has taken the time Swift classes, however, can easily be passed to Rust by reference. This is how sharing opaque types like I'm thinking that, for now, we only support For example: #[swift_bridge::bridge]
mod ffi {
#[swift_bridge(swift_repr = "class")]
struct Tomato {
field: u32
}
} The above bridge module has This would lead to us generating a Swift #[swift_bridge::bridge]
mod ffi {
extern "Rust" {
// The codegen for the `struct Tomato` above should be pretty much the same as the
// codegen for this opaque type.
// In both cases we generate a Swift class
// ( well, technically 3 -> https://chinedufn.github.io/swift-bridge/bridge-module/opaque-types/index.html#exposing-opaque-rust-types )
type OpaqueTomato;
}
}
The trick would be to massage the code so that when a struct has Are you up for that? I'd be happy to write up a contribution guide if that would help. |
hey @chinedufn , so the issue behind me having to use pub extern "C" fn _get(vec: *const Vec<#struct_name>, index: usize) -> #ffi_option_struct_repr {
let vec = unsafe { &*vec };
let val = vec.get(index).map(|v| v.clone()); // <---- I had to use .clone() here
#ffi_option_struct_repr::from_rust_repr(val)
} In contrast SharedEnum uses EDIT: here is the Rust error when using |
The reason that it's working for enums is that right now we automatically emit swift-bridge/crates/swift-bridge-ir/src/codegen/generate_rust_tokens/shared_enum.rs Lines 135 to 139 in 832498a
So, the Copies are cheap so this is fine, but we don't want to have unnecessary I suppose that we could land your implementation for transparent structs that explicitly implement Copy, but that would require us to add I'd imagine that folks aren't using transparent structs that contain only Still, I would merge Does that all make sense, or no? |
It does, yes. One issue though, I believe it will be very common to have Also, I think we will have this same issue for |
Also, it seems from the documentation that The main issue though is that starting from the release this PR would be merged, all structs exposed through the FFI would need to implement (or derive) |
Thank you for taking the time to think through all of this!
I think we want to avoid needing to clone in order to pass things across the FFI boundary. Copy is fine, but I don't want us to encourage rampant cloning, especially if there's an alternative (
Before landing this PR we would need to only generate the So, this wouldn't be a breaking change since
No because we would pass a reference to the struct to Swift, and Swift would hold this reference inside of a class. Here's a non swift-bridge example: struct MyStruct {
name: String
}
let instance = MyStruct { name: "hello".to_string() }'
let instance_ptr = &instance as *const MyStruct;
// We now have a pointer to the struct that we could pass over FFI. This could is a good example of how passing a reference to a type from Rust -> Swift looks swift-bridge/crates/swift-bridge-ir/src/codegen/codegen_tests/vec_codegen_tests.rs Lines 7 to 171 in c1fd717
Notice how we get a reference to the type, cast it to a pointer and return that pointer: swift-bridge/crates/swift-bridge-ir/src/codegen/codegen_tests/vec_codegen_tests.rs Lines 44 to 53 in c1fd717
Another example of passing references Lines 64 to 118 in e7aef34
Note that neither example requires I'd say that the best solution, at least for now, would be to support vecs on But, I'd be cool with landing you I don't think that we can land anything that relies on cloning though, since |
Yeah, now that I think more about it figuring out how to best support So it might be best to land this PR with support for |
Yeah, I was thinking about it as well, the main issue about classes and pointers is how do you make sure that the pointer in Rust is aligned with Swift, I don't see any way of checking that, more so, how do you align them if they aren't. It seems shared classes aren't supported yet as well, so probably there is no answer to this yet. So yeah, checking if the shared struct has So how can I check if a shared struct implements the |
I'm not understanding what you mean? This would essentially be an opaque pointer. But, at any rate, I thought about this a little more and realized that I'll make time for that at some point.
We'd have to add support for Similar to this issue about enums, but for structs instead #190 #194 If you're up for it, you could land that as a separate PR and then you'd be able to check for |
@chinedufn opened the PR for
Ideally we should check whether the trait is implemented as well, since one can implement these traits manually without the |
I suppose one could But yeah, it's certainly possible. If we ever wanted to handle this we could use a #[swift_bridge::bridge]
mod ffi {
#[swift_bridge(Copy)]
struct MyStruct {}
}
impl Copy for ffi::MyStruct {} We do something similar for opaque Rust types https://chinedufn.github.io/swift-bridge/bridge-module/opaque-types/index.html#swift_bridgecopysize Lines 259 to 284 in e7aef34
Sounds good! |
@@ -824,6 +824,210 @@ void* __swift_bridge__$Vec_SomeStruct$as_ptr(void* vec_ptr); | |||
} | |||
} | |||
|
|||
mod transparent_struct_vec_support_without_derives { |
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.
Minor request:
Mind adding /// Verify that ...
doc comments to any codegen test modules that you add.
They can sometimes feel redundant but I find that they really help when trying to understand a test since it's easier to read and make sense of prose than long snake case identifiers.
Especially for new contributors that are trying to understand what's going on.
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.
Done b08764e
hey @chinedufn I ended up opening a separate PR because of some conflicts between my fork's I've added more details on the PR's description |
This PR addresses #91
Added all the shims so transparent structs can support Vec. A couple caveats:
#[derive(Clone)]
macro to the generated struct, which means that all properties in a struct must implementClone
or be able to derive it. We could maybe only add the macro if there are any Vec usage of the struct, but my knowledge on Rust is kind of limited to do so 😅swift_repr = struct
, soclass
es still won't support Vec.Great description on how to implement this in the issue @chinedufn, was very helpful.