nvzqz / swift-bindgen

Bridging the gap between Swift and Rust
Apache License 2.0
150 stars 9 forks source link

Expressing Rust Move-Only Types in Swift #4

Open nvzqz opened 4 years ago

nvzqz commented 4 years ago

In Rust, types that don't implement Copy are considered to be move-only and can only be copied via Clone or other means.

In Swift, there's currently no notion of moving a value. Reassignments of a value result in an implicit copy. For class types or anything that contains a class member, this will increment the strong reference count.

There seems to be three approaches to this:

  1. Retrofit a Move protocol that gives automagical move semantics.

    Pros:

    • Doesn't require Swift users to rewrite any existing code.

    • Allows for deinit on non-class types.

    Cons:

    • Wouldn't work in the context of generics. Implicit copying would still be the default there unless a generic type is specified as Move. Rust's move-only types work in generics because all types are assumed to be move-only unless a generic type is specified as Copy.
  2. Introduce a Copy protocol and assume move-only otherwise. Essentially, just copy Rust.

    Pros:

    • Allows for easier FFI when Swift types cross over into Rust-land.

    • Fine-grained control over move semantics types.

    • Works in the context of generics out-of-the-box.

    Cons:

    • Results in significant added complexity, increasing the learning curve. Implicit copying helps keep Swift succinct and expressive.

    • Massive source compatibility break. Requires stdlib and Swift users to rewrite all implicit copies and opt into Copy where appropriate.

  3. Introduce a special Move<T> wrapper type that gives a type move semantics.

    Pros:

    • Allows for basic move-only types.

    Cons:

    • Doesn't gain much. Really only makes existing code more verbose.