diff --git a/src/cmd/compile/internal/gc/dcl.go b/src/cmd/compile/internal/gc/dcl.go index 4336f8e6d9..973016f97c 100644 --- a/src/cmd/compile/internal/gc/dcl.go +++ b/src/cmd/compile/internal/gc/dcl.go @@ -1275,7 +1275,9 @@ func addmethod(msym *Sym, t *Type, tpkg *Pkg, local, nointerface bool) { if msym.Name != f.Sym.Name { continue } - if !Eqtype(t, f.Type) { + // Eqtype only checks that incoming and result parameters match, + // so explicitly check that the receiver parameters match too. + if !Eqtype(t, f.Type) || !Eqtype(t.Recvs(), f.Type.Recvs()) { Yyerror("method redeclared: %v.%v\n\t%v\n\t%v", pa, msym, f.Type, t) } return diff --git a/src/cmd/compile/internal/gc/subr.go b/src/cmd/compile/internal/gc/subr.go index 88ca06903c..31efa6269e 100644 --- a/src/cmd/compile/internal/gc/subr.go +++ b/src/cmd/compile/internal/gc/subr.go @@ -726,9 +726,11 @@ func eqtype1(t1, t2 *Type, assumedEqual map[typePair]struct{}) bool { } return false - // Loop over structs: receiver, in, out. case TFUNC: - for _, f := range recvsParamsResults { + // Check parameters and result parameters for type equality. + // We intentionally ignore receiver parameters for type + // equality, because they're never relevant. + for _, f := range paramsResults { // Loop over fields in structs, ignoring argument names. ta, ia := IterFields(f(t1)) tb, ib := IterFields(f(t2)) @@ -2127,10 +2129,9 @@ func implements(t, iface *Type, m, samename **Field, ptr *int) bool { if im.Broke { continue } - imtype := methodfunc(im.Type, nil) var followptr bool tm := ifacelookdot(im.Sym, t, &followptr, false) - if tm == nil || tm.Nointerface || !Eqtype(methodfunc(tm.Type, nil), imtype) { + if tm == nil || tm.Nointerface || !Eqtype(tm.Type, im.Type) { if tm == nil { tm = ifacelookdot(im.Sym, t, &followptr, true) } diff --git a/src/cmd/compile/internal/gc/type.go b/src/cmd/compile/internal/gc/type.go index 2f05f4e5c5..9d0207d476 100644 --- a/src/cmd/compile/internal/gc/type.go +++ b/src/cmd/compile/internal/gc/type.go @@ -300,6 +300,11 @@ var recvsParamsResults = [3]func(*Type) *Type{ (*Type).Recvs, (*Type).Params, (*Type).Results, } +// paramsResults is like recvsParamsResults, but omits receiver parameters. +var paramsResults = [2]func(*Type) *Type{ + (*Type).Params, (*Type).Results, +} + // Key returns the key type of map type t. func (t *Type) Key() *Type { t.wantEtype(TMAP) diff --git a/test/method1.go b/test/method1.go index 365b8ca553..bb8c81d746 100644 --- a/test/method1.go +++ b/test/method1.go @@ -9,12 +9,16 @@ package main -type T struct { } -func (t *T) M(int, string) // GCCGO_ERROR "previous" -func (t *T) M(int, float64) { } // ERROR "redeclared|redefinition" +type T struct{} -func f(int, string) // GCCGO_ERROR "previous" -func f(int, float64) { } // ERROR "redeclared|redefinition" +func (t *T) M(int, string) // GCCGO_ERROR "previous" +func (t *T) M(int, float64) {} // ERROR "redeclared|redefinition" -func g(a int, b string) // GCCGO_ERROR "previous" -func g(a int, c string) // ERROR "redeclared|redefinition" +func (t T) H() // GCCGO_ERROR "previous" +func (t *T) H() {} // ERROR "redeclared|redefinition" + +func f(int, string) // GCCGO_ERROR "previous" +func f(int, float64) {} // ERROR "redeclared|redefinition" + +func g(a int, b string) // GCCGO_ERROR "previous" +func g(a int, c string) // ERROR "redeclared|redefinition"