Skip to content
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

Use Swift.Result instead of our Result if compiler(>=5) #280

Merged
merged 2 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions Result/Result.swift
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
// Copyright (c) 2015 Rob Rix. All rights reserved.

#if swift(>=4.2)
#if compiler(>=5)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this maintains the requirements for semantic version compatibility, so I think we need to drop support for Swift 4 to do this. (And we should do this!)

If we conditionally define the enum, then the output is different if Result is compiled in Swift 4 mode or Swift 5 mode. Since semantic versioning was defined by TPW and he writes Ruby, it's not totally clear whether it's meant to be source- or binary-compatible, but I think the safe thing is to require both.

Copy link
Contributor Author

@norio-nomura norio-nomura Jan 10, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to drop support for Swift 4 to do this. (And we should do this!)

Is it enough to just change the major (or minor) version? It seems there is no need to make Build impossible with older Swift.🤔

If we conditionally define the enum, then the output is different if Result is compiled in Swift 4 mode or Swift 5 mode.

It is not affected by the -swift-version flag. When using the Swift 5+ compiler, Swift.Result will be used.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, edited previous comment. 🙇

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I see! Tricky!


// Use Swift.Result
extension Result {
// ResultProtocol
public typealias Value = Success
public typealias Error = Failure
}

#else

/// An enum representing either a failure with an explanatory error, or a success with a result value.
public enum Result<Value, Error: Swift.Error> {
case success(Value)
case failure(Error)
}

#endif
#else

/// An enum representing either a failure with an explanatory error, or a success with a result value.
public enum Result<Value, Error: Swift.Error> {
case success(Value)
case failure(Error)
}

#endif

extension Result {
/// The compatibility alias for the Swift 5's `Result` in the standard library.
///
/// See https://github.com/apple/swift-evolution/blob/master/proposals/0235-add-result.md
Expand Down Expand Up @@ -165,6 +190,39 @@ extension Result where Result.Failure == AnyError {
}
}

// MARK: - Equatable

#if swift(>=4.2)
#if !compiler(>=5)
extension Result: Equatable where Result.Success: Equatable, Result.Failure: Equatable {}
#endif
#elseif swift(>=4.1)
extension Result: Equatable where Result.Success: Equatable, Result.Failure: Equatable {}
#endif

#if swift(>=4.2)
// Conformance to `Equatable` will be automatically synthesized.
#else
extension Result where Result.Success: Equatable, Result.Failure: Equatable {
/// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal.
public static func ==(left: Result<Value, Error>, right: Result<Value, Error>) -> Bool {
if let left = left.value, let right = right.value {
return left == right
} else if let left = left.error, let right = right.error {
return left == right
}
return false
}
}

extension Result where Result.Success: Equatable, Result.Failure: Equatable {
/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values.
public static func !=(left: Result<Value, Error>, right: Result<Value, Error>) -> Bool {
return !(left == right)
}
}
#endif

// MARK: - Derive result from failable closure

@available(*, deprecated, renamed: "Result.init(attempt:)")
Expand Down
23 changes: 0 additions & 23 deletions Result/ResultProtocol.swift
Original file line number Diff line number Diff line change
Expand Up @@ -111,29 +111,6 @@ extension Result where Result.Failure: ErrorConvertible {

// MARK: - Operators

extension Result where Result.Success: Equatable, Result.Failure: Equatable {
/// Returns `true` if `left` and `right` are both `Success`es and their values are equal, or if `left` and `right` are both `Failure`s and their errors are equal.
public static func ==(left: Result<Value, Error>, right: Result<Value, Error>) -> Bool {
if let left = left.value, let right = right.value {
return left == right
} else if let left = left.error, let right = right.error {
return left == right
}
return false
}
}

#if swift(>=4.1)
extension Result: Equatable where Result.Success: Equatable, Result.Failure: Equatable { }
#else
extension Result where Result.Success: Equatable, Result.Failure: Equatable {
/// Returns `true` if `left` and `right` represent different cases, or if they represent the same case but different values.
public static func !=(left: Result<Value, Error>, right: Result<Value, Error>) -> Bool {
return !(left == right)
}
}
#endif

extension Result {
/// Returns the value of `left` if it is a `Success`, or `right` otherwise. Short-circuits.
public static func ??(left: Result<Value, Error>, right: @autoclosure () -> Value) -> Value {
Expand Down