Ensuring in-place mutation of enum associated values

When dealing with enums with associated values, it's pretty common to use case matching to pull out and mutate associated values:

enum Count {

    case people(Int)
    case cars(Int)

    mutating func increment() {
        switch self {
            case .people(var count):
                count += 1
                self = .people(count)

            case .cars(let count):
                //  ...
        }
    }

}

Swift has (somewhat long-standingly) lacked a way to directly access and mutate enum cases' associated values conveniently, but that aside, is there a pattern that at least preserves in-place mutation and avoids a copy penalty?

For example, I came across this post that suggests that Swift is at least clever enough to recognize and turn a copy/mutate/assign dance into an in-place mutation, but (obviously) this isn't documented and it's unclear how reliable (or true) it is:

With the ownership features, you can get a stronger guarantee from the same pattern by doing a consuming pattern match:

switch consume _storage {
case .leaf(var values):
  values.append(value)
  _storage = .leaf(values)
}

since this should semantically ensure that the original value is moved as part of the pattern match.

10 Likes