mirror of https://github.com/golang/go.git
cmd/compile/internal/types2: when type hashing, use placeholders for type parameters
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>
This commit is contained in:
parent
a17a21c190
commit
489f58779c
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue