diff options
author | Matthew Dempsky <mdempsky@google.com> | 2021-12-16 12:55:15 -0800 |
---|---|---|
committer | Matthew Dempsky <mdempsky@google.com> | 2022-01-10 17:54:35 +0000 |
commit | 933f6685f7d33f3865d6ef062cbb0944d3f5d2fc (patch) | |
tree | 4dac3f9af4c69071a3a94ee40e90e58fa01d10b1 /src/cmd | |
parent | 9e7ea3566e662ba498d64cb63146575202a053ee (diff) | |
download | go-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.go | 37 |
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() { |