aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/typestring.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types2/typestring.go')
-rw-r--r--src/cmd/compile/internal/types2/typestring.go115
1 files changed, 56 insertions, 59 deletions
diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go
index 6083955306..bdafcf883d 100644
--- a/src/cmd/compile/internal/types2/typestring.go
+++ b/src/cmd/compile/internal/types2/typestring.go
@@ -8,7 +8,7 @@ package types2
import (
"bytes"
- "fmt"
+ "strconv"
"unicode/utf8"
)
@@ -63,32 +63,45 @@ func WriteSignature(buf *bytes.Buffer, sig *Signature, qf Qualifier) {
newTypeWriter(buf, qf).signature(sig)
}
-// instanceMarker is the prefix for an instantiated type in unexpanded form.
-const instanceMarker = '#'
-
type typeWriter struct {
buf *bytes.Buffer
seen map[Type]bool
qf Qualifier
- hash bool
+ env *Environment // if non-nil, we are type hashing
}
func newTypeWriter(buf *bytes.Buffer, qf Qualifier) *typeWriter {
- return &typeWriter{buf, make(map[Type]bool), qf, false}
+ return &typeWriter{buf, make(map[Type]bool), qf, nil}
}
-func newTypeHasher(buf *bytes.Buffer) *typeWriter {
- return &typeWriter{buf, make(map[Type]bool), nil, true}
+func newTypeHasher(buf *bytes.Buffer, env *Environment) *typeWriter {
+ assert(env != nil)
+ return &typeWriter{buf, make(map[Type]bool), nil, env}
+}
+
+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) 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) error(msg string) {
- if w.hash {
+ if w.env != nil {
panic(msg)
}
- w.string("<" + msg + ">")
+ w.buf.WriteString("<" + msg + ">")
}
func (w *typeWriter) typ(typ Type) {
@@ -115,7 +128,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:
@@ -126,7 +141,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
@@ -137,7 +152,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('}')
@@ -175,7 +194,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)
@@ -183,7 +202,7 @@ func (w *typeWriter) typ(typ Type) {
}
for _, typ := range t.embeddeds {
if !first {
- w.string("; ")
+ w.byte(';')
}
first = false
w.typ(typ)
@@ -223,20 +242,14 @@ func (w *typeWriter) typ(typ Type) {
}
case *Named:
- // Instance markers indicate unexpanded instantiated
- // types. Write them to aid debugging, but don't write
- // them when we need an instance hash: whether a type
- // is fully expanded or not doesn't matter for identity.
- if !w.hash && t.instPos != nil {
- w.byte(instanceMarker)
- }
+ w.typePrefix(t)
w.typeName(t.obj)
if t.targs != nil {
// instantiated type
w.typeList(t.targs.list())
- } else if !w.hash && t.TParams().Len() != 0 { // For type hashing, don't need to format the TParams
+ } else if w.env == nil && t.TypeParams().Len() != 0 { // For type hashing, don't need to format the TParams
// parameterized type
- w.tParamList(t.TParams().list())
+ w.tParamList(t.TypeParams().list())
}
case *TypeParam:
@@ -263,11 +276,20 @@ func (w *typeWriter) typ(typ Type) {
}
}
+// If w.env is non-nil, typePrefix writes a unique prefix for the named type t
+// based on the types already observed by w.env. If w.env is nil, it does
+// nothing.
+func (w *typeWriter) typePrefix(t *Named) {
+ if w.env != nil {
+ w.string(strconv.Itoa(w.env.idForType(t)))
+ }
+}
+
func (w *typeWriter) typeList(list []Type) {
w.byte('[')
for i, typ := range list {
if i > 0 {
- w.string(", ")
+ w.byte(',')
}
w.typ(typ)
}
@@ -291,7 +313,7 @@ func (w *typeWriter) tParamList(list []*TypeParam) {
w.byte(' ')
w.typ(prev)
}
- w.string(", ")
+ w.byte(',')
}
prev = tpar.bound
w.typ(tpar)
@@ -308,31 +330,6 @@ func (w *typeWriter) typeName(obj *TypeName) {
writePackage(w.buf, obj.pkg, w.qf)
}
w.string(obj.name)
-
- if w.hash {
- // For local defined types, use the (original!) TypeName's scope
- // numbers to disambiguate.
- if typ, _ := obj.typ.(*Named); typ != nil {
- // TODO(gri) Figure out why typ.orig != typ.orig.orig sometimes
- // and whether the loop can iterate more than twice.
- // (It seems somehow connected to instance types.)
- for typ.orig != typ {
- typ = typ.orig
- }
- w.writeScopeNumbers(typ.obj.parent)
- }
- }
-}
-
-// writeScopeNumbers writes the number sequence for this scope to buf
-// in the form ".i.j.k" where i, j, k, etc. stand for scope numbers.
-// If a scope is nil or has no parent (such as a package scope), nothing
-// is written.
-func (w *typeWriter) writeScopeNumbers(s *Scope) {
- if s != nil && s.number > 0 {
- w.writeScopeNumbers(s.parent)
- w.writef(".%d", s.number)
- }
}
func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
@@ -340,10 +337,10 @@ 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.hash && v.name != "" {
+ if w.env == nil && v.name != "" {
w.string(v.name)
w.byte(' ')
}
@@ -371,8 +368,8 @@ func (w *typeWriter) tuple(tup *Tuple, variadic bool) {
}
func (w *typeWriter) signature(sig *Signature) {
- if sig.TParams().Len() != 0 {
- w.tParamList(sig.TParams().list())
+ if sig.TypeParams().Len() != 0 {
+ w.tParamList(sig.TypeParams().list())
}
w.tuple(sig.params, sig.variadic)
@@ -384,7 +381,7 @@ func (w *typeWriter) signature(sig *Signature) {
}
w.byte(' ')
- if n == 1 && (w.hash || sig.results.vars[0].name == "") {
+ if n == 1 && (w.env != nil || sig.results.vars[0].name == "") {
// single unnamed result (if type hashing, name must be ignored)
w.typ(sig.results.vars[0].typ)
return