Skip to content

Panic and false positives on Go 1.27 promoted-field keys in composite literals #6780

Description

@kamenlitchev

Welcome

  • Yes, I'm using a binary release within 2 latest releases. Only such installations are supported.
  • Yes, I've searched similar issues on GitHub and didn't find any.
  • Yes, I've read the typecheck section of the FAQ.
  • Yes, I've tried with the standalone linter if available (e.g., gocritic, go vet, etc.).
  • I agree to follow this project's Code of Conduct

How did you install golangci-lint?

go install

Description of the problem

Go 1.27 allows a composite literal key to be any field selector, including a promoted field of an embedded struct (spec, "Composite literals"): Outer{A: "a"} now sets Outer.Inner.A directly, with no nested Inner{...}. skippedNamed assumes every literal key names a field of the outer struct, which no longer holds. This produces two distinct symptoms from one root cause.

Version of golangci-lint

2.13.2 built with go1.27.1

Configuration

Details

.golangci.yml - every other linter off, to isolate this one:

version: "2"
linters:
  default: none
  enable:
    - exhaustruct_v5

Go environment

Details
go version go1.27.1 windows/amd64
set AR=ar
set CC=gcc
set CGO_CFLAGS=-O2 -g
set CGO_CPPFLAGS=
set CGO_CXXFLAGS=-O2 -g
set CGO_ENABLED=0
set CGO_FFLAGS=-O2 -g
set CGO_LDFLAGS=-O2 -g
set CXX=g++
set GCCGO=gccgo
set GO111MODULE=
set GOAMD64=v1
set GOARCH=amd64
set GOAUTH=netrc
set GOCACHEPROG=
set GODEBUG=
set GOEXE=.exe
set GOEXPERIMENT=
set GOFIPS140=off
set GOFLAGS=
set GOHOSTARCH=amd64
set GOHOSTOS=windows
set GOINSECURE=
set GOMOD=NUL
set GOOS=windows
set GOPACKAGESDRIVER=
set GOPROXY=https://proxy.golang.org,direct
set GOROOT=C:\Program Files\Go
set GOSUMDB=sum.golang.org
set GOTELEMETRY=local
set GOTMPDIR=
set GOTOOLCHAIN=auto
set GOTOOLDIR=C:\Program Files\Go\pkg\tool\windows_amd64
set GOVCS=
set GOVERSION=go1.27.1
set GOWORK=
set PKG_CONFIG=pkg-config

Verbose output of running

Details

Verbose output

Standalone exhaustruct ./... (no flags, no config) — exit 2

panic: runtime error: makeslice: cap out of range

goroutine 52 [running]:
dev.gaijin.team/go/exhaustruct/v5/internal/structure.(*Struct).skippedNamed(0x3a4a671301b0, 0x3a4a6712e600, 0x0)
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/internal/structure/struct.go:138 +0x195
dev.gaijin.team/go/exhaustruct/v5/internal/structure.(*Struct).SkippedFields(0x3a4a671301b0?, 0x3a4a6712e600?, {0x3a4a6711660a?, 0x3a4a671301b0?})
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/internal/structure/struct.go:86 +0x6a
dev.gaijin.team/go/exhaustruct/v5/analyzer.literalVisitor.checkLiteral({0x3a4a66fbbc28, 0x3a4a6712e600, {0x3a4a67114280, 0x5, 0x8}}, {0x3a4a671301b0?, 0xb0?, 0x33?})
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/missing-fields-visitor.go:270 +0xbd
dev.gaijin.team/go/exhaustruct/v5/analyzer.literalVisitor.process({0x3a4a66fbbc28, 0x3a4a6712e600, {0x3a4a67114280, 0x5, 0x8}})
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/missing-fields-visitor.go:105 +0xdd
dev.gaijin.team/go/exhaustruct/v5/analyzer.(*missingFieldsVisitor).visit(0x3a4a67178328?, {0x7ff766bf6030?, 0x3a4a6712e600?}, 0x0?, {0x3a4a67114280?, 0x1?, 0x3a4a67114280?})
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/missing-fields-visitor.go:54 +0x65
golang.org/x/tools/go/ast/inspector.(*Inspector).WithStack(0x3a4a6711a318, {0x3a4a66ef9c50?, 0x3a4a67102210?, 0x1?}, 0x3a4a66fbbc40)
	golang.org/x/tools@v0.40.0/go/ast/inspector/inspector.go:206 +0x186
dev.gaijin.team/go/exhaustruct/v5/analyzer.(*missingFieldsVisitor).run(...)
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/missing-fields-visitor.go:40
dev.gaijin.team/go/exhaustruct/v5/analyzer.run(0x3a4a6716e0e0, 0x3a4a66f72af0, 0x3a4a67114200)
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/analyzer.go:110 +0x1df
dev.gaijin.team/go/exhaustruct/v5/analyzer.NewAnalyzer.func2(0x3a4a6716e0e0)
	dev.gaijin.team/go/exhaustruct/v5@v5.0.3/analyzer/analyzer.go:35 +0x4f
