chinedufn / swift-bridge

swift-bridge facilitates Rust and Swift interop.
https://chinedufn.github.io/swift-bridge
Apache License 2.0
810 stars 58 forks source link

Use Swift typed throws #289

Open chinedufn opened 1 month ago

chinedufn commented 1 month ago

Swift 6 will introduce a "typed throws" feature https://github.com/swiftlang/swift-evolution/blob/c0576bc0e479efabc97904020def8a8601939687/proposals/0413-typed-throws.md

// Copied from
// https://github.com/swiftlang/swift-evolution/blob/c0576bc0e479efabc97904020def8a8601939687/proposals/0413-typed-throws.md?plain=1#L224-L235
func callCat() throws(CatError) -> Cat {
  if Int.random(in: 0..<24) < 20 {
    throw .sleeps
  }
  // ...
}

Give the following bridge module:

#[swift_bridge::bridge]
mod ffi {
    enum MyError {
        Failed,
    }
    extern "Rust" {
        fn grow() -> Result<(), MyError>;
    }
}

We should emit a typed throw for Rust functions that return a Result.

// Currently generated Swift (before completing this issue)
func grow() throws {
    // ... calls Rust
}

// Typed throw (after completing this issue)
func grow() throws(MyError) {
    // ... calls Rust
}

We can add a #[swift_bridge(typed_throw)] attribute that allows people to use this in the 0.1.x branch, then remove the attribute once Swift 6 is the lowest Swift version supported by our "Minimum Supported Swift Version` policy https://github.com/chinedufn/swift-bridge/issues/288

#[swift_bridge::bridge]
mod ffi {
    // We would stop requiring this attribute whenever we dropped support for Swift 5.x
    extern "Rust" {
        #[swift_bridge(typed_throw)]
        fn grow() -> Result<(), ()>;
    }
}
NiwakaDev commented 1 week ago

@chinedufn I'd like to use the feature. Can I implement this feature?

chinedufn commented 1 week ago

Yeah!

chinedufn commented 1 week ago

then remove the attribute once Swift 6 is the lowest Swift version supported by our "Minimum Supported Swift Version` policy

Swift doesn't recommend using typed throws by default: https://github.com/swiftlang/swift-evolution/blob/d780651990fc5dec3e72c4c4203df1cff23bdf98/proposals/0413-typed-throws.md?plain=1#L448-L464

So, we may not want to default to using typed throws and instead keep the #[swift_bridge(typed_throw)] attribute even after Swift 6 is released. Not sure. Needs more research.