Skip to content

Commit f5ca11f

Browse files
Handling deep nested types
1 parent 208d830 commit f5ca11f

File tree

11 files changed

+424
-291
lines changed

11 files changed

+424
-291
lines changed

compiler/decls.go

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -451,13 +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-
var nestResolver *typeparams.Resolver
455-
if len(inst.TNest) > 0 {
456-
fn := typeparams.FindNestingFunc(inst.Object)
457-
tp := typeparams.SignatureTypeParams(fn.Type().(*types.Signature))
458-
nestResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, tp, inst.TNest, nil)
459-
}
460-
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, originType.TypeParams(), inst.TArgs, nestResolver)
454+
fc.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, inst)
461455
defer func() { fc.typeResolver = nil }()
462456

463457
instanceType := originType
@@ -469,10 +463,7 @@ func (fc *funcContext) newNamedTypeInstDecl(inst typeparams.Instance) (*Decl, er
469463
}
470464
instanceType = instantiated.(*types.Named)
471465
}
472-
if len(inst.TNest) > 0 {
473-
instantiated := nestResolver.Substitute(instanceType)
474-
instanceType = instantiated.(*types.Named)
475-
}
466+
instanceType = fc.typeResolver.Substitute(instanceType).(*types.Named)
476467
}
477468

478469
underlying := instanceType.Underlying()

