aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-09-06 16:25:43 -0700
committerDan Scales <danscales@google.com>2021-09-07 20:37:05 +0000
commit80783558b06741beaf41dbd198013fe3a13c9ad2 (patch)
tree5a2b8582afba8399f5df09c5b93818244870808f /src/cmd/compile/internal/noder
parent23f4f0db682fad0c8d61a5b5cdbdbad4cf1cd41f (diff)
downloadgo-80783558b06741beaf41dbd198013fe3a13c9ad2.tar.xz
cmd/compile: make sure imported instantiated types have their methods created
We should be putting a newly instantiated imported type in Instantiate/doInst onto the instTypeList, so its methods/dictionaries are instantiated. To do this, we needed a more general way to add a type to instTypeList, so add NeedInstType(), analogous to NeedRuntimeType(). This has the extra advantage that now all types created by the type substituter are added to instTypeList without any extra code, which was easy to forget. doInst() now correctly calls NeedInstType(). This is a bit aggressive, since a fully instantiated type in a generic function/method may never be used, if the generic method is never instantiated in the local package. But it should be fairly uncommon for a generic method to mention a fully instantiated type (but it does happen in this bug). Fixes both cases mentioned in the bug. Fixed #48185 Change-Id: I19b5012dfac17e306c8005f8595a648b0ab280d0 Reviewed-on: https://go-review.googlesource.com/c/go/+/347909 Trust: Dan Scales <danscales@google.com> Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder')
-rw-r--r--src/cmd/compile/internal/noder/expr.go1
-rw-r--r--src/cmd/compile/internal/noder/irgen.go3
-rw-r--r--src/cmd/compile/internal/noder/stencil.go68
-rw-r--r--src/cmd/compile/internal/noder/types.go6
4 files changed, 34 insertions, 44 deletions
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go
index 863acf587d..7dbbc88f8f 100644
--- a/src/cmd/compile/internal/noder/expr.go
+++ b/src/cmd/compile/internal/noder/expr.go
@@ -237,7 +237,6 @@ func (g *irgen) substType(typ *types.Type, tparams *types.Type, targs []ir.Node)
Targs: targs1,
}
newt := ts.Typ(typ)
- g.instTypeList = append(g.instTypeList, ts.InstTypeList...)
return newt
}
diff --git a/src/cmd/compile/internal/noder/irgen.go b/src/cmd/compile/internal/noder/irgen.go
index fd29c51c8a..a67b3994da 100644
--- a/src/cmd/compile/internal/noder/irgen.go
+++ b/src/cmd/compile/internal/noder/irgen.go
@@ -152,9 +152,6 @@ type irgen struct {
// types which we need to finish, by doing g.fillinMethods.
typesToFinalize []*typeDelayInfo
- // Fully-instantiated generic types whose methods should be instantiated
- instTypeList []*types.Type
-
dnum int // for generating unique dictionary variables
// Map from generic function to information about its type params, derived
diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go
index 3b15ac2c97..1c22fc2ac0 100644
--- a/src/cmd/compile/internal/noder/stencil.go
+++ b/src/cmd/compile/internal/noder/stencil.go
@@ -481,39 +481,43 @@ func (g *irgen) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
}
// instantiateMethods instantiates all the methods (and associated dictionaries) of
-// all fully-instantiated generic types that have been added to g.instTypeList.
+// all fully-instantiated generic types that have been added to typecheck.instTypeList.
+// It continues until no more types are added to typecheck.instTypeList.
func (g *irgen) instantiateMethods() {
- for i := 0; i < len(g.instTypeList); i++ {
- typ := g.instTypeList[i]
- assert(!typ.HasShape())
- // Mark runtime type as needed, since this ensures that the
- // compiler puts out the needed DWARF symbols, when this
- // instantiated type has a different package from the local
- // package.
- typecheck.NeedRuntimeType(typ)
- // Lookup the method on the base generic type, since methods may
- // not be set on imported instantiated types.
- baseSym := typ.OrigSym()
- baseType := baseSym.Def.(*ir.Name).Type()
- for j, _ := range typ.Methods().Slice() {
- if baseType.Methods().Slice()[j].Nointerface() {
- typ.Methods().Slice()[j].SetNointerface(true)
+ for {
+ instTypeList := typecheck.GetInstTypeList()
+ if len(instTypeList) == 0 {
+ break
+ }
+ for _, typ := range instTypeList {
+ assert(!typ.HasShape())
+ // Mark runtime type as needed, since this ensures that the
+ // compiler puts out the needed DWARF symbols, when this
+ // instantiated type has a different package from the local
+ // package.
+ typecheck.NeedRuntimeType(typ)
+ // Lookup the method on the base generic type, since methods may
+ // not be set on imported instantiated types.
+ baseSym := typ.OrigSym()
+ baseType := baseSym.Def.(*ir.Name).Type()
+ for j, _ := range typ.Methods().Slice() {
+ if baseType.Methods().Slice()[j].Nointerface() {
+ typ.Methods().Slice()[j].SetNointerface(true)
+ }
+ baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
+ // Eagerly generate the instantiations and dictionaries that implement these methods.
+ // We don't use the instantiations here, just generate them (and any
+ // further instantiations those generate, etc.).
+ // Note that we don't set the Func for any methods on instantiated
+ // types. Their signatures don't match so that would be confusing.
+ // Direct method calls go directly to the instantiations, implemented above.
+ // Indirect method calls use wrappers generated in reflectcall. Those wrappers
+ // will use these instantiations if they are needed (for interface tables or reflection).
+ _ = g.getInstantiation(baseNname, typ.RParams(), true)
+ _ = g.getDictionarySym(baseNname, typ.RParams(), true)
}
- baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
- // Eagerly generate the instantiations and dictionaries that implement these methods.
- // We don't use the instantiations here, just generate them (and any
- // further instantiations those generate, etc.).
- // Note that we don't set the Func for any methods on instantiated
- // types. Their signatures don't match so that would be confusing.
- // Direct method calls go directly to the instantiations, implemented above.
- // Indirect method calls use wrappers generated in reflectcall. Those wrappers
- // will use these instantiations if they are needed (for interface tables or reflection).
- _ = g.getInstantiation(baseNname, typ.RParams(), true)
- _ = g.getDictionarySym(baseNname, typ.RParams(), true)
}
}
- g.instTypeList = nil
-
}
// getInstNameNode returns the name node for the method or function being instantiated, and a bool which is true if a method is being instantiated.
@@ -735,9 +739,6 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*typ
}
ir.CurFunc = savef
- // Add any new, fully instantiated types seen during the substitution to
- // g.instTypeList.
- g.instTypeList = append(g.instTypeList, subst.ts.InstTypeList...)
if doubleCheck {
ir.Visit(newf, func(n ir.Node) {
@@ -1573,7 +1574,6 @@ func (g *irgen) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool)
off: off,
}
g.dictSymsToFinalize = append(g.dictSymsToFinalize, delay)
- g.instTypeList = append(g.instTypeList, subst.InstTypeList...)
return sym
}
@@ -1640,8 +1640,6 @@ func (g *irgen) finalizeSyms() {
objw.Global(lsym, int32(d.off), obj.DUPOK|obj.RODATA)
infoPrint("=== Finalized dictionary %s\n", d.sym.Name)
-
- g.instTypeList = append(g.instTypeList, subst.InstTypeList...)
}
g.dictSymsToFinalize = nil
}
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index b70d8d198e..5c9aafe490 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -321,10 +321,6 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
}
// Do the substitution of the type
meth2.SetType(ts.Typ(meth.Type()))
- // Add any new fully instantiated types
- // seen during the substitution to
- // g.instTypeList.
- g.instTypeList = append(g.instTypeList, ts.InstTypeList...)
newsym.Def = meth2
}
meth = meth2
@@ -335,7 +331,7 @@ func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
ntyp.Methods().Set(methods)
if !ntyp.HasTParam() && !ntyp.HasShape() {
// Generate all the methods for a new fully-instantiated type.
- g.instTypeList = append(g.instTypeList, ntyp)
+ typecheck.NeedInstType(ntyp)
}
}