What version of Go are you using (go version)?

$ go version
go version go1.20.6 linux/amd64

Does this issue reproduce with the latest release?

Yes

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GO111MODULE=""
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/sz/.cache/go-build"
GOENV="/home/sz/.config/go/env"
GOEXE=""
GOEXPERIMENT=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOINSECURE=""
GOMODCACHE="/home/sz/go/pkg/mod"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/home/sz/go"
GOPRIVATE=""
GOPROXY="https://proxy.golang.org,direct"
GOROOT="/usr/lib/go"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GOVCS=""
GOVERSION="go1.20.6"
GCCGO="gccgo"
GOAMD64="v1"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
GOWORK=""
CGO_CFLAGS="-O2 -g"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-O2 -g"
CGO_FFLAGS="-O2 -g"
CGO_LDFLAGS="-O2 -g"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -Wl,--no-gc-sections -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build2006396805=/tmp/go-build -gno-record-gcc-switches"

What did you do?

Consider the following code: https://go.dev/play/p/6MPHjq0B5km

It invokes reflect.StructOf method with two embedded fields, a struct and an interface. The resulting type has three methods, according to reflect.Type.NumMethod() function. The method list isn't lexicographically sorted and contains duplicates.

reflect.StructOf has its limitations documented in godoc, but it doesn't explain the observed behavior.

What did you expect to see?

Output:

Method 0: M1
Method 1: M2

What did you see instead?

Output:

Method 0: M1
Method 1: M2
Method 2: M1

Comment From: seankhliao

looks like a known limitation: https://cs.opensource.google/go/go/+/refs/tags/go1.20.6:src/reflect/type.go;l=2685

Comment From: g7r

@seankhliao, kind of yes. reflect.StructOf is really limited when it comes to embedding fields with methods. Nonetheless, reflect.StructOf allows me to create types that break contracts.

Comment From: heschi

cc @golang/runtime

Comment From: cherrymui

If we create such a struct in Go, it only has the M2 method: https://go.dev/play/p/wpUZ9HSrQQC . The ambiguous M1 method is not included in the method set of the outer struct. I think the reflect package should do that as well. I.e. the expected output would be just

Method 0: M2

Comment From: cherrymui

As we currently don't support embedding multiple non-interface fields, the duplicates must be from interface fields. I'm curious about your use case. As far as I can tell, calling embedded interface method doesn't seem to work.