-
Notifications
You must be signed in to change notification settings - Fork 569
Handling nested type arguments #1374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
I think this is all good, but I would like to better understand this:
Seen by whom? I think it's important that
Could you elaborate on this? It sounds like the problem is that when we are trying to compute type arguments for |
@nevkontakte Sorry, I wasn't very clear in my comment about the pointers. Instead of the example from the comment, lets use this one: func Foo[T any]() {
type Bar[U any] struct {
X T
Y U
}
} In the above we have the type I had to fix the code checking for concrete types in the visitor, so that it wouldn't have false negatives caused by the underlying types. But I still wanted to detect that When substituting This became an issue with how I had updated the Overall this means that the whole underlying type was "substituted lazily" including the type arguments themselves. To use it, we'd have to keep a map from type parameters to type arguments, including the implicit ones from the nest, so we can substitute while processing the underlying types. Which is great since the code you had already written (i.e. the replacer) already did that; I just had to adjust how I was thinking about nested types from the prior PR to this PR and adjust the code I wrote to match these changes. P.S. I think what tripped me up was that the substr wanted to fully substitute in most cases but in some cases with named types they used |
Ah, I see now, that makes sense. As an aside, in other places we haven't shied away from adding more data into |
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
Note: While working on the next PR, #1375, I discovered there is an issue with
FindNestingFunc
. It doesn't check inside methods. I thought the declarations in the scopes would include methods, I guess I should have actually checked because they don't. I'll fix that in #1375 since it doesn't cause any issues with generics behind a flag.