Go version
go version go1.26.1 linux/arm64
Also reproduced on both linux/amd64 and darwin/arm64 with go1.26.1.
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=''
GOARCH='arm64'
GOARM64='v8.0'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/root/.cache/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/root/.config/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -pthread -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build2790008987=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='arm64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/root/.config/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='local'
GOTOOLDIR='/usr/local/go/pkg/tool/linux_arm64'
GOVCS=''
GOVERSION='go1.26.1'
GOWORK=''
PKG_CONFIG='pkg-config'
What did you do?
Called a promoted method (LinkTo) on a generic interface variable. The method is promoted from a value-embedded generic struct (PipelineElement[O]) and is not overridden by either implementation.
The interface variable is assigned via a "factory then conditionally overwrite" pattern where one branch is dead code due to constant folding.
Minimal reproducer:
package main
import "fmt"
type AudioBuffer struct {
Buffer []int16
}
type Sink[O any] interface {
Chain(O)
}
type Src[O any] interface {
LinkTo(Sink[O])
}
type Filter[I, O any] interface {
Sink[I]
Src[O]
}
type TypePreservingFilter[IO any] interface {
Filter[IO, IO]
}
type PipelineElement[O any] struct {
chain func(O)
}
func (e *PipelineElement[O]) LinkTo(sink Sink[O]) {
e.chain = sink.Chain
}
type IdentityFilter[IO any] struct {
PipelineElement[IO] // value embedding
}
func (f *IdentityFilter[IO]) Chain(data IO) {}
type MonoConverter struct {
PipelineElement[*AudioBuffer] // value embedding
}
func (r *MonoConverter) Chain(ab *AudioBuffer) {}
type Resampler struct {
PipelineElement[*AudioBuffer] // value embedding
}
func (r *Resampler) Chain(ab *AudioBuffer) {}
func NewOptionalFilter[IO any]() TypePreservingFilter[IO] {
return &IdentityFilter[IO]{}
}
func main() {
isMono := true
sampleRate := 48000
apiSampleRate := 16000
monoConverter := NewOptionalFilter[*AudioBuffer]()
if !isMono { // dead branch
monoConverter = &MonoConverter{}
}
resampler := NewOptionalFilter[*AudioBuffer]()
if sampleRate != apiSampleRate { // taken branch
resampler = &Resampler{}
}
fmt.Printf("monoConverter: %T\n", monoConverter)
fmt.Printf("resampler: %T\n", resampler)
monoConverter.LinkTo(resampler) // panics
fmt.Println("OK")
}
What did you see happen?
monoConverter: *main.IdentityFilter[*main.AudioBuffer]
resampler: *main.Resampler
panic: interface conversion: main.TypePreservingFilter[*main.AudioBuffer] is *main.IdentityFilter[*main.AudioBuffer], not *main.MonoConverter
goroutine 1 [running]:
main.main()
/main.go:74 +0xe8
exit status 2
The panic performs a type assertion to *main.MonoConverter that does not exist in the source code — the compiler inserted it during devirtualization.
What did you expect to see?
monoConverter: *main.IdentityFilter[*main.AudioBuffer]
resampler: *main.Resampler
OK
Go version
go version go1.26.1 linux/arm64
Also reproduced on both linux/amd64 and darwin/arm64 with go1.26.1.
Output of
go envin your module/workspace:What did you do?
Called a promoted method (
LinkTo) on a generic interface variable. The method is promoted from a value-embedded generic struct (PipelineElement[O]) and is not overridden by either implementation.The interface variable is assigned via a "factory then conditionally overwrite" pattern where one branch is dead code due to constant folding.
Minimal reproducer:
What did you see happen?
The panic performs a type assertion to
*main.MonoConverterthat does not exist in the source code — the compiler inserted it during devirtualization.What did you expect to see?