Confusing implicit conversion of enum case associated values to typle

Hi,

I imagine this is well known, but it is the first time I've knowingly hit it. Basically, Swift 4.2 (haven't tested other older Swift versions yet) will happily perform an implicit conversion from N associated values into a single tuple, leading to some very confusing error messages when you don't expect it do something like this:

import UIKit

enum Outcome {
    case success
    case failure(error: Error?, shouldStop: Bool)
}

let value: Outcome = .failure(error: nil, shouldStop: true)

if case .success = value {
    print("Success")
} else if case .failure(let error) = value {
    // `error` now has the tuple of (error, shouldStop) in it, which is... unexpected and confusing
    let theError: Error? = error
    if let foundError = theError {
        print("Failure with error: \(foundError)")
    }
}

/*
Output:

error: ImplicitTupleConfusion.playground:7:28: error: cannot convert value of type '(error: Error?, shouldStop: Bool)' to specified type 'Error?'
    let theError: Error? = error
                           ^~~~~
                                 as! Error
*/

In the code (playground) above the if case .failure(let error) = value coerces the two associated values into a single tuple, and the compiler gives the error shown. It took me a fair while to debug what was going on, because of course this error was not occurring in code that is this simple, and it was very counter-intuitive to work out the mistake - all the types were spread across the code base etc.

Is this a bug, or a known / expected behaviour? Wondering if I should JIRA or if there is an existing JIRA.

Cheers

I've encountered this as well, and I think it's somewhat inconsistent with current Swift which does not allow to call a function with a single tuple that contains its arguments anymore (swift-evolution/0029-remove-implicit-tuple-splat.md at master · apple/swift-evolution · GitHub).

Possibly, we are just in a very long transition phase, and there are some rough edges regarding tuples (see Roadmap for and state of single element tuple types? or The Generics Manifesto and single-element tuples for another example).

This behavior was intentional, but is slated to be eliminated by swift-evolution/0155-normalize-enum-case-representation.md at master · apple/swift-evolution · GitHub, which is still undergoing implementation.

4 Likes

Thanks for the deail @Joe_Groff! I won't file an issue then.