]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: when type hashing, use placeholders for type parameters
authorRobert Griesemer <gri@golang.org>
Tue, 16 Nov 2021 16:31:38 +0000 (08:31 -0800)
committerRobert Griesemer <gri@golang.org>
Wed, 17 Nov 2021 04:31:40 +0000 (04:31 +0000)
This is a port of CL 363114 from go/types to types2 with a temporary
work-around in tparamIndex to avoid a crash with the unified build
and test/typeparam/setsimp.go.

Change-Id: Id4805385f21c95b461911b246fb47ee278a84ac9
Reviewed-on: https://go-review.googlesource.com/c/go/+/364336
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/typestring.go
src/cmd/compile/internal/types2/unify.go

index 1857f58a4bb8b312ab5e51ff46534b134de00d12..ba3494d9d9583c64c98acde3e5c43635a37c0d4b 100644 (file)
@@ -8,6 +8,7 @@ package types2
 
 import (
        "bytes"
+       "fmt"
        "strconv"
        "unicode/utf8"
 )
@@ -70,20 +71,21 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
 }
 
 type typeWriter struct {
-       buf   *bytes.Buffer
-       seen  map[Type]bool
-       qf    Qualifier
-       ctxt  *Context // if non-nil, we are type hashing
-       debug bool     // if true, write debug annotations
+       buf     *bytes.Buffer
+       seen    map[Type]bool
+       qf      Qualifier
+       ctxt    *Context       // if non-nil, we are type hashing
+       tparams *TypeParamList // local type parameters
+       debug   bool           // if true, write debug annotations
 }
 
 func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter {
-       return &typeWriter{buf, make(map[Type]bool), qf, nil, false}
+       return &typeWriter{buf, make(map[Type]bool), qf, nil, nil, false}
 }
 
 func newTypeHasher(buf *bytes.Buffer, ctxt *Context) *typeWriter {
        assert(ctxt != nil)
-       return &typeWriter{buf, make(map[Type]bool), nil, ctxt, false}
+       return &typeWriter{buf, make(map[Type]bool), nil, ctxt, nil, false}
 }
 
 func (w *typeWriter) byte(b byte) {
@@ -265,12 +267,16 @@ func (w *typeWriter) typ(typ Type) {
                }
 
        case *Named:
-               w.typePrefix(t)
-               w.typeName(t.obj)
+               // If hashing, write a unique prefix for t to represent its identity, since
+               // named type identity is pointer identity.
+               if w.ctxt != nil {
+                       w.string(strconv.Itoa(w.ctxt.getID(t)))
+               }
+               w.typeName(t.obj) // when hashing written for readability of the hash only
                if t.targs != nil {
                        // instantiated type
                        w.typeList(t.targs.list())
-               } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams
+               } else if w.ctxt == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TypeParams
                        // parameterized type
                        w.tParamList(t.TypeParams().list())
                }
@@ -280,9 +286,16 @@ func (w *typeWriter) typ(typ Type) {
                        w.error("unnamed type parameter")
                        break
                }
-               w.string(t.obj.name)
-               if w.debug || w.ctxt != nil {
-                       w.string(subscript(t.id))
+               if i := tparamIndex(w.tparams.list(), t); i >= 0 {
+                       // The names of type parameters that are declared by the type being
+                       // hashed are not part of the type identity. Replace them with a
+                       // placeholder indicating their index.
+                       w.string(fmt.Sprintf("$%d", i))
+               } else {
+                       w.string(t.obj.name)
+                       if w.debug || w.ctxt != nil {
+                               w.string(subscript(t.id))
+                       }
                }
 
        default:
@@ -292,15 +305,6 @@ func (w *typeWriter) typ(typ Type) {
        }
 }
 
-// If w.ctxt is non-nil, typePrefix writes a unique prefix for the named type t
-// based on the types already observed by w.ctxt. If w.ctxt is nil, it does
-// nothing.
-func (w *typeWriter) typePrefix(t *Named) {
-       if w.ctxt != nil {
-               w.string(strconv.Itoa(w.ctxt.getID(t)))
-       }
-}
-
 func (w *typeWriter) typeList(list []Type) {
        w.byte('[')
        for i, typ := range list {
@@ -385,6 +389,13 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
 
 func (w *typeWriter) signature(sig *Signature) {
        if sig.TypeParams().Len() != 0 {
+               if w.ctxt != nil {
+                       assert(w.tparams == nil)
+                       w.tparams = sig.TypeParams()
+                       defer func() {
+                               w.tparams = nil
+                       }()
+               }
                w.tParamList(sig.TypeParams().list())
        }
 
index ccb6ee870935a506d9db767ac8905cdef33fd251..651bba1a6bfcebc75a34242cdfa97e0ddbff96e0 100644 (file)
@@ -9,6 +9,7 @@ package types2
 import (
        "bytes"
        "fmt"
+       "internal/buildcfg"
 )
 
 // The unifier maintains two separate sets of type parameters x and y
@@ -161,6 +162,12 @@ func (d *tparamsList) index(typ Type) int {
 // If tpar is a type parameter in list, tparamIndex returns the type parameter index.
 // Otherwise, the result is < 0. tpar must not be nil.
 func tparamIndex(list []*TypeParam, tpar *TypeParam) int {
+       // Temporary work-around for getting around a crash
+       // with unified build.
+       // TODO(gri) investigate and implement proper fix
+       if buildcfg.Experiment.Unified && tpar.index < 0 {
+               return -1
+       }
        if i := tpar.index; i < len(list) && list[i] == tpar {
                return i
        }