It turns out that Swift 3 nested enums combine options, but it's not inheritance. It's a little know "feature" you should be aware of when designing API with Swift 3.
I didn't know that, and my (I have to admit reasonable assumption) lead to the problem that can't be easily "workaround" now.
One day I got this Natalie#90:
When trying to compile the generated Storyboards.swift, I have the error Ambiguous type name 'Segue.'
Segue
is an enum
type and the only possibility to make it ambiguous is when two or more segues share the same identifier (case option). This, on the other hand, should be easy to fix by simply change identifier to unique.
This is not such case!
What we deal here is two classes: Class A
has defined subtype enum Reusable
, with one case option1
.
class A {
enum Reusable {
case option1
}
}
there is another class B
that inherit from the class A
with defined subtype enum Reusable
, with one case option1
.
class B: A {
enum Reusable {
case option1
}
}
these are four types in this example
- class
A
- class
B
- enum
A.Reusable
- enum
B.Reusable
When I'm trying to use B.Reusable
compiler is confused and doesn't know what to do. I am confused as well, even more.
here we go. As soon as I'm trying to use enums I run into troubles:
let _ = B.Reusable.option1
generate compile time errors:
Untitled.swift:17:11: error: ambiguous use of 'option1'
let _ = B.Reusable.option1
^
Untitled.swift:9:8: note: found this candidate
case option1
^
Untitled.swift:3:8: note: found this candidate
case option1
^
waaaaaat? Recall how B.Reusable
is defined. There is only one possible case for B.Reusable.option1
.
That's…not how I'd expect it to behave
Here what is going on: Because B
inherits from A
, then B.Reusable
magically inherit optiona1
from A.Reusable
. With that in mind, it is possible to write the code that compile, works and doesn't makes any sense:
class A {
enum Reusable {
case option1
}
}
class B: A {
enum Reusable { }
}
let _ = A.Reusable.option1
let _ = B.Reusable.option1 // wat???
B.Reusable.option1
is never defined, but due to magic inheritance, it is available to use.
No one expects the Spanish Inquisition
We have a bug here. A bug, which made me a headache. No one expects this behavior. Distinct types should remain distinct. What next? It should be fixed (I hope it's not an intended behavior). There is bug SR-3492 reported, you can subscribe to get notified when it gets resolved.
You have been warned.
This post is a follow-up of the tweet of mine. If you like stuff like that, you should definitely follow me on Twitter.
Cheers.