@enumRepresentable attribute to automatically synthesise Enum cases and compose enums from Protocols

Given this example enum

enum AsyncState<T> {
    case initial
    case isUpdating(Float)
    case didUpdate(T)
    case didFail(Error)
}

considering that enum cases without associated values are equivalent to:

static let initial: AsyncState<T>

considering that enum cases with associated values are equivalent to:

static func isUpdating(_ progress: Float) -> AsyncState<T>

it would be really useful to be able to declare a protocol like this:

protocol State {
    associatedtype T

    @enumRepresentable
    static var initial: Self { get }
   
    @enumRepresentable
    static func isUpdating(_ progress: Float) -> Self
    @enumRepresentable
    static func didUpdate(_ value: T) -> Self
    @enumRepresentable
    static func didFail(_ error: Error) -> Self
}

then simply declare:

enum AsyncState: State {
    typealias T = SomeType
}

and have all the cases synthesised automatically.
We could compose enums from protocols gaining flexibility and having compile time safety.
The @enumRepresentable annotation would be ignored when adopting the protocol in classes or structs.

Honestly, If this were to ever exist, I would rather prefer protocol Foo: enum and use cases as requirements.

That sounds good too, but with the annotation we'd have the flexibility of also specifying some requirements that are not enum cases in the same protocol.

What exactly does this let you do that is cumbersome or impossible today? I'm failing to see the benefit vs implementation case.

1 Like

Yes, I understand your reasons for the annotation – the protocol will not be constrained to enums only. The use case of having such an annotation for that reason is rather vague though.

However, this not a bad approach to the problem that was always faced with enum inheritance.

I could have an enum like

enum ComplexState: State {
    typealias T = SomeType

    case someOtherCase
}

that could extend the State protocol while having the other 4 cases automatically synthesised.

Imho that's way to much magic that isn't intuitive... inheritance for enums would be easy to understand, but using protocols for auto synthesis is a big step.

1 Like

I agree that it is a big step but inheritance would prevent composition from multiple protocols and also the reason why this may be not super-intuitive is that we're not very used to think about enum cases as static vars/functions which requires a more functional mindset, but I think we Swift developers are getting there.

1 Like

I would be ok with enum cases satisfying static vars from a protocol, but not sure about having this special compiler magic for automatically inferring cases when an enum conforms.

1 Like

Right now, if you copy/paste the code from my pitch (without the @enumRepresentable annotations) and make the enum conform to the State protocol, you'll get an error from the compiler about duplicate symbols so I don't think it would be too "magical".