Skip to content

Commit

Permalink
go/types: return typeHash value without blanks
Browse files Browse the repository at this point in the history
This is an adjusted port of CL 349990 from types2 to go/types:
typeHash remains unexported but is adjusted to not contain blanks.

Change-Id: I37fa826b8a185e3c275ae9bea29a3b0ed386d2c9
Reviewed-on: https://go-review.googlesource.com/c/go/+/351171
Trust: Robert Griesemer <[email protected]>
Reviewed-by: Robert Findley <[email protected]>
  • Loading branch information
griesemer committed Sep 21, 2021
1 parent 7dfe686 commit ebc6ce4
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 15 deletions.
5 changes: 3 additions & 2 deletions src/go/types/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package types

import (
"bytes"
"strings"
"sync"
)

Expand All @@ -32,7 +33,7 @@ func NewEnvironment() *Environment {
// typeHash returns a string representation of typ, which can be used as an exact
// 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
// instantiated with targs.
// instantiated with targs. The result is guaranteed to not contain blanks (" ").
func (env *Environment) typeHash(typ Type, targs []Type) string {
assert(env != nil)
assert(typ != nil)
Expand All @@ -50,7 +51,7 @@ func (env *Environment) typeHash(typ Type, targs []Type) string {
h.typ(typ)
}

return buf.String()
return strings.Replace(buf.String(), " ", "#", -1) // ReplaceAll is not available in Go1.4
}

// typeForHash returns the recorded type for the type hash h, if it exists.
Expand Down
46 changes: 33 additions & 13 deletions src/go/types/typestring.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ package types

import (
"bytes"
"fmt"
"go/token"
"strconv"
"unicode/utf8"
Expand Down Expand Up @@ -81,14 +80,29 @@ func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter {
return &typeWriter{buf, make(map[Type]bool), nil, env}
}

func (w *typeWriter) byte(b byte) { w.buf.WriteByte(b) }
func (w *typeWriter) string(s string) { w.buf.WriteString(s) }
func (w *typeWriter) writef(format string, args ...interface{}) { fmt.Fprintf(w.buf, format, args...) }
func (w *typeWriter) byte(b byte) {
if w.env != nil {
if b == ' ' {
b = '#'
}
w.buf.WriteByte(b)
return
}
w.buf.WriteByte(b)
if b == ',' || b == ';' {
w.buf.WriteByte(' ')
}
}

func (w *typeWriter) string(s string) {
w.buf.WriteString(s)
}

func (w *typeWriter) error(msg string) {
if w.env != nil {
panic(msg)
}
w.string("<" + msg + ">")
w.buf.WriteString("<" + msg + ">")
}

func (w *typeWriter) typ(typ Type) {
Expand All @@ -115,7 +129,9 @@ func (w *typeWriter) typ(typ Type) {
w.string(t.name)

case *Array:
w.writef("[%d]", t.len)
w.byte('[')
w.string(strconv.FormatInt(t.len, 10))
w.byte(']')
w.typ(t.elem)

case *Slice:
Expand All @@ -126,7 +142,7 @@ func (w *typeWriter) typ(typ Type) {
w.string("struct{")
for i, f := range t.fields {
if i > 0 {
w.string("; ")
w.byte(';')
}
// This doesn't do the right thing for embedded type
// aliases where we should print the alias name, not
Expand All @@ -137,7 +153,11 @@ func (w *typeWriter) typ(typ Type) {
}
w.typ(f.typ)
if tag := t.Tag(i); tag != "" {
w.writef(" %q", tag)
w.byte(' ')
// TODO(rfindley) If tag contains blanks, replacing them with '#'
// in Environment.TypeHash may produce another tag
// accidentally.
w.string(strconv.Quote(tag))
}
}
w.byte('}')
Expand Down Expand Up @@ -175,15 +195,15 @@ func (w *typeWriter) typ(typ Type) {
first := true
for _, m := range t.methods {
if !first {
w.string("; ")
w.byte(';')
}
first = false
w.string(m.name)
w.signature(m.typ.(*Signature))
}
for _, typ := range t.embeddeds {
if !first {
w.string("; ")
w.byte(';')
}
first = false
w.typ(typ)
Expand Down Expand Up @@ -270,7 +290,7 @@ func (w *typeWriter) typeList(list []Type) {
w.byte('[')
for i, typ := range list {
if i > 0 {
w.string(", ")
w.byte(',')
}
w.typ(typ)
}
Expand All @@ -294,7 +314,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
w.byte(' ')
w.typ(prev)
}
w.string(", ")
w.byte(',')
}
prev = tpar.bound
w.typ(tpar)
Expand All @@ -318,7 +338,7 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
if tup != nil {
for i, v := range tup.vars {
if i > 0 {
w.string(", ")
w.byte(',')
}
// parameter names are ignored for type identity and thus type hashes
if w.env == nil && v.name != "" {
Expand Down

0 comments on commit ebc6ce4

Please sign in to comment.