Handling nested type arguments #1374
Open
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.
This fixes some issues. See "Fixing Nested Type Arguments" in summary of #1370.
This also cleans up some of the resolver code to make it easier to prepare for resolution of types.
This change fixes when a type argument itself is nested. For example:
The
Baz
is instantiated correctly using the nesting type argument forFoo
and the argument given to itBar
. However,Bar
has not been instantiated correctly with the nesting type argument forFoo
, meaningBar
is still generic with the underlying type ofstruct { X T }
. IfFoo[int]()
is called, theBar
used for the type argument forBaz
needs to be understood to beBar[int;]
withstruct { X int }
.Initially I intended to change the substitution to always modify the underlying struct in a named type. However, that causes problems in the instance map since the instance map uses the object pointer as a key and the fully substituted object has a different pointer. Instead, following how
types.Instantiate
works, I made the instances allow for lazy substitution, i.e. unsubstituted type parameters are allowed in the context of a named type with those type parameters and properly substituted type arguments.In the above example this would mean
Bar
would be seen asstruct { X T }
but that is now acceptable to the code since it is in context whereT
is defined. This is acceptable since the transformation code later on continues to substitute as needed, so theT
will be substituted toint
before it is used.The only draw back to not fully substituting the underlying types is that when printing
Baz[Bar]
inFoo[int]
; Go will outputBaz[Bar[int;]]
(ignoring the dot numbering and the extra;
), whilst now, GopherJS will outputBaz[Bar]
without properly indicating the nesting context. We can swing back around to this later, I didn't want get stuck on this too long when it is rare that nested type arguments or deep nesting is used in normal code.This is related to #1013 and #1270