]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: when type hashing, use placeholders for type parameters
authorRobert Findley <rfindley@google.com>
Wed, 10 Nov 2021 20:53:16 +0000 (15:53 -0500)
committerRobert Findley <rfindley@google.com>
Sat, 13 Nov 2021 00:36:41 +0000 (00:36 +0000)
Type parameter names don't matter for the purposes of generic type
identity, so mask them with numeric placeholders when hashing.

Change-Id: Iacb4c23abecdd733fc292ae13ecac6baa2c5524c
Reviewed-on: https://go-review.googlesource.com/c/go/+/363114
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/go/types/typestring.go

index 9192b0423bbc0f1edf2fd51518a5dec6e329b976..cb41abd2ac46d8eb6b96891805b4dfba8f91cdd8 100644 (file)
@@ -8,6 +8,7 @@ package types
 
 import (
        "bytes"
+       "fmt"
        "go/token"
        "strconv"
        "unicode/utf8"
@@ -71,20 +72,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) {
@@ -259,8 +261,12 @@ 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())
@@ -274,9 +280,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:
@@ -286,15 +299,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 {
@@ -379,6 +383,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())
        }