I have an XCTest case that produces an intriguing warning:
func testFutureValueWithTimeout() {
let expectation = XCTestExpectation(description: "This should not fail")
DispatchQueue.global().async {
let expect = FutureResult<Int>()
do {
// This expectation is never fulfilled so should timeout
XCTAssertThrowsError(try expect.valueWhenFulfilled(timeoutValue: .now() + 1.0))
} catch {
// Ignore
}
expectation.fulfill()
}
wait(for: [expectation], timeout: 2)
}
This code produces the warning:
'catch' block is unreachable because no errors are thrown in 'do' block
The solution is obvious: "Remove the catch block"
func testFutureValueWithTimeout() {
let expectation = XCTestExpectation(description: "This should not fail")
DispatchQueue.global().async {
let expect = FutureResult<Int>()
// This expectation is never fulfilled so should timeout
XCTAssertThrowsError(try expect.valueWhenFulfilled(timeoutValue: .now() + 1.0))
expectation.fulfill()
}
wait(for: [expectation], timeout: 2)
}
which now fails with the message:
Invalid conversion from throwing function of type '() throws -> Void' to non-throwing function type '@convention(block) () -> Void'
This is a utility class around futures. I assumed it would not be relevant to explain this compiler warning.
The signature of the method valueWhenFulfilled is as follows:
public func valueWhenFulfilled(timeoutValue: DispatchTime) throws -> T
But the error is caught by XCTAssertThrowsError, so there's no need to surround it in a do-catch block. Just look at the function signature. It's not a throwing function:
I created a minimal version that still shows the compiler warning:
public enum FutureResultError: Error {
case futureEndedInError
}
public class FutureResult<T> {
public init() {
}
public func valueWhenFulfilled(timeoutValue: DispatchTime) throws -> T {
throw(FutureResultError.futureEndedInError)
}
}
With this code I get the same warning. Also the same error when I remove the catch block.
I do understand that XCTAssertThrowsError it is not supposed to throw an error. This is exactly why I am posting this question. It seems like the compiler is confused somehow.