diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go index 0423fcce987..459e1d1703c 100644 --- a/src/cmd/compile/internal/noder/reader.go +++ b/src/cmd/compile/internal/noder/reader.go @@ -631,7 +631,7 @@ func (r *reader) mangle(sym *types.Sym) *types.Sym { } // TODO(mdempsky): We need the linker to replace "" in the symbol // names here. - buf.WriteString(targ.ShortString()) + buf.WriteString(targ.LinkString()) } } buf.WriteByte(']') @@ -2041,7 +2041,7 @@ func (r *reader) wrapTypes(target *ir.Package) { seen := make(map[string]*types.Type) for _, typ := range needWrapperTypes { if typ.Sym() == nil { - key := typ.ShortString() + key := typ.LinkString() if prev := seen[key]; prev != nil { if !types.Identical(typ, prev) { base.Fatalf("collision: types %v and %v have short string %q", typ, prev, key) diff --git a/src/cmd/compile/internal/reflectdata/reflect.go b/src/cmd/compile/internal/reflectdata/reflect.go index 8421e36b3dd..316c7eb2935 100644 --- a/src/cmd/compile/internal/reflectdata/reflect.go +++ b/src/cmd/compile/internal/reflectdata/reflect.go @@ -717,7 +717,7 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { } exported := false - p := t.LongString() + p := t.NameString() // If we're writing out type T, // we are very likely to write out type *T as well. // Use the string "*T"[1:] for "T", so that the two @@ -781,11 +781,11 @@ func dcommontype(lsym *obj.LSym, t *types.Type) int { // TrackSym returns the symbol for tracking use of field/method f, assumed // to be a member of struct/interface type t. func TrackSym(t *types.Type, f *types.Field) *obj.LSym { - return base.PkgLinksym("go.track", t.ShortString()+"."+f.Sym.Name, obj.ABI0) + return base.PkgLinksym("go.track", t.LinkString()+"."+f.Sym.Name, obj.ABI0) } func TypeSymPrefix(prefix string, t *types.Type) *types.Sym { - p := prefix + "." + t.ShortString() + p := prefix + "." + t.LinkString() s := types.TypeSymLookup(p) // This function is for looking up type-related generated functions @@ -833,7 +833,7 @@ func TypePtr(t *types.Type) *ir.AddrExpr { // ITabAddr returns an expression representing a pointer to the itab // for concrete type typ implementing interface iface. func ITabAddr(typ, iface *types.Type) *ir.AddrExpr { - s, existed := ir.Pkgs.Itab.LookupOK(typ.ShortString() + "," + iface.ShortString()) + s, existed := ir.Pkgs.Itab.LookupOK(typ.LinkString() + "," + iface.LinkString()) lsym := s.Linksym() if !existed { diff --git a/src/cmd/compile/internal/typecheck/stmt.go b/src/cmd/compile/internal/typecheck/stmt.go index cd00f1b3d11..313491ba0b8 100644 --- a/src/cmd/compile/internal/typecheck/stmt.go +++ b/src/cmd/compile/internal/typecheck/stmt.go @@ -678,7 +678,7 @@ func (s *typeSet) add(pos src.XPos, typ *types.Type) { // LongString does not uniquely identify types, so we need to // disambiguate collisions with types.Identical. // TODO(mdempsky): Add a method that *is* unique. - ls := typ.LongString() + ls := typ.NameString() prevs := s.m[ls] for _, prev := range prevs { if types.Identical(typ, prev.typ) { diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go index b4d1f6c8bbd..095b795d036 100644 --- a/src/cmd/compile/internal/types/fmt.go +++ b/src/cmd/compile/internal/types/fmt.go @@ -242,17 +242,37 @@ func (t *Type) String() string { return tconv(t, 0, fmtGo) } -// ShortString generates a short description of t. -// It is used in autogenerated method names, reflection, -// and itab names. -func (t *Type) ShortString() string { +// LinkString returns an unexpanded string description of t, suitable +// for use in link symbols. "Unexpanded" here means that the +// description uses `"".` to qualify identifiers from the current +// package, and "expansion" refers to the renaming step performed by +// the linker to replace these qualifiers with proper `path/to/pkg.` +// qualifiers. +// +// After expansion, the description corresponds to type identity. That +// is, for any pair of types t1 and t2, Identical(t1, t2) and +// expand(t1.LinkString()) == expand(t2.LinkString()) report the same +// value. +// +// Within a single compilation unit, LinkString always returns the +// same unexpanded description for identical types. Thus it's safe to +// use as a map key to implement a type-identity-keyed map. However, +// make sure all LinkString calls used for this purpose happen within +// the same compile process; the string keys are not stable across +// multiple processes. +func (t *Type) LinkString() string { return tconv(t, 0, fmtTypeID) } -// LongString generates a complete description of t. -// It is useful for reflection, -// or when a unique fingerprint or hash of a type is required. -func (t *Type) LongString() string { +// NameString generates a user-readable, mostly unique string +// description of t. NameString always returns the same description +// for identical types, even across compilation units. +// +// NameString qualifies identifiers by package name, so it has +// collisions when different packages share the same names and +// identifiers. It also does not distinguish function-scope defined +// types from package-scoped defined types or from each other. +func (t *Type) NameString() string { return tconv(t, 0, fmtTypeIDName) } @@ -677,7 +697,7 @@ func FmtConst(v constant.Value, sharp bool) string { // TypeHash computes a hash value for type t to use in type switch statements. func TypeHash(t *Type) uint32 { - p := t.LongString() + p := t.NameString() // Using MD5 is overkill, but reduces accidental collisions. h := md5.Sum([]byte(p)) diff --git a/src/cmd/compile/internal/types/type.go b/src/cmd/compile/internal/types/type.go index 075009d6a3b..7f750007972 100644 --- a/src/cmd/compile/internal/types/type.go +++ b/src/cmd/compile/internal/types/type.go @@ -2129,7 +2129,7 @@ func TypeSymLookup(name string) *Sym { } func TypeSymName(t *Type) string { - name := t.ShortString() + name := t.LinkString() // Use a separate symbol name for Noalg types for #17752. if TypeHasNoAlg(t) { name = "noalg." + name diff --git a/src/cmd/compile/internal/walk/order.go b/src/cmd/compile/internal/walk/order.go index 62d9b95be90..59701613c35 100644 --- a/src/cmd/compile/internal/walk/order.go +++ b/src/cmd/compile/internal/walk/order.go @@ -78,7 +78,7 @@ func (o *orderState) newTemp(t *types.Type, clear bool) *ir.Name { var v *ir.Name // Note: LongString is close to the type equality we want, // but not exactly. We still need to double-check with types.Identical. - key := t.LongString() + key := t.NameString() a := o.free[key] for i, n := range a { if types.Identical(t, n.Type()) { @@ -370,7 +370,7 @@ func (o *orderState) markTemp() ordermarker { // which must have been returned by markTemp. func (o *orderState) popTemp(mark ordermarker) { for _, n := range o.temp[mark:] { - key := n.Type().LongString() + key := n.Type().NameString() o.free[key] = append(o.free[key], n) } o.temp = o.temp[:mark]