diff options
Diffstat (limited to 'src/cmd/compile/internal/types2/typestring.go')
-rw-r--r-- | src/cmd/compile/internal/types2/typestring.go | 115 |
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 |