Skip to content

x/tools/go/analysis/passes/fieldalignment: fix reorders declaration but not unkeyed struct literals, changing behavior #80277

Description

@Dinichthys

Go version

1.27 linux/amd64

Output of go env in your module/workspace:

AR='ar'
CC='gcc'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/home/dinichthys/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/home/dinichthys/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2612980177=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/home/dinichthys/Codiruiy/Work/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/home/dinichthys/Codiruiy/Work/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/home/dinichthys/Codiruiy/Work/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/home/dinichthys/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/home/dinichthys/Codiruiy/Work/go/pkg/tool/linux_amd64'
GOVCS=''
GOVERSION='go1.27-devel_770243423a Sat Apr 4 16:59:04 2026 +0300'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

For example, we have structure A with following order

type A struct {
	b byte
	c int
	d byte
}

// And following usage of this structure
tmp := A{'a', 3, 'c'}

We can use fieldalignment with flag -fix to try to pack this structure effective. It will reorder fields in the structure, but won't reorder elements in curly brackets.

What did you see happen?

Code will transform into

type A struct {
	c int   // Order changed. Fields 'c' and 'b' were swapped
	b byte
	d byte
}

// So usage become invalid, but it still could be compiled, so the result of the program unexpected changed.
// It is UB, but also we can get uncompiled code same way.
tmp := A{'a', 3, 'c'}

What did you expect to see?

We should transform AST with all place of usage structure.

Expected result:

type A struct {
	c int   // Order changed. Fields 'c' and 'b' were swapped
	b byte
	d byte
}

tmp := A{3, 'a', 'c'}

Metadata

Metadata

Assignees

No one assigned

    Labels

    NeedsInvestigationSomeone must examine and confirm this is a valid issue and not a duplicate of an existing one.ToolsThis label describes issues relating to any tools in the x/tools repository.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions