Simplify empty enum protocol conformance

I have a protocol:

public protocol Capability {
    var storage: Storage? { get }
    typealias ID = CapabilityID<Self>
}

If I want to conform an empty enum to this I need to provide a definition of storage even though there is no possibility it will be called:

public enum LightsCapability: Capability {
    public var storage: Storage? {
        fatalError("Impossible to call – this type is uninhabited")
    }
}

It makes sense I would need to fulfil static obligations for an empty enum, but I am surprised the compiler asks me to provide a var that can't be called.

I've noticed that in other places Swift's compiler is canny about when a code path can't be called:

func test(input: Result<Never, Error>) {
    switch input {
    // No `.success` case is needed.
    case let .failure(error): print(error)
    }
}

Thanks for reading!

2 Likes

This is actually simpler than that:

public var storage: Storage? {
  switch self {}
}
2 Likes

Heh – that's cool :slight_smile: … But I'd really like to not even need to provide the implementation, given there would never be anything to call it on.

Protocols can have static requirements that even an empty enum would have to fulfill, so empty enums can't just get a default implementation of every requirement.

1 Like

Well, perhaps Swift can just synthesize protocol requirements that are known to be unreachable, like non-static properties and methods, and functions that take an uninhabited type as an argument, while any other protocol requirements would still have to be specified explicitly.

3 Likes

Yes, but non static requirements as in the example can be correctly synthesised, right? There's never a possible instance for them to be called on.

That's a great generalisation for functions with uninhabited arguments!

If any argument is uninhabited then the function can't be called, I think? My proposal is a special case of that for the situation of the implicit self argument, but the general case is even better.

1 Like