aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-12-16 12:55:15 -0800
committerMatthew Dempsky <mdempsky@google.com>2022-01-10 17:54:35 +0000
commit933f6685f7d33f3865d6ef062cbb0944d3f5d2fc (patch)
tree4dac3f9af4c69071a3a94ee40e90e58fa01d10b1 /src/cmd
parent9e7ea3566e662ba498d64cb63146575202a053ee (diff)
downloadgo-933f6685f7d33f3865d6ef062cbb0944d3f5d2fc.tar.gz
go-933f6685f7d33f3865d6ef062cbb0944d3f5d2fc.zip
cmd/compile: unique LinkString for renamed, embedded fields
Using type aliases, it's possible to create structs with embedded fields that have no corresponding type literal notation. However, we still need to generate a unique name for these types to use for linker symbols. This CL introduces a new "struct{ Name = Type }" syntax for use in LinkString formatting to represent these types. Fixes #50190. Change-Id: I025ceb09a86e00b7583d3b9885d612f5d6cb44fe Reviewed-on: https://go-review.googlesource.com/c/go/+/372914 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Trust: Matthew Dempsky <mdempsky@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com> Trust: Dan Scales <danscales@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Robert Griesemer <gri@golang.org>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/types/fmt.go37
1 files changed, 35 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/types/fmt.go b/src/cmd/compile/internal/types/fmt.go
index 3198a1f53c..1399483424 100644
--- a/src/cmd/compile/internal/types/fmt.go
+++ b/src/cmd/compile/internal/types/fmt.go
@@ -631,6 +631,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
}
var name string
+ nameSep := " "
if verb != 'S' {
s := f.Sym
@@ -639,9 +640,41 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
s = OrigSym(s)
}
- if s != nil && f.Embedded == 0 {
+ if s != nil {
if funarg != FunargNone {
name = fmt.Sprint(f.Nname)
+ } else if f.Embedded != 0 {
+ // Using type aliases and embedded fields, it's possible to
+ // construct types that can't be directly represented as a
+ // type literal. For example, given "type Int = int" (#50190),
+ // it would be incorrect to format "struct{ Int }" as either
+ // "struct{ int }" or "struct{ Int int }", because those each
+ // represent other, distinct types.
+ //
+ // So for the purpose of LinkString (i.e., fmtTypeID), we use
+ // the non-standard syntax "struct{ Int = int }" to represent
+ // embedded fields that have been renamed through the use of
+ // type aliases.
+ if mode == fmtTypeID {
+ // Compute styp, the symbol that would normally be used as
+ // the field name when embedding f.Type.
+ // TODO(mdempsky): Check for other occurences of this logic
+ // and deduplicate.
+ typ := f.Type
+ if typ.Sym() == nil && typ.IsPtr() {
+ typ = typ.Elem()
+ }
+ styp := typ.Sym()
+ if styp != nil && IsExported(styp.Name) {
+ styp = LocalPkg.Lookup(styp.Name)
+ }
+
+ // If embedded field was renamed, use syntax extension.
+ if s != styp {
+ name = sconv(s, 0, mode)
+ nameSep = " = "
+ }
+ }
} else if verb == 'L' {
name = s.Name
if name == ".F" {
@@ -658,7 +691,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
if name != "" {
b.WriteString(name)
- b.WriteString(" ")
+ b.WriteString(nameSep)
}
if f.IsDDD() {