Either this is a bug or not, I’d say this seems to be a desirable behavior to have. For instance, in Go you can pass it as foo(v...), which is highly convenient, and resolves disambiguity of array passing.
It's not a bug, it's a design flaw that we haven't been able to fix because no one can agree on a syntax for splatting an array into a variadic parameter list.
Given this, it sounds like the syntax the core team wants for splatting is:
func foo<T>(_ arg: T...) {
print(repeat each arg)
}
Which isn't that bad, and I can't think of any reason it won't work. It's basically just an overload of repeat each that takes an array instead of a pack parameter.
The implementation in the pitch has probably bit-rotted though.
Array (or tuple) splatting while look related, is a different feature that could be considered separately. You don't need array splatting in the example above to pass "Int..." function parameter as an argument to a function that requires "Int..." parameter, and whilst "Int..." function parameter is treated as an array inside the function there could be some internal difference to treat it differently to a normal array (to not allow normal [Int] array passed to "Int..." function parameter).
It is when you go beyond simple case with Int… it becomes an issue. Say, we want a variadic parameter to be a protocol that an Array can confirm too. Now there is no way to know either we want to pass an array as a single argument, or expand to be a multiple arguments, and that’s why syntax for this matters. Without that feature would be incomplete and narrowly applicable.
Assume that these variadic parameters are collected into an array to later be passed to the function, like building a format string. You now limited in this application of an array to collect arguments.
BTW, oddly that this example will compile right now and print accordingly results:
protocol P {}
extension Int: P {}
extension Array: P {}
func foo(_ v: P...) {
print(v)
}
func bar(_ v: P...) {
foo(v)
}
bar(1, 2, 3) // will output [1, 2, 3]
bar([1, 2, 3]) // will output [[1, 2, 3]]
bar([1], [2], [3]) // will output [[1], [2], [3]]
While when you are passing concrete Int... it won't.
And with generics it compiles too, yet output differs:
Hope it won't break anything, since the idea to check protocol and generic came from similar use in a small util I've written around Swift 3 and remembered that the initial case has worked there, so this behaviour has been around for a while I guess.
EDIT: Ok, I misunderstood your original bug report because you started with two examples that work as expected. Yes, it's a bug that the argument value is not wrapped inside of an array here:
protocol P { }
extension Int: P { }
extension Array: P { }
func foo3(_ x: P...) { print("\(x.count) variadic argument(s) to 'foo3'") }
let x: [P] = [1, 2, 3]
foo3(x)