]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile/internal/types2: export TypeHash, return value without blanks
authorRobert Griesemer <gri@golang.org>
Tue, 14 Sep 2021 20:09:19 +0000 (13:09 -0700)
committerRobert Griesemer <gri@golang.org>
Wed, 15 Sep 2021 03:29:39 +0000 (03:29 +0000)
Change the typeWriter to produce blank-free hashes where easily possible
if used as a type hasher, and replace remaining blanks with '#' is needed.

Exported Environment.TypeHash for use by the compiler.

Change-Id: Icbd364c207f9c139a7a1844bb695512a0c56a4e4
Reviewed-on: https://go-review.googlesource.com/c/go/+/349990
Trust: Robert Griesemer <gri@golang.org>
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/cmd/compile/internal/types2/environment.go
src/cmd/compile/internal/types2/instantiate.go
src/cmd/compile/internal/types2/named.go
src/cmd/compile/internal/types2/subst.go
src/cmd/compile/internal/types2/typestring.go

index 816139bbb478c3ce753f1e7a6343be2aa2662e61..5ef8855a1b38348351d1bff35cb238f8d5afb41c 100644 (file)
@@ -5,6 +5,7 @@ package types2
 
 import (
        "bytes"
+       "strings"
        "sync"
 )
 
@@ -28,11 +29,11 @@ func NewEnvironment() *Environment {
        }
 }
 
-// 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.
 // If typ is a *Named type and targs is not empty, typ is printed as if it were
-// instantiated with targs.
-func (env *Environment) typeHash(typ Type, targs []Type) string {
+// 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)
        var buf bytes.Buffer
@@ -56,7 +57,7 @@ func (env *Environment) typeHash(typ Type, targs []Type) string {
                }
        }
 
-       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.
index 469ceea5c4cc7ca46b266fed95c64d586b65ee35..fdb87e75f6d15fdcd297e16fefc8aed431a14f48 100644 (file)
@@ -108,7 +108,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Envi
        case *Named:
                var h string
                if env != nil {
-                       h = env.typeHash(t, targs)
+                       h = env.TypeHash(t, targs)
                        // typ may already have been instantiated with identical type arguments. In
                        // that case, re-use the existing instance.
                        if named := env.typeForHash(h, nil); named != nil {
index 99410aedfbe8e94e6e0274571582062fd0abaacf..46487d1cae73d0ddd08a5e36b4202bf9f06b984d 100644 (file)
@@ -262,7 +262,7 @@ func (n *Named) expand(env *Environment) *Named {
                                        // instance in the process of expansion.
                                        env = NewEnvironment()
                                }
-                               h := env.typeHash(n.orig, n.targs.list())
+                               h := env.TypeHash(n.orig, n.targs.list())
                                // add the instance to the environment to avoid infinite recursion.
                                // addInstance may return a different, existing instance, but we
                                // shouldn't return that instance from expand.
index 4627dd3c5ba96ec163c4d8215c9e9e13aa08cad3..8d96494af02de5a22240a82bdb1a51428bc6b931 100644 (file)
@@ -211,7 +211,7 @@ func (subst *subster) typ(typ Type) Type {
                }
 
                // before creating a new named type, check if we have this one already
-               h := subst.env.typeHash(t.orig, newTArgs)
+               h := subst.env.TypeHash(t.orig, newTArgs)
                dump(">>> new type hash: %s", h)
                if named := subst.env.typeForHash(h, nil); named != nil {
                        dump(">>> found %s", named)
index 39ba278d539c66feebfac8fe2c08163fafa70a4d..71da37c3a14d0c9789063508f27ca709982b50e3 100644 (file)
@@ -8,7 +8,6 @@ package types2
 
 import (
        "bytes"
-       "fmt"
        "strconv"
        "unicode/utf8"
 )
@@ -83,14 +82,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) {
@@ -117,7 +131,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:
@@ -128,7 +144,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
@@ -139,7 +155,11 @@ func (w *typeWriter) typ(typ Type) {
                        }
                        w.typ(f.typ)
                        if tag := t.Tag(i); tag != "" {
-                               w.writef(" %q", tag)
+                               w.byte(' ')
+                               // TODO(gri) If tag contains blanks, replacing them with '#'
+                               //           in Environment.TypeHash may produce another tag
+                               //           accidentally.
+                               w.string(strconv.Quote(tag))
                        }
                }
                w.byte('}')
@@ -177,7 +197,7 @@ 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)
@@ -185,7 +205,7 @@ func (w *typeWriter) typ(typ Type) {
                }
                for _, typ := range t.embeddeds {
                        if !first {
-                               w.string("; ")
+                               w.byte(';')
                        }
                        first = false
                        w.typ(typ)
@@ -279,7 +299,7 @@ func (w *typeWriter) typeList(list []Type) {
        w.byte('[')
        for i, typ := range list {
                if i > 0 {
-                       w.string(", ")
+                       w.byte(',')
                }
                w.typ(typ)
        }
@@ -303,7 +323,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
                                w.byte(' ')
                                w.typ(prev)
                        }
-                       w.string(", ")
+                       w.byte(',')
                }
                prev = tpar.bound
                w.typ(tpar)
@@ -327,7 +347,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 != "" {