Go version

go version go1.25-20250711-RC00 REDACTED +6ebb5f56d9 X:fieldtrack,boringcrypto 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='0'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='g++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v3'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='REDACTED'
GOCACHEPROG=''
GODEBUG=''
GOENV='REDACTED'
GOEXE=''
GOEXPERIMENT='fieldtrack,boringcrypto'
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -m64 -Wl,--no-gc-sections -fmessage-length=0 -ffile-prefix-map=/tmp/go-build889680920=/tmp/go-build -gno-record-gcc-switches'
GOHOSTARCH='amd64'
GOHOSTOS='linux'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='REDACTED'
GONOPROXY=''
GONOSUMDB=''
GOOS='linux'
GOPATH='REDACTED'
GOPRIVATE=''
GOPROXY=''
GOROOT='REDACTED'
GOSUMDB=''
GOTELEMETRY='local'
GOTELEMETRYDIR='REDACTED'
GOTMPDIR=''
GOTOOLCHAIN=''
GOTOOLDIR='REDACTED'
GOVCS=''
GOVERSION='go1.25-20250711-RC00 REDACTED +6ebb5f56d9 X:fieldtrack,boringcrypto'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

We use //go:nointerface within a project, and we encountered the following issue:

package missing_method_repro_test

import "testing"

type Fooer interface {
    Foo() string
}

type FooImpl struct{}

//go:nointerface
func (FooImpl) Foo() string { return "foo" }

func toInterface[T Fooer](fooer T) Fooer {
    return fooer
}

func TestFooer(t *testing.T) {
    var iface Fooer = toInterface(FooImpl{})
    if iface == nil {
        t.Errorf("iface = nil, want non-nil")
    }
    if iface.Foo == nil {
        t.Errorf("iface.Foo = nil, want non-nil")
    }
    iface.Foo() // panics with nil pointer dereference
}

What did you see happen?

So even though a method is marked as nointerface, it's valid to pass this to function with the interface as a type constraint (and calling the method actually works). It looks like it's also valid to pass this value to an interface (because it passes assignability rules in the generic). And while the interface method even returns non-nil, calling the mehtod results in a nil pointer dereference. Please note that the following workaround works:

type dispatch func() string

func (d dispatch) Foo() string {
  return d()
}

func toInterface[T Fooer](fooer T) Fooer {
    return dispatch(fooer.Foo)
}

What did you expect to see?

Since the manual dispatch approach works, I guess the compiler could just figure out how to do this kind of dispatching itself.

Comment From: cherrymui

So even though a method is marked as nointerface, it's valid to pass this to function with the interface as a type constraint

I think this should not be allowed. A type constraint is an interface. So if a type does not satisfy a regular interface, it should also not satisfy the same interface as a type constraint.

cc @golang/compiler @mrkfrmn

Comment From: zoltanhalassy

I think this should not be allowed.

I don't mind personally, but please note that code exists out there right now, which relies on the generic loophole. I don't know what's the procedure around that. Disallowing it will cause compilation failures for existing code from that change though.

Comment From: cherrymui

Thanks for the note. We should analyze the internal usage and have a migration plan. Let's continue this on the internal channel. Would you mind filing an issue internally? Thanks.

Comment From: gabyhelp

Related Issues

(Emoji vote if this was helpful or unhelpful; more detailed feedback welcome in this discussion.)