Skip to content

Commit 80c79ed

Browse files
mdempskyjproberts
authored andcommitted
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 golang#50190. Change-Id: I025ceb09a86e00b7583d3b9885d612f5d6cb44fe Reviewed-on: https://go-review.googlesource.com/c/go/+/372914 Run-TryBot: Matthew Dempsky <[email protected]> Trust: Matthew Dempsky <[email protected]> TryBot-Result: Gopher Robot <[email protected]> Reviewed-by: Dan Scales <[email protected]> Trust: Dan Scales <[email protected]> Reviewed-by: Cuong Manh Le <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent ac9b72f commit 80c79ed

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

src/cmd/compile/internal/types/fmt.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -631,6 +631,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
631631
}
632632

633633
var name string
634+
nameSep := " "
634635
if verb != 'S' {
635636
s := f.Sym
636637

@@ -639,9 +640,41 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
639640
s = OrigSym(s)
640641
}
641642

642-
if s != nil && f.Embedded == 0 {
643+
if s != nil {
643644
if funarg != FunargNone {
644645
name = fmt.Sprint(f.Nname)
646+
} else if f.Embedded != 0 {
647+
// Using type aliases and embedded fields, it's possible to
648+
// construct types that can't be directly represented as a
649+
// type literal. For example, given "type Int = int" (#50190),
650+
// it would be incorrect to format "struct{ Int }" as either
651+
// "struct{ int }" or "struct{ Int int }", because those each
652+
// represent other, distinct types.
653+
//
654+
// So for the purpose of LinkString (i.e., fmtTypeID), we use
655+
// the non-standard syntax "struct{ Int = int }" to represent
656+
// embedded fields that have been renamed through the use of
657+
// type aliases.
658+
if mode == fmtTypeID {
659+
// Compute styp, the symbol that would normally be used as
660+
// the field name when embedding f.Type.
661+
// TODO(mdempsky): Check for other occurences of this logic
662+
// and deduplicate.
663+
typ := f.Type
664+
if typ.Sym() == nil && typ.IsPtr() {
665+
typ = typ.Elem()
666+
}
667+
styp := typ.Sym()
668+
if styp != nil && IsExported(styp.Name) {
669+
styp = LocalPkg.Lookup(styp.Name)
670+
}
671+
672+
// If embedded field was renamed, use syntax extension.
673+
if s != styp {
674+
name = sconv(s, 0, mode)
675+
nameSep = " = "
676+
}
677+
}
645678
} else if verb == 'L' {
646679
name = s.Name
647680
if name == ".F" {
@@ -658,7 +691,7 @@ func fldconv(b *bytes.Buffer, f *Field, verb rune, mode fmtMode, visited map[*Ty
658691

659692
if name != "" {
660693
b.WriteString(name)
661-
b.WriteString(" ")
694+
b.WriteString(nameSep)
662695
}
663696

664697
if f.IsDDD() {

test/fixedbugs/issue50190.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// run
2+
3+
// Copyright 2021 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package main
8+
9+
type int float32
10+
11+
type Int = int
12+
13+
type A = struct{ int }
14+
type B = struct{ Int }
15+
16+
func main() {
17+
var x, y interface{} = A{}, B{}
18+
if x == y {
19+
panic("FAIL")
20+
}
21+
}

0 commit comments

Comments
 (0)