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.
Summary
Adding type parameters from a function into the nested types inside of that function. For example:
The type
Bar
is concrete (i.e. not generic) however it acts like it is generic because it is nested in a generic function. If the function is called likeFoo[string]()
thenBar
innately is different from if the function is called likeFoo[int]()
. The nesting type parameters is shown likeBar[T;]
and instantiated likeBar[string;]
andBar[int;]
.In Go the
;
in the type parameters isn't present if the nested type is concrete.Baz
is generic meaning the;
indicates the separation between the nested type parameters and the objects own type parameters. For example ifBaz[string]{}
is expressed inside ofFoo[int]
, then aBaz[int; string]
is instantiated. IfBaz[T]{}
is expressed inside ofFoo[X]
, then aBaz[X; X]
is instantiated.When creating instances for a nested type, all combinations of nest function instances and nesting type instances need to be determined. For example if
Foo
has the instancesFoo[string]
andFoo[int]
, andBaz
has the instancesBaz[bool]
andBaz[string]
, then the resolved instances forBaz
areBaz[string; bool]
,Baz[string; string]
,Baz[int; bool]
, andBaz[int; string]
. While reading the instances fromtypes.Info
, an instance may have a type parameter in it, e.g.Baz[T]
. We replace the type parameter with the nest function's instance type arguments, meaningBaz[T]
resolves toBaz[int; int]
andBaz[string; string]
, but notBaz[int; string]
norBaz[string; int]
.Note: I used
TNest
or similar to store the type arguments from the nest function or method as a separate set fromTArgs
. This is different from what Go does which is using an index for the "implicit" type arguments to differentiate between the two parts, seen here. I felt it was easier to maintain and to fit into the existing code better than using an index.This is related to #1013 and #1270
Future Work / Known Issues
Fixing Nested Type Arguments
This change does not include a fix for 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 beBar[int;]
withstruct { X int }
.I didn't fix this issue yet because it feels very unlikely, although possible, to happen, and I found it while finishing up this PR. So, instead of delaying this initial work on nested types, I left some tests that demonstrate the issue and skipped them with a
TODO(grantnelson-wf)
comment.Fixing DCE
This change does not include an update to the DCE to remove unused instances caused by nested types. For example:
In the above code the instances
Foo[string]
andFoo[int]
are created, thenFoo[int]
is found to be dead and eliminated. However, the instanceBar[string;]
andBar[int;]
are created by their respective nest function instances. Right now our DCE doesn't take into account the nesting type parameters so will see all instances ofBar
as alive because"Bar"
is used in the aliveFoo[string]
. This leaves the dead codeBar[int]
, also seen as"Bar"
, alive when it should be eliminated.A following ticket will fix the DCE to take into acount the nesting type parameters so that dead nested types will be properly removed.
Numbering Nested Types Issue
This change does not include any of the numbering of types like Go does. For example:
When the types returned from
Foo
andBar
are printed, they aremain.Biz[main.Baz·1]
andmain.Biz[main.Baz·2]
respectively. The·1
and·2
are indications of which declaration ofBaz
is being used. They are not shown in all cases and never show for package level declarations. The numbering is applied in the order the files are parsed and nested types are declared in those files.The number increases monotonically with each new type declaration regardless of their name and type, meaning if the
Baz
inBar
is changed totype Cat interface{}
andBiz
is instantiated withCat
inBar
, the types aremain.Biz[main.Baz·1]
andmain.Biz[main.Cat·2]
. The type fromFoo
didn't change andCat
is still denoted with a·2
since it is the second nested type.Since these numbers aren't being collected nor printed, we can not remove
typeparam/nested.go
from the known failures of the Gorepo Tests yet. The test will not pass because the outputs will not match without the nested type numbering. So, not only are does that test hit some "Nested Type Arguments" (themain.U
's aren't being instantiated correctly), but the difference in the outputs looks like: