Reduced example: let array = [[] [0]] also causes the same crash: Fatal error: Index out of range. If you do [[] []] then it complains cannot subscript a value of type '[Any]' with an index of type '()'
I think this should at least result in a warning because there is a whitespace in between the square brackets so the user at least is informed that this will be a subscript operation. Then the user can decide if it should be [][42] or [], [42].
I realize this is a special case, but this could also be diagnosed as out-of-range at compile time, given that it's an array literal and an index literal. Getting the diagnostic would indicate that perhaps it's just a typo.
Yeah but [[0][0]] is perfectly valid and shouldn't cause an error, but a warning, sure. Something like subscript expression '[0][0]' inside a collection might be unexpected; did you mean '[0], [0]'?
So I think @Avi is on the right track. The compiler does know that we're subscripting an empty array literal which is also known to be of type Array in our case. If it's a stdlib collection type, it should be possible to correctly diagnose this, no?
For example:
[[0], [] [42]]
Here the type will be inferred as [[Int]] in which case we're subscripting an empty [[Int]], which will crash at runtime.
If not any current diagnostics then I hope this will be matched by compile time evaluation evolution of Swift in case that collection subscript will be marked as evaluable at compile time.
What about Double? or Float? It might involve too much work trying to deal with this. We might be able to do this much easily once we have support for compile-time evaluation. For now, I think a simple warning diagnostic (bonus points for a fix-it but I think this will be tricky) is good enough for most cases.
let array = [[1], 2, [3] [4]] // warning: subscript expression '[3][4]' inside a collection might be unexpected
The error diagnostic would only come in to play if the subscript is an integer literal and it is subscripting an array literal. No other case can be handled at compile time with the current compiler.
I am also pro warning about subscripts of elements inside collection literals in general, but only in the following conditions:
The subscript is an integer literal or compile-time-evaluated constant.
It is common to select a single element from a known list to be interpolated into the array. However, this is usually intended to be done at runtime. If it is intended at compile time, see the next condition.
There is a space between the array literal closing bracket and the subscript's opening bracket.
As noted above, selecting from an array literal is a common idiom, and is less-likely to be an error if written as [...][x], rather than [...] [x].
The OP’s problem could be addressed without any false positives by diagnosing out-of-bounds access at compile time for literal arrays of type Array with literal subscripts. I think that’s the way to go here.
It seems like it could be possible to construct a type that's ExpressibleByArrayLiteral and has a subscript such that [[1, 2, 3], [4, 5, 6] [7, 8, 9]] is a valid literal. Not that it's a common or likely combination.
@krilnon's answer is as correct as any. In most cases, Swift does not impose any whitespace requirements on its tokens, other than not running two identifier-ish things together. The main exceptions are operators, where whitespace disambiguates prefix/postfix vs. infix operations, and optional trailing elements (trailing closures, the expression in a return statement), which can't be wrapped to the next line. Unless there was a deliberate reason to disallow something, the parser mostly doesn't.
(Does this count as a deliberate reason to disallow something? Maybe. But that'd be source-breaking at this point.)