[Idea] Splat def parameters into array

Splat parameters are currently moved into a tuple.

def foo(*x)
  x
end

typeof(foo(1, true)) # => Tuple(Int32, Bool)

It would be nice if splatting could support other collection types, including dynamically sized ones. This is not useful for forwarding parameters, one of the primary purposes of splat tuples.
But it is convenient for a neat syntax where the def defines the collection type and the caller doesn’t have to worry about which type to chose. The def can own it which could enable performance optimizations.

A use case for that is the new process spawn API from RFC 25.

Example:

def foo(*x : *Array(Bool | Int32))
  x
end

typeof(foo(1, true)) # => Array(Bool | Int32)

The call foo(1, true) would expand to an implicit array-like literal, equivalent to foo(Array(Bool | Int32){1, true}).

I extracted the thread about #values_at into Splatting in `#values_at` because it’s not directly related to array splatting.

The key point for this discussion:

Splat parameters should be able to receive splat arguments (and forward them):

def foo(*x : *Array(Bool | Int32))
  x
end

tuple = {1, true}
foo(*tuple) # this call must create a new array from the tuple

ary = [1, true]
foo(*ary) # this call should pass `ary` and not create a new array

Question is how this should work if the types to not match exactly? (e.g. if the argument is Array(Int32)?

But this is to be restricted to a limited number of builtin types? Or how would the compiler know how to create and populate instances of user defined collection types?

For example, the compiler would rewrite these arguments:

foo(1, true)

to create an array-like literal and pass that instead.

foo(Array(Bool | Int32){1, true})

Which then further expands to something like this:

%temp = Array(Bool | Int32).new
%temp << 1
%temp << true
foo(%temp)

So custom types are supported as long as they support array-like literal construction.