Fixed Enum Layout Sizes

WARNING: Turns out there are some nasty side-effects, see the update below.

: .warning

If you have every attempted to create a generic enum, you have most certainly encountered the following error message:

error: unimplemented IR generation feature non-fixed multi-payload enum layout

: .warning

Yikes! Well, it turns out that Swift (whether by-design or a current limitation) needs to know the full layout size of the enum at compile time. So code like this:

enum FailableOf<T> {
  case Success(T)
  case Failure(Error)

  init(_ value: T) {
    self = .Success(value)
  }

  init(_ error: Error) {
    self = .Failure(error)
  }

  var failed: Bool { /* ... */ }
  var error: Error? { /* ... */ }

  var value: T? {
    switch self {
    case .Success(let value):
      return value

    default:
      return nil
    }
  }
}

Is just not possible to write. I had worked around this by using a wrapper class FailableWrapper<T> (see Error Handling in Swift).

However, Rob Napier tweeted a much more elegant solution.

//platform.twitter.com/widgets.js
When I saw that, I thought, "well duh!". So much better than my workaround.

Here's the source for my full FailableOf<T> class; no more need for the wrapper class.

public enum FailableOf<T> {
    case Success(@autoclosure() -> T)
    case Failure(Error)

    public init(_ value: T) {
        self = .Success(value)
    }

    public init(_ error: Error) {
        self = .Failure(error)
    }

    public var failed: Bool {
        switch self {
        case .Failure(let error):
            return true

        default:
            return false
        }
    }

    public var error: Error? {
        switch self {
        case .Failure(let error):
            return error

        default:
            return nil
        }
    }

    public var value: T? {
        switch self {
        case .Success(let value):
            return value()

        default:
            return nil
        }
    }
}

UPDATE August 6th: Thanks for John Vasileff for pointing out, what should have been, an obvious design flaw with this approach.

: .info

//platform.twitter.com/widgets.js
Yep… he's right. =)

Back to my wrapper class for now.

Fixed Enum Layout Sizes