How can I fix warning with this typedThrow error?

I'm trying to merge errors in to generics. And I'm getting two kind's of warning that I can't understand

enum NoThrow: Error {
    
}
func howToThrow() throws(NoThrow) {
    
}
func foo() {

    do {
        try howToThrow()
    } catch {
//Constant 'error' inferred to have type 'NoThrow', which is an enum with no cases
//Add an explicit type annotation to silence this warning
        switch error {
        @unknown default:
            fatalError()
        }
    }
}

Above code is complaining Constant 'error' inferred to have type 'NoThrow', which is an enum with no cases. Add an explicit type annotation to silence this warning
How can I add explicit type mark in this case?

enum EitherError<First:Error,Second:Error>:Error {
    case first(First)
    case second(Second)
}

func checkTwo<First:Error, Second:Error>(
    first: () throws(First) -> Void,
    second: () throws(Second) -> Void
) throws(EitherError<First,Second>) {
    do {
        try first()
    } catch {
        throw .first(error)
    }
    do {
        try second()
    } catch {
        throw .second(error)
    }
}

func foo() {
    do {
        
        try checkTwo(first: {}, second: {})
    } catch {
///Switch covers known cases, but 'EitherError<Never, Never>' may have additional unknown values; this is an error in the Swift 6 language mode
///Add missing cases
        switch error {
        case .first(let never):
            
            break
        case .second(let never):
            break
        @unknown default:
            fatalError()
        }
    }
}

Above Code is yelling at me Switch covers known cases, but 'EitherError<Never, Never>' may have additional unknown values; this is an error in the Swift 6 language mode. Add missing cases.

1 Like

The first warning is telling you that NoThrow has no cases; therefore, it can never be thrown. Based on how you named this type, it sounds like this is what you want. However, the compiler is warning you because usually people don't write that a function throws when it never throws (other than in the generic context).

In the standard library, there is a type called Never that is already declared as an enum with no cases and serves the same purpose as your custom type. You can write func howToThrow() throws(Never) instead and this warning will go away, but instead you will get other warnings since the compiler understands that howToThrow() actually never throws, and the declaration is equivalent to writing func howToThrow().

Without changing the code in any other way, there is not really a way to add any explicit type annotation to silence this warning without getting some other warning. The compiler is able to determine one way or another that all of this error handling code is unconditionally unreachable and basically wants you to remove it.

cc @Douglas_Gregor because the fix-it here is bogus—it "adds an explicit type annotation" by changing the code to catch {: NoThrow


As far as I can tell, the second warning is straightforwardly a compiler bug; with EitherError being a non-resilient type, there is (a) no way for there to be unknown cases; and (b) even if there were, it should be covered by @unknown default but the warning won't go away and the fix-it doesn't do anything. Probably worth filing a GitHub issue particularly since we're upgrading this warning to an error in Swift 6.

That said, the workaround is to delete the second case and write a plain default.

4 Likes

Thanks for detailed explanation. I created an issue on [TypedThrow] compiler warns with unfixable message when using generic enum error · Issue #74227 · apple/swift · GitHub