]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] Separate out gcshape types that are instantiated types
authorDan Scales <danscales@google.com>
Fri, 9 Jul 2021 23:27:22 +0000 (16:27 -0700)
committerDan Scales <danscales@google.com>
Mon, 19 Jul 2021 05:02:24 +0000 (05:02 +0000)
Distinguish the gcshape of all top-level instantiated type from normal
concrete types, even if they have the exact same underlying "shape",
because in a function instantiation, any method call on this type arg
will be a generic method call (requiring a dictionary), rather than a
direct method call on the underlying type (no dictionary).

So, we add the instshape prefix to the gcshape name for instantiated
types, and we make it a defined type with that name.

Change-Id: I33056269d24f3451a2632a5ce6a481108f533c9c
Reviewed-on: https://go-review.googlesource.com/c/go/+/335169
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/stencil.go

index f4935fe22a4f8ebc91828e8100558e4ed33e63e7..7eac8573c96943d2aa0f8f424c8ca84a82ecc4c6 100644 (file)
@@ -729,11 +729,37 @@ func gcshapeType(t *types.Type) (*types.Type, string) {
 
        // Call CallSize so type sizes and field offsets are available.
        types.CalcSize(t)
+
+       instType := t.Sym() != nil && t.IsFullyInstantiated()
+       if instType {
+               // We distinguish the gcshape of all top-level instantiated type from
+               // normal concrete types, even if they have the exact same underlying
+               // "shape", because in a function instantiation, any method call on
+               // this type arg will be a generic method call (requiring a
+               // dictionary), rather than a direct method call on the underlying
+               // type (no dictionary). So, we add the instshape prefix to the
+               // normal gcshape name, and will make it a defined type with that
+               // name below.
+               buf.WriteString("instshape-")
+       }
        fl = accumGcshape(fl, buf, t, nil)
+
        // TODO: Should gcshapes be in a global package, so we don't have to
        // duplicate in each package? Or at least in the specified source package
        // of a function/method instantiation?
        gcshape := types.NewStruct(types.LocalPkg, fl)
+       gcname := buf.String()
+       if instType {
+               // Lookup or create type with name 'gcname' (with instshape prefix).
+               newsym := t.Sym().Pkg.Lookup(gcname)
+               if newsym.Def != nil {
+                       gcshape = newsym.Def.Type()
+               } else {
+                       newt := typecheck.NewIncompleteNamedType(t.Pos(), newsym)
+                       newt.SetUnderlying(gcshape.Underlying())
+                       gcshape = newt
+               }
+       }
        assert(gcshape.Size() == t.Size())
        return gcshape, buf.String()
 }
@@ -764,7 +790,7 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth
                        // Testing out gcshapeType() and gcshapeName()
                        for i, t := range targs {
                                gct, gcs := gcshapeType(t)
-                               fmt.Printf("targ %d: %v %v\n", i, gct, gcs)
+                               fmt.Printf("targ %d: %v %v %v\n", i, gcs, gct, gct.Underlying())
                        }
                }
                // If instantiation doesn't exist yet, create it and add