golang.org/x/tools/go/analysis/checker.(*Action).execOnce.func3(...)
	golang.org/x/tools@v0.40.0/go/analysis/checker/checker.go:359
golang.org/x/tools/go/analysis/checker.(*Action).execOnce(0x3a4a6712c320)
	golang.org/x/tools@v0.40.0/go/analysis/checker/checker.go:380 +0xbfc
sync.(*Once).doSlow(0x3a4a6712e340?, 0x7ff76679f0e0?)
	sync/once.go:78 +0xab
sync.(*Once).Do(...)
	sync/once.go:69
golang.org/x/tools/go/analysis/checker.(*Action).exec(...)
	golang.org/x/tools@v0.40.0/go/analysis/checker/checker.go:258
golang.org/x/tools/go/analysis/checker.execAll.func1(0x3a4a66ef9f98?)
	golang.org/x/tools@v0.40.0/go/analysis/checker/checker.go:246 +0x45
created by golang.org/x/tools/go/analysis/checker.execAll in goroutine 1
	golang.org/x/tools@v0.40.0/go/analysis/checker/checker.go:252 +0x167

golangci-lint cache clean && golangci-lint run -v ./... — exit 3

level=info msg="golangci-lint has version 2.13.2 built with go1.27.1"
level=info msg="[config_reader] Used config file .golangci.yml"
level=info msg="[config_reader] Module name \"exbug\""
level=info msg="[goenv] Read go env for 55.8393ms: map[string]string{\"GOCACHE\":\"...\", \"GOROOT\":\"...\"}"
level=info msg="[lintersdb] Active 1 linters: [exhaustruct_v5]"
level=info msg="[loader] Go packages loading at mode 8767 (deps|exports_file|files|imports|name|compiled_files|types_sizes) took 673.6954ms"
level=info msg="[runner/filename_unadjuster] Pre-built 0 adjustments in 0s"
level=info msg="[linters_context/goanalysis] analyzers took 0s with top 10 stages: typecheck: 0s, inspect: 0s"
level=error msg="[runner] Panic: exhaustruct_v5: package \"exbug\" (isInitialPkg: true, needAnalyzeSource: true): runtime error: makeslice: cap out of range: goroutine 180 [running]:\nruntime/debug.Stack()\n\t...\ndev.gaijin.team/go/exhaustruct/v5/internal/structure.(*Struct).skippedNamed(...)\n\t.../internal/structure/struct.go:138 +0x195\n..."
level=warning msg="[runner] Can't run linter goanalysis_metalinter: goanalysis_metalinter: exhaustruct_v5: package \"exbug\" (isInitialPkg: true, needAnalyzeSource: true): runtime error: makeslice: cap out of range"
level=info msg="[runner] processing took 0s with stages: path_absoluter: 0s, fixer: 0s, ..."
level=info msg="[runner] linters took 2.5762ms with stages: goanalysis_metalinter: 2.5762ms"
level=error msg="Running error: can't run linter goanalysis_metalinter\ngoanalysis_metalinter: exhaustruct_v5: package \"exbug\" (isInitialPkg: true, needAnalyzeSource: true): runtime error: makeslice: cap out of range"
level=info msg="Memory: 9 samples, avg is 42.9MB, max is 43.3MB"
level=info msg="Execution took 732.1109ms"

The panic inside the level=error line is the same stack as above, with golangci-lint's goanalysis frames wrapped around it.

A minimal reproducible example or link to a public repository

Details ### 1. Panic when promoted keys outnumber the outer struct's own fields
package exbug

type Inner struct{ A, B string }

type Outer struct{ Inner }

func New() Outer {
	return Outer{A: "a", B: "b"}
}

Compiles cleanly under Go 1.27. exhaustruct ./... panics:

panic: runtime error: makeslice: cap out of range

goroutine 52 [running]:
dev.gaijin.team/go/exhaustruct/v5/internal/structure.(*Struct).skippedNamed(...)
	internal/structure/struct.go:138
dev.gaijin.team/go/exhaustruct/v5/internal/structure.(*Struct).SkippedFields(...)
	internal/structure/struct.go:86
dev.gaijin.team/go/exhaustruct/v5/analyzer.literalVisitor.checkLiteral(...)
	analyzer/missing-fields-visitor.go:270

2. False positive when the counts happen not to go negative

type Inner struct{ A string }

type Outer struct {
	Inner

	C string
}

func New() Outer {
	return Outer{A: "a", C: "c"}
}

Reports exbug.Outer is missing field Inner, though the literal initializes every field.

Validation

  • Yes, I've included all the information above (example, version, config, etc.).

Supporter

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingdependenciesRelates to an upstream dependency

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions