Skip to content

Commit 51c6a03

Browse files
Working on resolver improvements
1 parent 6a4f2ca commit 51c6a03

File tree

2 files changed

+32
-16
lines changed

2 files changed

+32
-16
lines changed

compiler/internal/typeparams/collect.go

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,21 @@ import (
1212

1313
// Resolver translates types defined in terms of type parameters into concrete
1414
// types, given a mapping from type params to type arguments.
15+
//
16+
// Generic types that have no type arguments applied will have the type parameters
17+
// substituted, however the type arguments will not be applied to instantiate
18+
// the type. For example, given `func Foo[T any]() { type Bar[U *T] struct { x T; y U } }`,
19+
// and if `Foo[int]` is used as the root for the resolver, then `Bar[U *T]` will
20+
// be substituted to create the generic `Bar[U *int] struct { x int; y U }`,
21+
// and the generic (because of the `T`) `Bar[bool] struct { x T; y bool}` will
22+
// be substituted to create the concrete `Bar[bool] struct { x int; y bool }`.
23+
// Typically the instantiated type from `info.Instances` should be substituted
24+
// to get the concrete type.
1525
type Resolver struct {
26+
tc *types.Context
1627
tParams *types.TypeParamList
1728
tArgs []types.Type
18-
root Instance // The root instance that this resolver is based on.
29+
root Instance
1930

2031
// subster is the substitution helper that will perform the actual
2132
// substitutions. This maybe nil when there are no substitutions but
@@ -65,6 +76,7 @@ func NewResolver(tc *types.Context, root Instance) *Resolver {
6576
}
6677

6778
return &Resolver{
79+
tc: tc,
6880
tParams: tParams,
6981
tArgs: root.TArgs,
7082
root: root,
@@ -257,8 +269,7 @@ func (c *visitor) addInstance(obj types.Object, tArgList *types.TypeList, tNest
257269
TArgs: tArgs,
258270
TNest: tNest,
259271
}.String()) // TODO(grantnelson-wf): REMOVE
260-
fmt.Printf("\tresolver: %s\n", c.resolver.String()) // TODO(grantnelson-wf): REMOVE
261-
fmt.Printf("\troot: %s\n", c.resolver.root.String()) // TODO(grantnelson-wf): REMOVE
272+
fmt.Printf("\tresolver: %s\n", c.resolver.String()) // TODO(grantnelson-wf): REMOVE
262273
for i := 0; i < len(tArgs); i++ {
263274
fmt.Printf("\t%d: (%T) %s => %s\n", i, tArgs[i], tArgs[i], tArgs[i].Underlying()) // TODO(grantnelson-wf): REMOVE
264275
}

compiler/internal/typeparams/collect_test.go

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -685,12 +685,6 @@ func TestCollector_NestedRecursiveTypeParams(t *testing.T) {
685685
}
686686

687687
func TestCollector_NestedTypeParams(t *testing.T) {
688-
// TODO(grantnelson-wf): This test is failing because the type parameters
689-
// inside of U are not being resolved to concrete types. This is because
690-
// when instantiating X in the collector, we are not resolving the
691-
// nested type of U that is X's type argument. This leave the A in U
692-
// as a type parameter instead of resolving it to string.
693-
694688
// This is based off of part of go1.19.13/test/typeparam/nested.go
695689
src := `package test
696690
func F[A any]() any {
@@ -704,24 +698,33 @@ func TestCollector_NestedTypeParams(t *testing.T) {
704698
`
705699

706700
f := srctesting.New(t)
701+
tc := types.NewContext()
707702
file := f.Parse(`test.go`, src)
708703
info, pkg := f.Check(`test`, file)
709704

710705
c := Collector{
711-
TContext: types.NewContext(),
706+
TContext: tc,
712707
Info: info,
713708
Instances: &PackageInstanceSets{},
714709
}
715710
c.Scan(pkg, file)
716711

717712
uAny := srctesting.LookupObj(pkg, `F.U`)
718-
uInt, err := types.Instantiate(types.NewContext(), uAny.Type(), []types.Type{types.Typ[types.Int]}, true)
713+
resolver := NewResolver(tc, Instance{
714+
Object: uAny,
715+
TNest: []types.Type{types.Typ[types.Int]},
716+
TArgs: []types.Type{types.Typ[types.Bool]},
717+
})
718+
// Substitute will only substitute type parameters in generic types but
719+
// will not instantiate any generic type by applying the type arguments,
720+
// therefore we need to instantiate first.
721+
uBool, err := types.Instantiate(tc, uAny.Type(), []types.Type{types.Typ[types.Bool]}, true)
719722
if err != nil {
720-
t.Fatalf("Failed to instantiate U[int]: %v", err)
723+
t.Fatalf("Failed to instantiate U[bool]: %v", err)
721724
}
722-
//TODO(grantnelson-wf): Need to instantiate uInt to replace `A` with `int` in the struct.
723-
if isGeneric(uInt) {
724-
t.Errorf("Expected uInt to be non-generic, got %v", uInt.Underlying())
725+
uIntBool := resolver.Substitute(uBool)
726+
if isGeneric(uIntBool) {
727+
t.Errorf("Expected uInt to be concrete, got %v:%v", uIntBool, uIntBool.Underlying())
725728
}
726729

727730
want := []Instance{
@@ -735,13 +738,15 @@ func TestCollector_NestedTypeParams(t *testing.T) {
735738
}, {
736739
Object: srctesting.LookupObj(pkg, `F.T`),
737740
TNest: []types.Type{types.Typ[types.Int]},
738-
TArgs: []types.Type{uInt}, // TODO(grantnelson-wf): This still had a type param in it that needs to be resolved.
741+
TArgs: []types.Type{uIntBool},
739742
},
740743
}
741744
got := c.Instances.Pkg(pkg).Values()
742745
if diff := cmp.Diff(want, got, instanceOpts()); diff != `` {
743746
t.Errorf("Instances from Collector contain diff (-want,+got):\n%s", diff)
744747
}
748+
749+
t.Fail()
745750
}
746751

747752
func evalTypeArgs(t *testing.T, fSet *token.FileSet, pkg *types.Package, expr string) []types.Type {

0 commit comments

Comments
 (0)