diff --git a/Sources/ConcurrencyExtras/Result.swift b/Sources/ConcurrencyExtras/Result.swift index 046066b..baae40f 100644 --- a/Sources/ConcurrencyExtras/Result.swift +++ b/Sources/ConcurrencyExtras/Result.swift @@ -1,14 +1,27 @@ -extension Result where Failure == Swift.Error { - /// Creates a new result by evaluating an async throwing closure, capturing the returned value as - /// a success, or any thrown error as a failure. - /// - /// - Parameter body: A throwing closure to evaluate. - @_transparent - public init(catching body: () async throws -> Success) async { - do { - self = .success(try await body()) - } catch { - self = .failure(error) +#if compiler(>=6) + extension Result { + /// Creates a new result by evaluating an async throwing closure, capturing the returned value as + /// a success, or any thrown error as a failure. + /// + /// - Parameter body: A throwing closure to evaluate. + @_transparent + public init(catching body: () async throws(Failure) -> Success) async { + do { + self = .success(try await body()) + } catch { + self = .failure(error) + } } } -} +#else + extension Result where Failure == Swift.Error { + @_transparent + public init(catching body: () async throws -> Success) async { + do { + self = .success(try await body()) + } catch { + self = .failure(error) + } + } + } +#endif diff --git a/Tests/ConcurrencyExtrasTests/ResultTests.swift b/Tests/ConcurrencyExtrasTests/ResultTests.swift new file mode 100644 index 0000000..6bd5984 --- /dev/null +++ b/Tests/ConcurrencyExtrasTests/ResultTests.swift @@ -0,0 +1,62 @@ +import ConcurrencyExtras +import XCTest + +final class ResultTests: XCTestCase { + struct SomeError: Error, Equatable { } + func f(_ value: Int) async throws -> Int { + if value == 42 { + return 42 + } else { + throw SomeError() + } + } + + func testBasics() async { + do { + let res = await Result { try await f(42) } + XCTAssertEqual(try res.get(), 42) + } + do { + let res = await Result { try await f(0) } + do { + _ = try res.get() + } catch let error as SomeError { + XCTAssertEqual(error, SomeError()) + } catch { + XCTFail("unexpected error: \(error)") + } + } + } + + #if compiler(>=6) + func g(_ value: Int) async throws(SomeError) -> Int { + if value == 42 { + return 42 + } else { + throw SomeError() + } + } + + func testTypedThrows() async { + let res = await Result { () async throws(SomeError) -> Int in try await g(0) } + do { + _ = try res.get() + } catch { + XCTAssertEqual(error, SomeError()) + } + } + + func h() async throws(SomeError) -> Int { + throw SomeError() + } + + func testTypedThrowsInference() async { + let res = await Result(catching: h) + do { + _ = try res.get() + } catch { + XCTAssertEqual(error, SomeError()) + } + } + #endif +}