1

Is the following a compiler bug or am I doing something wrong:

protocol Subscriptable {
    associatedtype Element
    associatedtype Index
    var firstIndex: Index { get }
    var lastIndex: Index { get }
    subscript(index: Index) -> Element { get set }
}

struct AnySubscriptable<E, I>: Subscriptable {
    typealias Element = E
    typealias Index = I
    let firstIndexee: () -> I
    let lastIndexee: () -> I
    let subscriptee: (index: I) -> E
    let setSubscriptee: (index: I, element: E) -> Void
    var firstIndex: I { return firstIndexee() }
    var lastIndex: I { return lastIndexee() }
    subscript(index: I) -> E {
        get { return subscriptee(index: index) }
        set { setSubscriptee(index: index, element: newValue) }
    }
}

extension Array {
    var asScriptable: AnySubscriptable<Element, Int> {
        return AnySubscriptable(
            firstIndexee: { return self.startIndex }, // Error: Cannot convert `() -> Int` to expected `() -> _`
            lastIndexee: { return self.endIndex },
            subscriptee: { return self[$0] },
            setSubscriptee: { self[$0] = $1 }
        )
    }
}

The error, "Cannot convert () -> Int to expected () -> _", on the firstIndexee closure in the extension is strange because:

  1. The type is correct
  2. There is no error on lastIndexee
  3. If set is removed from subscript in Subscriptable, and hence setSubscriptee etc. in AnySubscriptable and in the extension, then the error goes away.

Compiler bug or my mistake?

Thanks in advance for any help,

-- Howard.

Howard Lovatt
  • 968
  • 1
  • 8
  • 15

1 Answers1

0

The error message is misleading what is required is a mutable copy of self for the setSubscriptee capture of self:

extension Array {
    var asSubscriptable: AnySubscriptable<Element, Int> {
        var mutableSelf = self // Without this line type inference fails with a *very* misleading error message!
        return AnySubscriptable(
            firstIndexee: { return self.startIndex },
            lastIndexee: { return self.endIndex },
            subscriptee: { return self[$0] },
            setSubscriptee: { mutableSelf[$0] = $1 }
        )
    }
}
Howard Lovatt
  • 968
  • 1
  • 8
  • 15