compiler/expressions.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ func (fc *funcContext) translateExpr(expr ast.Expr) *expression {
531531
case *types.Signature:
532532
return fc.formatExpr("%s", fc.instName(fc.instanceOf(e.X.(*ast.Ident))))
533533
default:
534-
panic(fmt.Errorf(`unhandled IndexExpr: %T`, t))
534+
panic(fmt.Errorf(`unhandled IndexExpr: %T in %T`, t, fc.typeOf(e.X)))
535535
}
536536
case *ast.IndexListExpr:
537537
switch t := fc.typeOf(e.X).Underlying().(type) {

compiler/functions.go

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -48,13 +48,9 @@ func (fc *funcContext) nestedFunctionContext(info *analysis.FuncInfo, inst typep
4848
c.allVars[k] = v
4949
}
5050

51-
if sig.TypeParams().Len() > 0 {
52-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.TypeParams(), inst.TArgs, nil)
53-
} else if sig.RecvTypeParams().Len() > 0 {
54-
c.typeResolver = typeparams.NewResolver(c.pkgCtx.typesCtx, sig.RecvTypeParams(), inst.TArgs, nil)
55-
}
56-
if c.objectNames == nil {
57-
c.objectNames = map[types.Object]string{}
51+
// Use the parent function's resolver unless the function has it's own type arguments.
52+
if !inst.IsTrivial() {
53+
c.typeResolver = typeparams.NewResolver(fc.pkgCtx.typesCtx, inst)
5854
}
5955

6056
// Synthesize an identifier by which the function may reference itself. Since

compiler/internal/analysis/info.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -124,11 +124,7 @@ func (info *Info) newFuncInfoInstances(fd *ast.FuncDecl) []*FuncInfo {
124124

125125
funcInfos := make([]*FuncInfo, 0, len(instances))
126126
for _, inst := range instances {
127-
var resolver *typeparams.Resolver
128-
if sig, ok := obj.Type().(*types.Signature); ok {
129-
tp := typeparams.SignatureTypeParams(sig)
130-
resolver = typeparams.NewResolver(info.typeCtx, tp, inst.TArgs, nil)
131-
}
127+
resolver := typeparams.NewResolver(info.typeCtx, inst)
132128
fi := info.newFuncInfo(fd, inst.Object, inst.TArgs, resolver)
133129
funcInfos = append(funcInfos, fi)
134130
}

compiler/internal/typeparams/collect.go

Lines changed: 25 additions & 154 deletions
Original file line numberDiff line numberDiff line change
@@ -4,143 +4,8 @@ import (
44
"fmt"
55
"go/ast"
66
"go/types"
7-
"strings"
8-
9-
"github.com/gopherjs/gopherjs/compiler/typesutil"
10-
"github.com/gopherjs/gopherjs/internal/govendor/subst"
117
)
128

13-
// Resolver translates types defined in terms of type parameters into concrete
14-
// types, given a mapping from type params to type arguments.
15-
type Resolver struct {
16-
tParams *types.TypeParamList
17-
tArgs []types.Type
18-
parent *Resolver
19-
20-
// subster is the substitution helper that will perform the actual
21-
// substitutions. This maybe nil when there are no substitutions but
22-
// will still usable when nil.
23-
subster *subst.Subster
24-
selMemo map[typesutil.Selection]typesutil.Selection
25-
}
26-
27-
// NewResolver creates a new Resolver with tParams entries mapping to tArgs
28-
// entries with the same index.
29-
func NewResolver(tc *types.Context, tParams *types.TypeParamList, tArgs []types.Type, parent *Resolver) *Resolver {
30-
r := &Resolver{
31-
tParams: tParams,
32-
tArgs: tArgs,
33-
parent: parent,
34-
subster: subst.New(tc, tParams, tArgs),
35-
selMemo: map[typesutil.Selection]typesutil.Selection{},
36-
}
37-
return r
38-
}
39-
40-
// TypeParams is the list of type parameters that this resolver
41-
// (not any parent) will substitute.
42-
func (r *Resolver) TypeParams() *types.TypeParamList {
43-
if r == nil {
44-
return nil
45-
}
46-
return r.tParams
47-
}
48-
49-
// TypeArgs is the list of type arguments that this resolver
50-
// (not any parent) will resolve to.
51-
func (r *Resolver) TypeArgs() []types.Type {
52-
if r == nil {
53-
return nil
54-
}
55-
return r.tArgs
56-
}
57-
58-
// Parent is the resolver for the function or method that this resolver
59-
// is nested in. This may be nil if the context for this resolver is not
60-
// nested in another generic function or method.
61-
func (r *Resolver) Parent() *Resolver {
62-
if r == nil {
63-
return nil
64-
}
65-
return r.parent
66-
}
67-
68-
// Substitute replaces references to type params in the provided type definition
69-
// with the corresponding concrete types.
70-
func (r *Resolver) Substitute(typ types.Type) types.Type {
71-
if r == nil || typ == nil {
72-
return typ // No substitutions to be made.
73-
}
74-
typ = r.subster.Type(typ)
75-
typ = r.parent.Substitute(typ)
76-
return typ
77-
}
78-
79-
// SubstituteAll same as Substitute, but accepts a TypeList are returns
80-
// substitution results as a slice in the same order.
81-
func (r *Resolver) SubstituteAll(list *types.TypeList) []types.Type {
82-
result := make([]types.Type, list.Len())
83-
for i := range result {
84-
result[i] = r.Substitute(list.At(i))
85-
}
86-
return result
87-
}
88-
89-
// SubstituteSelection replaces a method of field selection on a generic type
90-
// defined in terms of type parameters with a method selection on a concrete
91-
// instantiation of the type.
92-
func (r *Resolver) SubstituteSelection(sel typesutil.Selection) typesutil.Selection {
93-
if r == nil || sel == nil {
94-
return sel // No substitutions to be made.
95-
}
96-
if concrete, ok := r.selMemo[sel]; ok {
97-
return concrete
98-
}
99-
100-
switch sel.Kind() {
101-
case types.MethodExpr, types.MethodVal, types.FieldVal:
102-
recv := r.Substitute(sel.Recv())
103-
if types.Identical(recv, sel.Recv()) {
104-
return sel // Non-generic receiver, no substitution necessary.
105-
}
106-
107-
// Look up the method on the instantiated receiver.
108-
pkg := sel.Obj().Pkg()
109-
obj, index, _ := types.LookupFieldOrMethod(recv, true, pkg, sel.Obj().Name())
110-
if obj == nil {
111-
panic(fmt.Errorf("failed to lookup field %q in type %v", sel.Obj().Name(), recv))
112-
}
113-
typ := obj.Type()
114-
115-
if sel.Kind() == types.MethodExpr {
116-
typ = typesutil.RecvAsFirstArg(typ.(*types.Signature))
117-
}
118-
concrete := typesutil.NewSelection(sel.Kind(), recv, index, obj, typ)
119-
r.selMemo[sel] = concrete
120-
return concrete
121-
default:
122-
panic(fmt.Errorf("unexpected selection kind %v: %v", sel.Kind(), sel))
123-
}
124-
}
125-
126-
// String gets a strings representation of the resolver for debugging.
127-
func (r *Resolver) String() string {
128-
if r == nil {
129-
return `{}`
130-
}
131-
132-
parts := make([]string, 0, len(r.tArgs))
133-
for i, ta := range r.tArgs {
134-
parts = append(parts, fmt.Sprintf("%s->%s", r.tParams.At(i), ta))
135-
}
136-
137-
nestStr := ``
138-
if r.parent != nil {
139-
nestStr = r.parent.String() + `:`
140-
}
141-
return nestStr + `{` + strings.Join(parts, `, `) + `}`
142-
}
143-
1449
// visitor implements ast.Visitor and collects instances of generic types and
14510
// functions into an InstanceSet.
14611
//
@@ -151,7 +16,9 @@ type visitor struct {
15116
instances *PackageInstanceSets
15217
resolver *Resolver
15318
info *types.Info
154-
tNest []types.Type // The type arguments for a nested context.
19+
20+
nestTParams *types.TypeParamList // The type parameters for a nested context.
21+
nestTArgs []types.Type // The type arguments for a nested context.
15522
}
15623

15724
var _ ast.Visitor = &visitor{}
@@ -195,12 +62,14 @@ func (c *visitor) visitInstance(ident *ast.Ident, inst types.Instance) {
19562

19663
// If the object is defined in the same scope as the instance,
19764
// then we apply the current nested type arguments.
198-
var tNest []types.Type
65+
var nestTParams *types.TypeParamList
66+
var nestTArgs []types.Type
19967
if obj.Parent().Contains(ident.Pos()) {
200-
tNest = c.tNest
68+
nestTParams = c.nestTParams
69+
nestTArgs = c.nestTArgs
20170
}
20271

203-
c.addInstance(obj, tArgs, tNest)
72+
c.addInstance(obj, tArgs, nestTParams, nestTArgs)
20473
}
20574

20675
func (c *visitor) visitNestedType(obj types.Object) {
@@ -222,12 +91,12 @@ func (c *visitor) visitNestedType(obj types.Object) {
22291
return
22392
}
22493

225-
c.addInstance(obj, nil, c.resolver.TypeArgs())
94+
c.addInstance(obj, nil, c.resolver.TypeParams(), c.resolver.TypeArgs())
22695
}
22796

228-
func (c *visitor) addInstance(obj types.Object, tArgList *types.TypeList, tNest []types.Type) {
97+
func (c *visitor) addInstance(obj types.Object, tArgList *types.TypeList, nestTParams *types.TypeParamList, nestTArgs []types.Type) {
22998
tArgs := c.resolver.SubstituteAll(tArgList)
230-
if isGeneric(tArgs...) {
99+
if isGeneric(nestTParams, tArgs) {
231100
// Skip any instances that still have type parameters in them after
232101
// substitution. This occurs when a type is defined while nested
233102
// in a generic context and is not fully instantiated yet.
@@ -238,7 +107,7 @@ func (c *visitor) addInstance(obj types.Object, tArgList *types.TypeList, tNest
238107
c.instances.Add(Instance{
239108
Object: obj,
240109
TArgs: tArgs,
241-
TNest: tNest,
110+
TNest: nestTArgs,
242111
})
243112

244113
if t, ok := obj.Type().(*types.Named); ok {
@@ -247,7 +116,7 @@ func (c *visitor) addInstance(obj types.Object, tArgList *types.TypeList, tNest
247116
c.instances.Add(Instance{
248117
Object: method.Origin(),
249118
TArgs: tArgs,
250-
TNest: tNest,
119+
TNest: nestTArgs,
251120
})
252121
}
253122
}
@@ -358,12 +227,13 @@ func (c *Collector) Scan(pkg *types.Package, files ...*ast.File) {
358227
}
359228

360229
func (c *Collector) scanSignature(inst Instance, typ *types.Signature, objMap map[types.Object]ast.Node) {
361-
tParams := SignatureTypeParams(typ)
362230
v := visitor{
363231
instances: c.Instances,
364-
resolver: NewResolver(c.TContext, tParams, inst.TArgs, nil),
232+
resolver: NewResolver(c.TContext, inst),
365233
info: c.Info,
366-
tNest: inst.TArgs,
234+
235+
nestTParams: SignatureTypeParams(typ),
236+
nestTArgs: inst.TArgs,
367237
}
368238
ast.Walk(&v, objMap[inst.Object])
369239
}
@@ -377,18 +247,19 @@ func (c *Collector) scanNamed(inst Instance, typ *types.Named, objMap map[types.
377247
return
378248
}
379249

380-
var nestResolver *Resolver
381-
if len(inst.TNest) > 0 {
382-
fn := FindNestingFunc(inst.Object)
383-
tp := SignatureTypeParams(fn.Type().(*types.Signature))
384-
nestResolver = NewResolver(c.TContext, tp, inst.TNest, nil)
250+
var nestTParams *types.TypeParamList
251+
nest := FindNestingFunc(obj)
252+
if nest != nil {
253+
nestTParams = SignatureTypeParams(nest.Type().(*types.Signature))
385254
}
386255

387256
v := visitor{
388257
instances: c.Instances,
389-
resolver: NewResolver(c.TContext, typ.TypeParams(), inst.TArgs, nestResolver),
258+
resolver: NewResolver(c.TContext, inst),
390259
info: c.Info,
391-
tNest: inst.TNest,
260+
261+
nestTParams: nestTParams,
262+
nestTArgs: inst.TNest,
392263
}
393264
ast.Walk(&v, node)
394265
}

0 commit comments

Comments
 (0)