Search code examples
arraysswiftsubscript

Why can't I subscript Array with a Int32 index?


Could you tell me why it's not possible to use a Int32 (or UInt, UInt8, etc.) index to subscript Array? The following code show examples of what work and what doesn't work:

var buffer = [UInt8]()
buffer.append(0)

buffer[0] = 1    // Valid
buffer[-1] = 1   // Valid :)

var index1:Int = 0
buffer[index1] = 1 // Valid

var index2:Int32 = 0
buffer[index2] = 1 // Invalid

The last line results in this error:

Cannot subscript a value of type '[UInt8]' with an index of type 'Int32'


Solution

  • In Swift, Array conforms to—among other things—MutableCollection which defines an associated Index type, which is used for subscripting. This can be seen in the following MutableCollection.subscript signature:

    subscript(position: Index) -> Element { get set }
    

    In the Array implementation of MutableCollection the Index type is defined as Int. This is why Array expects Int values for its indexed subscript.


    In the examples in your question, the reason why buffer[0] = 1 works is because both Int (the index type) and UInt8 (the element type) conforms to ExpressibleByIntegerLiteral. When the type system infers the types of the index (and the element) it sees that the value being passed requires the type to conform to ExpressibleByIntegerLiteral and that Array.Index requires the type to be Int. Since both of these are satisfiable (because Int conforms to ExpressibleByIntegerLiteral), the type system infers that the 0 is an Int. The same process applies to inferring that the 1 is a UInt8.

    In the later two examples the index1 and index2 variables have been explicitly typed as Int and Int32 respectively. When passing index1 to Array.subscript which expects an Int index, the types match. However, when passing index2 (which is of type Int32 to Array.subscript which expects an Int index, there is a type mismatch. Array expects an Int index and the index2 variable is explicitly typed as Int32 which is a different type. There is no inference of the index type because these values aren't passed as literals, but rather as variables with a specific type.