cmd/compile: compute embedded field offset in static initialization

Currently, when static initializes a variable with a struct
literal, the compiler uses the field's offset in its containing
struct. This is usually correct, except that with the newly-
allowed direct access of embedded field, the offset does not
include the offset of the embedded type in its containing type.
We need to include all the implicit field offsets in the offset
calculation.

For #9859.

Change-Id: Ifa4fae77383d912fba2638538248b06a3c286373
Reviewed-on: https://go-review.googlesource.com/c/go/+/780220
LUCI-TryBot-Result: golang-scoped@luci-project-accounts.iam.gserviceaccount.com <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
Cherry Mui 2026-05-19 22:31:50 -04:00
parent dd1da37fa4
commit e2c188568d
3 changed files with 23 additions and 1 deletions

View file

@ -546,7 +546,7 @@ func (s *Schedule) initplan(n ir.Node) {
if a.Sym().IsBlank() {
continue
}
s.addvalue(p, a.Field.Offset, a.Value)
s.addvalue(p, typecheck.FieldOffset(n.Type(), a.Field), a.Value)
}
case ir.OMAPLIT:

View file

@ -790,3 +790,21 @@ var slist []symlink
type symlink struct {
field *types.Field
}
// FieldOffset returns the offset of field f in t,
// including any implicit offsets from embedded fields.
func FieldOffset(t *types.Type, f *types.Field) int64 {
if f.Sym == nil {
return f.Offset
}
path, ambig := dotpath(f.Sym, t, nil, false)
if path == nil || ambig {
return f.Offset
}
var offset int64
for _, d := range path {
offset += d.field.Offset
}
offset += f.Offset
return offset
}

View file

@ -28,6 +28,7 @@ type C struct {
func main() {
eq(A{1, B{b: "foo"}}, A{a: 1, b: "foo"})
eq(A{B: B{C: C{c: "foo"}}}, A{c: "foo"})
eq(x, A{B: B{b: "foo"}})
}
func eq(x, y any) {
@ -35,3 +36,6 @@ func eq(x, y any) {
panic(fmt.Sprintf("%v != %v", x, y))
}
}
// test global initializer
var x = A{b: "foo"}