Support type var splats inside Tuple during generic parameter substitution #10232
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #8520.
Consider the example from there:
When
Foo(String, Int32, Bool)
is instantiated, the compiler requests the type of the@action
instance variable; this must be a type, not an AST node. (Generic type splats inside AST nodes are already supported, so the type restriction of#initialize
works as intended.) The compiler knows the following type parameter substitutions:R
->String
A
->Tuple(Int32, Bool)
It then proceeds to perform type parameter substitution on
Proc(*A, R)
. The compiler also "instiantiates" an unboundCrystal::GenericInstanceType
from this expression, even if the type arguments are not known in advance. This "type" has the following type vars:T
(fromProc
's definition) ->Tuple(*A)
(thisA
is from the outerFoo
)R
(fromProc
's definition) ->R
(from the outerFoo
)The compiler doesn't know how to substitute
A
->Tuple(Int32, Bool)
intoTuple(*A)
, as it previously assumes there are no type var splats inside an unboundTuple(...)
expression; this is what this PR implements. AsCrystal::TupleInstanceType
backs all generic type var splats, including ones in included/inherited types, this PR also makes the following possible:The "more args" specs are written in such a way that splat expansions in unbound generic expressions always correspond to splat parameters in the generic definitions; see #3649 (comment) for the rationale behind this.