// Inline body index.
for nPkgs := ird.uint64(); nPkgs > 0; nPkgs-- {
pkg := p.pkgAt(ird.uint64())
+ pkgPrefix := pkg.Prefix + "."
for nSyms := ird.uint64(); nSyms > 0; nSyms-- {
- s := pkg.Lookup(p.stringAt(ird.uint64()))
+ s2 := p.stringAt(ird.uint64())
+ // Function/method instantiation names may include "" to
+ // represent the path name of the imported package (in type
+ // names), so replace "" with pkg.Prefix. The "" in the names
+ // will get replaced by the linker as well, so will not
+ // appear in the executable. Include the dot to avoid
+ // matching with struct tags ending in '"'.
+ s2 = strings.Replace(s2, "\"\".", pkgPrefix, -1)
+ s := pkg.Lookup(s2)
off := ird.uint64()
if _, ok := inlineImporter[s]; !ok {
if i > 0 {
b.WriteByte(',')
}
- // Use NameString(), which includes the package name for the local
- // package, to make sure that type arguments (including type params),
- // are uniquely specified.
- tstring := targ.NameString()
- // types1 uses "interface {" and types2 uses "interface{" - convert
- // to consistent types2 format. Same for "struct {"
- tstring = strings.Replace(tstring, "interface {", "interface{", -1)
- tstring = strings.Replace(tstring, "struct {", "struct{", -1)
+ // Make sure that type arguments (including type params), are
+ // uniquely specified. LinkString() eliminates all spaces
+ // and includes the package path (local package path is "" before
+ // linker substitution).
+ tstring := targ.LinkString()
b.WriteString(tstring)
}
b.WriteString("]")
return s
}
+ // LinkString specifies the type uniquely, but has no spaces.
nm := fmt.Sprintf("%s_%d", u.LinkString(), index)
sym := types.ShapePkg.Lookup(nm)
if sym.Def != nil {
// The default is regular Go syntax (fmtGo).
// fmtDebug is like fmtGo but for debugging dumps and prints the type kind too.
// fmtTypeID and fmtTypeIDName are for generating various unique representations
-// of types used in hashes and the linker.
+// of types used in hashes, the linker, and function/method instantiations.
type fmtMode int
const (
case TINTER:
if t.IsEmptyInterface() {
- b.WriteString("interface {}")
+ if mode == fmtTypeID {
+ b.WriteString("interface{}")
+ } else {
+ b.WriteString("interface {}")
+ }
break
}
- b.WriteString("interface {")
+ if mode == fmtTypeID {
+ b.WriteString("interface{")
+ } else {
+ b.WriteString("interface {")
+ }
for i, f := range t.AllMethods().Slice() {
if i != 0 {
b.WriteByte(';')
}
- b.WriteByte(' ')
+ if mode != fmtTypeID {
+ b.WriteByte(' ')
+ }
switch {
case f.Sym == nil:
// Check first that a symbol is defined for this type.
}
tconv2(b, f.Type, 'S', mode, visited)
}
- if t.AllMethods().Len() != 0 {
+ if t.AllMethods().Len() != 0 && mode != fmtTypeID {
b.WriteByte(' ')
}
b.WriteByte('}')
}
b.WriteByte(byte(close))
} else {
- b.WriteString("struct {")
+ if mode == fmtTypeID {
+ b.WriteString("struct{")
+ } else {
+ b.WriteString("struct {")
+ }
for i, f := range t.Fields().Slice() {
if i != 0 {
b.WriteByte(';')
}
- b.WriteByte(' ')
+ if mode != fmtTypeID {
+ b.WriteByte(' ')
+ }
fldconv(b, f, 'L', mode, visited, funarg)
}
- if t.NumFields() != 0 {
+ if t.NumFields() != 0 && mode != fmtTypeID {
b.WriteByte(' ')
}
b.WriteByte('}')
if name != "" {
b.WriteString(name)
- b.WriteString(" ")
+ if mode == fmtTypeID {
+ // This is the one case where we can't omit the space, since
+ // we need a separate between field name and type, so we use
+ // "#" instead.
+ b.WriteString("#")
+ } else {
+ b.WriteString(" ")
+ }
}
if f.IsDDD() {
}
if verb != 'S' && funarg == FunargNone && f.Note != "" {
- b.WriteString(" ")
+ if mode != fmtTypeID {
+ b.WriteString(" ")
+ }
+ // TODO: for fmtTypeID, we should possibly using %-quoting, so
+ // space is %20, etc.
b.WriteString(strconv.Quote(f.Note))
}
}