mirror of
https://github.com/golang/go
synced 2024-11-17 13:54:46 -07:00
cmd/compile: allow methods on shape types (but no bodies)
In a previous change, I was too aggressive in substInstType() in not generating methods for shape types during import. We do actually want to generate the method nodes - we just don't want to generate method bodies (which we would never use). We may need the method nodes for checking types later in the compile (especially with inlining). So, we do generate method nodes for shape types during import. In order to avoid the name collision we previously had, we now add ".nofunc." to the method nodes for shape types (during import and in the type substituter). We do that by passing in a 'isMethodNode' arg to MakeInstSym. We keep the normal name (without ".nofunc") for any other method nodes, and for the instantiated functions that help with implementing the methods of fully-instantiated types. The ".nofunc" names will never appear in the executable, since we don't generate any method bodies for the method nodes of shape types. Change-Id: I3e57e328691214140ca5f48d32011552d2a0d45d Reviewed-on: https://go-review.googlesource.com/c/go/+/352470 Trust: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
964ea8c648
commit
dfd875d015
@ -626,7 +626,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth
|
||||
shapes = s1
|
||||
}
|
||||
|
||||
sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, isMeth)
|
||||
sym := typecheck.MakeFuncInstSym(nameNode.Sym(), shapes, false, isMeth)
|
||||
info := g.instInfoMap[sym]
|
||||
if info == nil {
|
||||
// If instantiation doesn't exist yet, create it and add
|
||||
|
@ -1927,7 +1927,7 @@ func methodWrapper(rcvr *types.Type, method *types.Field, forItab bool) *obj.LSy
|
||||
}
|
||||
targs = targs2
|
||||
|
||||
sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, true)
|
||||
sym := typecheck.MakeFuncInstSym(ir.MethodSym(methodrcvr, method.Sym), targs, false, true)
|
||||
if sym.Def == nil {
|
||||
// Currently we make sure that we have all the instantiations
|
||||
// we need by generating them all in ../noder/stencil.go:instantiateMethods
|
||||
|
@ -1867,11 +1867,6 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) {
|
||||
}
|
||||
t.SetUnderlying(subst.Typ(baseType.Underlying()))
|
||||
|
||||
if t.HasShape() && !t.IsInterface() {
|
||||
// Concrete shape types have no methods.
|
||||
return
|
||||
}
|
||||
|
||||
newfields := make([]*types.Field, baseType.Methods().Len())
|
||||
for i, f := range baseType.Methods().Slice() {
|
||||
if !f.IsMethod() || types.IsInterfaceMethod(f.Type) {
|
||||
@ -1895,7 +1890,7 @@ func substInstType(t *types.Type, baseType *types.Type, targs []*types.Type) {
|
||||
}
|
||||
t2 := msubst.Typ(f.Type)
|
||||
oldsym := f.Nname.Sym()
|
||||
newsym := MakeFuncInstSym(oldsym, targs, true)
|
||||
newsym := MakeFuncInstSym(oldsym, targs, true, true)
|
||||
var nname *ir.Name
|
||||
if newsym.Def != nil {
|
||||
nname = newsym.Def.(*ir.Name)
|
||||
|
@ -962,8 +962,8 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string {
|
||||
}
|
||||
|
||||
// MakeFuncInstSym makes the unique sym for a stenciled generic function or method,
|
||||
// based on the name of the function fnsym and the targs. It replaces any
|
||||
// existing bracket type list in the name. MakeInstName asserts that fnsym has
|
||||
// based on the name of the function gf and the targs. It replaces any
|
||||
// existing bracket type list in the name. MakeInstName asserts that gf has
|
||||
// brackets in its name if and only if hasBrackets is true.
|
||||
//
|
||||
// Names of declared generic functions have no brackets originally, so hasBrackets
|
||||
@ -973,8 +973,19 @@ func makeInstName1(name string, targs []*types.Type, hasBrackets bool) string {
|
||||
//
|
||||
// The standard naming is something like: 'genFn[int,bool]' for functions and
|
||||
// '(*genType[int,bool]).methodName' for methods
|
||||
func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym {
|
||||
return gf.Pkg.Lookup(makeInstName1(gf.Name, targs, hasBrackets))
|
||||
//
|
||||
// isMethodNode specifies if the name of a method node is being generated (as opposed
|
||||
// to a name of an instantiation of generic function or name of the shape-based
|
||||
// function that helps implement a method of an instantiated type). For method nodes
|
||||
// on shape types, we prepend "nofunc.", because method nodes for shape types will
|
||||
// have no body, and we want to avoid a name conflict with the shape-based function
|
||||
// that helps implement the same method for fully-instantiated types.
|
||||
func MakeFuncInstSym(gf *types.Sym, targs []*types.Type, isMethodNode, hasBrackets bool) *types.Sym {
|
||||
nm := makeInstName1(gf.Name, targs, hasBrackets)
|
||||
if targs[0].HasShape() && isMethodNode {
|
||||
nm = "nofunc." + nm
|
||||
}
|
||||
return gf.Pkg.Lookup(nm)
|
||||
}
|
||||
|
||||
func MakeDictSym(gf *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym {
|
||||
@ -1262,7 +1273,7 @@ func (ts *Tsubster) typ1(t *types.Type) *types.Type {
|
||||
for i, f := range t.Methods().Slice() {
|
||||
t2 := ts.typ1(f.Type)
|
||||
oldsym := f.Nname.Sym()
|
||||
newsym := MakeFuncInstSym(oldsym, ts.Targs, true)
|
||||
newsym := MakeFuncInstSym(oldsym, ts.Targs, true, true)
|
||||
var nname *ir.Name
|
||||
if newsym.Def != nil {
|
||||
nname = newsym.Def.(*ir.Name)
|
||||
|
Loading…
Reference in New Issue
Block a user