Why does this switch compile when it is not exhaustive?

I have this Result enumeration:

 public enum Result<T> { case success(T) case failure(Error) } 

And I wanted to implement CustomStringConvertible , which is why I did. (Do not punch holes in this, it has been simplified for this question :):

 extension Result: CustomStringConvertible { public var description: String { switch self { case .success(let value as CustomStringConvertible): return "Result.success(\(value.description))" case .success(let value): return "Result.success(\(value))" case .failure(let error as CustomStringConvertible): return "Result.failure(\(error.description))" } } } 

Doing this on the playground is absolutely accurate. However, it does not take into account the final r.description . (The same runtime failure occurs in my application, so it has nothing to do with being on the playground.)

 var r: Result<String> = .success("hello") r.description r = .failure(NSError(domain: "", code: 0, userInfo: nil)) r.description struct MyError: Error { } r = .failure(MyError()) r.description 

After a lot of scratches on my head and installing the code, I found that this is because MyError does not implement CustomStringConvertible, so no cases in the switch match. I assume this means that garbage is returned from this method.

So, does anyone know why this switch compiles?


EDIT

After fixing this on the playground, adding the last example:

 case .failure(let error): return "Result.failure(\(error))" 

it works. However, when I add this back to my application, the compiler has the courage to issue a warning: warning: case is already handled by previous patterns; consider removing it warning: case is already handled by previous patterns; consider removing it - is this an error in Swift (unlikely) or did I misunderstand the relationship between Error and CustomStringConvertible (rather)?

+7
switch-statement swift
source share
1 answer

I assume that you are importing Foundation into a file that defines the type of Result . Well, this has the (sometimes) undesirable effect of a compiler associating Swift values ​​with Objective-C compatible objects, and this is what happens in your case.

Removing the import Foundation clause will cause your switch to fail to compile because it is not exhaustive. I suspect that the Foundation import connects the CustomStringConvertible protocol with a CustomStringConvertible tag with some Objective-C value, but is incorrect, which leads to the application crashing.

0
source share

All Articles