Trouble Forwarding to Mutating Subscript

I was trying to write a wrapper around InlineArray with a borrowing & mutating subscript that forwards to the array's subscript (to get a feel for it), but I unexpectedly ended up with an error inside my mutating getter.

public struct Vec4<Element: Numeric> {
  var storage: [4 of Element]
  public init(_ x: Element, _ y: Element, _ z: Element, _ w: Element) {
    storage = [x, y, z, w]
  }
  public subscript(index: Int) -> Element {
    borrow { storage[index] }
    mutate { &storage[index] }
  }
}

The error is:

main.swift:8:14: error: invalid return value from a mutate accessor
 6 |   public subscript(index: Int) -> Element {
 7 |     borrow { storage[index] }
 8 |     mutate { &storage[index] }
   |              |- error: invalid return value from a mutate accessor
   |              `- note: mutate accessors can return stored properties, computed properties with mutate accessors or global 'let' declarations
 9 |   }
10 | }

Am I holding it wrong, or should I file a bug report?

2 Likes

You're not holding it wrong, per se. In Swift 6.4 InlineArray's subscript is implemented with unsafeAddress accessors, and those don't compose with anything. As of now you could implement this as a yielding mutate accessor (using -enable-experimental-feature CoroutineAccessors).

public subscript(index: Int) -> Element {
  yielding borrow { yield storage[index] }
  yielding mutate { yield &storage[index] }
}

On main currently, InlineArray's subscript is now implemented with borrow and mutate; I think your example above would work with a recent nightly.

3 Likes

I was trying this out on Apple Swift version 6.5-dev (LLVM 47afa53ea425e20, Swift 871a239941f3613).

I would have expected it to work with that nightly. Can you post an issue?

1 Like

Done. Unable to Forward to InlineArray's Mutate-ing Script. · Issue #91936 · swiftlang/swift · GitHub

1 Like