Skip to content

Commit 6581339

Browse files
Using TypeParamLists
1 parent 9783473 commit 6581339

File tree

8 files changed

+113
-13
lines changed

8 files changed

+113
-13
lines changed

compiler/decls.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -451,7 +451,7 @@ func (fc *funcContext) newNamedTypeVarDecl(obj *types.TypeName) *Decl {
451451
func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, error) {
452452
originType := inst.Object.Type().(*types.Named)
453453

454-
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, typeparams.ToSlice(originType.TypeParams()), inst.TArgs)
454+
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, originType.TypeParams(), inst.TArgs)
455455
defer func() { fc.typeResolver = nil }()
456456

457457
instanceType := originType

compiler/functions.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,9 @@ func (fc *funcContext) nestedFunctionContext(info *analysis.FuncInfo, inst typep
4949
}
5050

5151
if sig.TypeParams().Len() > 0 {
52-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, typeparams.ToSlice(sig.TypeParams()), inst.TArgs)
52+
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.TypeParams(), inst.TArgs)
5353
} else if sig.RecvTypeParams().Len() > 0 {
54-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, typeparams.ToSlice(sig.RecvTypeParams()), inst.TArgs)
54+
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.RecvTypeParams(), inst.TArgs)
5555
}
5656
if c.objectNames == nil {
5757
c.objectNames = map[types.Object]string{}

compiler/internal/analysis/info.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ func (info *Info) newFuncInfoInstances(fd *ast.FuncDecl) []*FuncInfo {
126126
for _, inst := range instances {
127127
var resolver *typeparams.Resolver
128128
if sig, ok := obj.Type().(*types.Signature); ok {
129-
tp := typeparams.ToSlice(typeparams.SignatureTypeParams(sig))
129+
tp := typeparams.SignatureTypeParams(sig)
130130
resolver = typeparams.NewResolver(info.typeCtx, tp, inst.TArgs)
131131
}
132132
fi := info.newFuncInfo(fd, inst.Object, inst.TArgs, resolver)

compiler/internal/typeparams/collect.go

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ type Resolver struct {
1818

1919
// NewResolver creates a new Resolver with tParams entries mapping to tArgs
2020
// entries with the same index.
21-
func NewResolver(tc *types.Context, tParams []*types.TypeParam, tArgs []types.Type) *Resolver {
21+
func NewResolver(tc *types.Context, tParams *types.TypeParamList, tArgs []types.Type) *Resolver {
2222
r := &Resolver{
2323
subster: subst.New(tc, nil, tParams, tArgs),
2424
selMemo: map[typesutil.Selection]typesutil.Selection{},
@@ -82,6 +82,13 @@ func (r *Resolver) SubstituteSelection(sel typesutil.Selection) typesutil.Select
8282
}
8383
}
8484

85+
func (r *Resolver) String() string {
86+
if r == nil || r.subster == nil {
87+
return "nil"
88+
}
89+
return r.subster.String()
90+
}
91+
8592
// ToSlice converts TypeParamList into a slice with the same order of entries.
8693
func ToSlice(tpl *types.TypeParamList) []*types.TypeParam {
8794
result := make([]*types.TypeParam, tpl.Len())
@@ -276,7 +283,7 @@ func (c *Collector) Scan(pkg *types.Package, files ...*ast.File) {
276283
inst, _ := iset.next()
277284
switch typ := inst.Object.Type().(type) {
278285
case *types.Signature:
279-
tParams := ToSlice(SignatureTypeParams(typ))
286+
tParams := SignatureTypeParams(typ)
280287
v := visitor{
281288
instances: c.Instances,
282289
resolver: NewResolver(c.TContext, tParams, inst.TArgs),
@@ -290,7 +297,7 @@ func (c *Collector) Scan(pkg *types.Package, files ...*ast.File) {
290297
obj := typ.Obj()
291298
v := visitor{
292299
instances: c.Instances,
293-
resolver: NewResolver(c.TContext, ToSlice(typ.TypeParams()), inst.TArgs),
300+
resolver: NewResolver(c.TContext, typ.TypeParams(), inst.TArgs),
294301
info: c.Info,
295302
}
296303
fmt.Printf("[Start] Named: %s\n", inst.TypeString()) // TODO(grantnelson-wf): remove

compiler/internal/typeparams/collect_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func TestVisitor(t *testing.T) {
194194
descr: "generic function",
195195
resolver: NewResolver(
196196
types.NewContext(),
197-
ToSlice(lookupType("entry2").(*types.Signature).TypeParams()),
197+
lookupType("entry2").(*types.Signature).TypeParams(),
198198
[]types.Type{lookupType("B")},
199199
),
200200
node: lookupDecl("entry2"),
@@ -203,7 +203,7 @@ func TestVisitor(t *testing.T) {
203203
descr: "generic method",
204204
resolver: NewResolver(
205205
types.NewContext(),
206-
ToSlice(lookupType("entry3.method").(*types.Signature).RecvTypeParams()),
206+
lookupType("entry3.method").(*types.Signature).RecvTypeParams(),
207207
[]types.Type{lookupType("C")},
208208
),
209209
node: lookupDecl("entry3.method"),
@@ -222,7 +222,7 @@ func TestVisitor(t *testing.T) {
222222
descr: "generic type declaration",
223223
resolver: NewResolver(
224224
types.NewContext(),
225-
ToSlice(lookupType("entry3").(*types.Named).TypeParams()),
225+
lookupType("entry3").(*types.Named).TypeParams(),
226226
[]types.Type{lookupType("D")},
227227
),
228228
node: lookupDecl("entry3"),
@@ -492,7 +492,7 @@ func TestResolver_SubstituteSelection(t *testing.T) {
492492
info, pkg := f.Check("pkg/test", file)
493493

494494
method := srctesting.LookupObj(pkg, "g.Method").(*types.Func).Type().(*types.Signature)
495-
resolver := NewResolver(nil, ToSlice(method.RecvTypeParams()), []types.Type{srctesting.LookupObj(pkg, "x").Type()})
495+
resolver := NewResolver(nil, method.RecvTypeParams(), []types.Type{srctesting.LookupObj(pkg, "x").Type()})
496496

497497
if l := len(info.Selections); l != 1 {
498498
t.Fatalf("Got: %d selections. Want: 1", l)

internal/govendor/subst/export.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package subst
55

66
import (
7+
"fmt"
78
"go/token"
89
"go/types"
910
)
@@ -14,7 +15,9 @@ import (
1415

1516
// Subster performs type parameter substitution.
1617
type Subster struct {
17-
impl *subster
18+
impl *subster
19+
tParams []*types.TypeParam
20+
tArgs []types.Type
1821
}
1922

2023
// New creates a new Subster with a given list of type parameters and matching args.
@@ -27,6 +30,8 @@ type Subster struct {
2730
// - Given type arguments should not contain any types in the type parameters.
2831
// - The internal implementation is not concurrency-safe.
2932
func New(tc *types.Context, fn *types.Func, tParams *types.TypeParamList, tArgs []types.Type) *Subster {
33+
assert(tParams.Len() == len(tArgs), "New() argument count must match")
34+
3035
if tParams.Len() == 0 && len(tArgs) == 0 {
3136
return nil
3237
}
@@ -50,3 +55,24 @@ func (s *Subster) Type(typ types.Type) types.Type {
5055
}
5156
return s.impl.typ(typ)
5257
}
58+
59+
// Params returns the type parameters being substituted.
60+
func (s *Subster) Params() []*types.TypeParam {
61+
if s == nil {
62+
return nil
63+
}
64+
return s.tParams
65+
}
66+
67+
// Args returns the type arguments to substitute for the
68+
// corresponding type parameter at the same index.
69+
func (s *Subster) Args() []types.Type {
70+
if s == nil {
71+
return nil
72+
}
73+
return s.tArgs
74+
}
75+
76+
func (s *Subster) String() string {
77+
return fmt.Sprintf("%v->%v", s.Params(), s.Args())
78+
}

internal/govendor/subst/export_test.go

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import (
88
"testing"
99
)
1010

11-
func TestNestedSubst(t *testing.T) {
11+
func TestNestedSubstInGenericFunction(t *testing.T) {
1212
const source = `
1313
package P
1414
@@ -71,6 +71,68 @@ func TestNestedSubst(t *testing.T) {
7171
}
7272
}
7373

74+
func TestNestedSubstInConcreteFunction(t *testing.T) {
75+
const source = `
76+
package P
77+
78+
func A(){
79+
type C[U any] struct{X T; Y U}
80+
}`
81+
82+
fSet := token.NewFileSet()
83+
f, err := parser.ParseFile(fSet, "hello.go", source, 0)
84+
if err != nil {
85+
t.Fatal(err)
86+
}
87+
88+
var conf types.Config
89+
pkg, err := conf.Check("P", fSet, []*ast.File{f}, nil)
90+
if err != nil {
91+
t.Fatal(err)
92+
}
93+
94+
for _, test := range []struct {
95+
fnName string // the name of the nesting function
96+
fnArgs []string // type expressions of args for the nesting function
97+
stName string // the name of the named type
98+
stArgs []string // type expressions of args for the named type
99+
want string // expected underlying value after substitution
100+
}{
101+
{
102+
fnName: "A", fnArgs: []string{"int"},
103+
stName: "B", stArgs: []string{},
104+
want: "struct{X int}",
105+
},
106+
} {
107+
ctxt := types.NewContext()
108+
109+
fnGen, _ := pkg.Scope().Lookup(test.fnName).(*types.Func)
110+
if fnGen == nil {
111+
t.Fatal("Failed to find the function " + test.fnName)
112+
}
113+
fnType := fnGen.Type().(*types.Signature)
114+
fnArgs := evalTypeList(t, fSet, pkg, test.fnArgs)
115+
fnInst, err := types.Instantiate(ctxt, fnType, fnArgs, true)
116+
if err != nil {
117+
t.Fatalf("Failed to instantiate %s: %v", fnType, err)
118+
}
119+
fnFunc := types.NewFunc(fnGen.Pos(), pkg, fnGen.Name(), fnInst.(*types.Signature))
120+
121+
stType, _ := fnFunc.Scope().Lookup(test.stName).Type().(*types.Named)
122+
if stType == nil {
123+
t.Fatal("Failed to find the object " + test.fnName + " in function " + test.fnName)
124+
}
125+
stArgs := evalTypeList(t, fSet, pkg, test.stArgs)
126+
127+
stSubst := New(types.NewContext(), fnFunc, stType.TypeParams(), stArgs)
128+
stInst := stSubst.Type(stType.Underlying())
129+
130+
if got := stInst.String(); got != test.want {
131+
t.Errorf("subst{%v->%v}.typ(%s) = %v, want %v", test.stName, test.stArgs, stType.Underlying(), got, test.want)
132+
}
133+
}
134+
}
135+
74136
func evalType(t *testing.T, fSet *token.FileSet, pkg *types.Package, expr string) types.Type {
75137
tv, err := types.Eval(fSet, pkg, 0, expr)
76138
if err != nil {

internal/govendor/subst/util.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ func changeRecv(s *types.Signature, recv *types.Var) *types.Signature {
3030
// obj must not be a method or a field.
3131
// From https://cs.opensource.google/go/x/tools/+/refs/tags/v0.32.0:go/ssa/util.go;l=145
3232
func declaredWithin(obj types.Object, fn *types.Func) bool {
33+
// GOPHERJS change: Made fn optionally nil.
34+
if fn == nil {
35+
return false
36+
}
37+
3338
if obj.Pos() != token.NoPos {
3439
return fn.Scope().Contains(obj.Pos()) // trust the positions if they exist.
3540
}

0 commit comments

Comments
 (0)