mirror of
https://github.com/golang/go
synced 2024-11-26 09:38:10 -07:00
go/types: eliminate typeHashing global variable
This is a port of CL 345929 to go/types. It is also a step toward making instantiation concurrency-safe. Also fix some whitespace in instantiate.go. Updates #47910 Change-Id: Icdeb227cb83eee15da6db90daab294c8c55db601 Reviewed-on: https://go-review.googlesource.com/c/go/+/346557 Trust: Robert Findley <rfindley@google.com> Run-TryBot: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
parent
0df6df17e1
commit
5cd1b847dc
@ -121,8 +121,8 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type {
|
|||||||
case *Named:
|
case *Named:
|
||||||
h := typeHash(t, targs)
|
h := typeHash(t, targs)
|
||||||
if check != nil {
|
if check != nil {
|
||||||
// typ may already have been instantiated with identical type arguments. In
|
// typ may already have been instantiated with identical type arguments.
|
||||||
// that case, re-use the existing instance.
|
// In that case, re-use the existing instance.
|
||||||
if named := check.typMap[h]; named != nil {
|
if named := check.typMap[h]; named != nil {
|
||||||
return named
|
return named
|
||||||
}
|
}
|
||||||
@ -135,6 +135,7 @@ func (check *Checker) instance(pos token.Pos, typ Type, targs []Type) Type {
|
|||||||
check.typMap[h] = named
|
check.typMap[h] = named
|
||||||
}
|
}
|
||||||
return named
|
return named
|
||||||
|
|
||||||
case *Signature:
|
case *Signature:
|
||||||
tparams := t.TParams()
|
tparams := t.TParams()
|
||||||
if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
|
if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
|
||||||
|
@ -256,8 +256,6 @@ func (subst *subster) typ(typ Type) Type {
|
|||||||
return typ
|
return typ
|
||||||
}
|
}
|
||||||
|
|
||||||
var typeHashing = 0
|
|
||||||
|
|
||||||
// typeHash returns a string representation of typ, which can be used as an exact
|
// typeHash returns a string representation of typ, which can be used as an exact
|
||||||
// type hash: types that are identical produce identical string representations.
|
// type hash: types that are identical produce identical string representations.
|
||||||
// If typ is a *Named type and targs is not empty, typ is printed as if it were
|
// If typ is a *Named type and targs is not empty, typ is printed as if it were
|
||||||
@ -266,19 +264,16 @@ func typeHash(typ Type, targs []Type) string {
|
|||||||
assert(typ != nil)
|
assert(typ != nil)
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
assert(typeHashing == 0)
|
h := newTypeHasher(&buf)
|
||||||
typeHashing++
|
|
||||||
w := newTypeWriter(&buf, nil)
|
|
||||||
if named, _ := typ.(*Named); named != nil && len(targs) > 0 {
|
if named, _ := typ.(*Named); named != nil && len(targs) > 0 {
|
||||||
// Don't use WriteType because we need to use the provided targs
|
// Don't use WriteType because we need to use the provided targs
|
||||||
// and not any targs that might already be with the *Named type.
|
// and not any targs that might already be with the *Named type.
|
||||||
w.typeName(named.obj)
|
h.typeName(named.obj)
|
||||||
w.typeList(targs)
|
h.typeList(targs)
|
||||||
} else {
|
} else {
|
||||||
assert(targs == nil)
|
assert(targs == nil)
|
||||||
w.typ(typ)
|
h.typ(typ)
|
||||||
}
|
}
|
||||||
typeHashing--
|
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
// there should be no instance markers in type hashes
|
// there should be no instance markers in type hashes
|
||||||
|
@ -63,10 +63,15 @@ type typeWriter struct {
|
|||||||
buf *bytes.Buffer
|
buf *bytes.Buffer
|
||||||
seen map[Type]bool
|
seen map[Type]bool
|
||||||
qf Qualifier
|
qf Qualifier
|
||||||
|
hash bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter {
|
func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter {
|
||||||
return &typeWriter{buf, make(map[Type]bool), qf}
|
return &typeWriter{buf, make(map[Type]bool), qf, false}
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTypeHasher(buf *bytes.Buffer) *typeWriter {
|
||||||
|
return &typeWriter{buf, make(map[Type]bool), nil, true}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) }
|
func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) }
|
||||||
@ -208,7 +213,7 @@ func (w *typeWriter) typ(typ Type) {
|
|||||||
// types. Write them to aid debugging, but don't write
|
// types. Write them to aid debugging, but don't write
|
||||||
// them when we need an instance hash: whether a type
|
// them when we need an instance hash: whether a type
|
||||||
// is fully expanded or not doesn't matter for identity.
|
// is fully expanded or not doesn't matter for identity.
|
||||||
if typeHashing == 0 && t.instPos != nil {
|
if !w.hash && t.instPos != nil {
|
||||||
w.byte(instanceMarker)
|
w.byte(instanceMarker)
|
||||||
}
|
}
|
||||||
w.typeName(t.obj)
|
w.typeName(t.obj)
|
||||||
@ -292,7 +297,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
|
|||||||
|
|
||||||
func (w *typeWriter) typeName(obj *TypeName) {
|
func (w *typeWriter) typeName(obj *TypeName) {
|
||||||
if obj == nil {
|
if obj == nil {
|
||||||
assert(typeHashing == 0) // we need an object for type hashing
|
assert(!w.hash) // we need an object for type hashing
|
||||||
w.string("<Named w/o object>")
|
w.string("<Named w/o object>")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -301,7 +306,7 @@ func (w *typeWriter) typeName(obj *TypeName) {
|
|||||||
}
|
}
|
||||||
w.string(obj.name)
|
w.string(obj.name)
|
||||||
|
|
||||||
if typeHashing != 0 {
|
if w.hash {
|
||||||
// For local defined types, use the (original!) TypeName's scope
|
// For local defined types, use the (original!) TypeName's scope
|
||||||
// numbers to disambiguate.
|
// numbers to disambiguate.
|
||||||
if typ, _ := obj.typ.(*Named); typ != nil {
|
if typ, _ := obj.typ.(*Named); typ != nil {
|
||||||
@ -335,7 +340,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
|
|||||||
w.string(", ")
|
w.string(", ")
|
||||||
}
|
}
|
||||||
// parameter names are ignored for type identity and thus type hashes
|
// parameter names are ignored for type identity and thus type hashes
|
||||||
if typeHashing == 0 && v.name != "" {
|
if !w.hash && v.name != "" {
|
||||||
w.string(v.name)
|
w.string(v.name)
|
||||||
w.byte(' ')
|
w.byte(' ')
|
||||||
}
|
}
|
||||||
@ -383,8 +388,8 @@ func (w *typeWriter) signature(sig *Signature) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
w.byte(' ')
|
w.byte(' ')
|
||||||
if n == 1 && (typeHashing != 0 || sig.results.vars[0].name == "") {
|
if n == 1 && (w.hash || sig.results.vars[0].name == "") {
|
||||||
// single unnamed result (if typeHashing, name must be ignored)
|
// single unnamed result (if type hashing, name must be ignored)
|
||||||
w.typ(sig.results.vars[0].typ)
|
w.typ(sig.results.vars[0].typ)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user