}
}
+func TestIssue61737(t *testing.T) {
+ // This test verifies that it is possible to construct invalid interfaces
+ // containing duplicate methods using the go/types API.
+ //
+ // It must be possible for importers to construct such invalid interfaces.
+ // Previously, this panicked.
+
+ sig1 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[Int])), nil, false)
+ sig2 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[String])), nil, false)
+
+ methods := []*Func{
+ NewFunc(nopos, nil, "M", sig1),
+ NewFunc(nopos, nil, "M", sig2),
+ }
+
+ embeddedMethods := []*Func{
+ NewFunc(nopos, nil, "M", sig2),
+ }
+ embedded := NewInterfaceType(embeddedMethods, nil)
+ iface := NewInterfaceType(methods, []Type{embedded})
+ iface.NumMethods() // unlike go/types, there is no Complete() method, so we complete implicitly
+}
+
func TestIssue15305(t *testing.T) {
const src = "package p; func f() int16; var _ = f(undef)"
f := mustParse(src)
import (
"cmd/compile/internal/syntax"
- "fmt"
. "internal/types/errors"
"sort"
"strings"
// we can get rid of the mpos map below and simply use the cloned method's
// position.
- var todo []*Func
var seen objset
var allMethods []*Func
mpos := make(map[*Func]syntax.Pos) // method specification or method embedding position, for good error messages
allMethods = append(allMethods, m)
mpos[m] = pos
case explicit:
- if check == nil {
- panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name))
+ if check != nil {
+ var err error_
+ err.code = DuplicateDecl
+ err.errorf(pos, "duplicate method %s", m.name)
+ err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
+ check.report(&err)
}
- // check != nil
- var err error_
- err.code = DuplicateDecl
- err.errorf(pos, "duplicate method %s", m.name)
- err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
- check.report(&err)
default:
// We have a duplicate method name in an embedded (not explicitly declared) method.
// Check method signatures after all types are computed (go.dev/issue/33656).
// If we're pre-go1.14 (overlapping embeddings are not permitted), report that
// error here as well (even though we could do it eagerly) because it's the same
// error message.
- if check == nil {
- // check method signatures after all locally embedded interfaces are computed
- todo = append(todo, m, other.(*Func))
- break
+ if check != nil {
+ check.later(func() {
+ if !check.allowVersion(m.pkg, pos, go1_14) || !Identical(m.typ, other.Type()) {
+ var err error_
+ err.code = DuplicateDecl
+ err.errorf(pos, "duplicate method %s", m.name)
+ err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
+ check.report(&err)
+ }
+ }).describef(pos, "duplicate method check for %s", m.name)
}
- // check != nil
- check.later(func() {
- if !check.allowVersion(m.pkg, pos, go1_14) || !Identical(m.typ, other.Type()) {
- var err error_
- err.code = DuplicateDecl
- err.errorf(pos, "duplicate method %s", m.name)
- err.errorf(mpos[other.(*Func)], "other declaration of %s", m.name)
- check.report(&err)
- }
- }).describef(pos, "duplicate method check for %s", m.name)
}
}
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
- // process todo's (this only happens if check == nil)
- for i := 0; i < len(todo); i += 2 {
- m := todo[i]
- other := todo[i+1]
- if !Identical(m.typ, other.typ) {
- panic(fmt.Sprintf("%s: duplicate method %s", m.pos, m.name))
- }
- }
-
ityp.tset.comparable = allComparable
if len(allMethods) != 0 {
sortMethods(allMethods)
}
}
+func TestIssue61737(t *testing.T) {
+ // This test verifies that it is possible to construct invalid interfaces
+ // containing duplicate methods using the go/types API.
+ //
+ // It must be possible for importers to construct such invalid interfaces.
+ // Previously, this panicked.
+
+ sig1 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[Int])), nil, false)
+ sig2 := NewSignatureType(nil, nil, nil, NewTuple(NewParam(nopos, nil, "", Typ[String])), nil, false)
+
+ methods := []*Func{
+ NewFunc(nopos, nil, "M", sig1),
+ NewFunc(nopos, nil, "M", sig2),
+ }
+
+ embeddedMethods := []*Func{
+ NewFunc(nopos, nil, "M", sig2),
+ }
+ embedded := NewInterfaceType(embeddedMethods, nil)
+ iface := NewInterfaceType(methods, []Type{embedded})
+ iface.Complete()
+}
+
func TestIssue15305(t *testing.T) {
const src = "package p; func f() int16; var _ = f(undef)"
fset := token.NewFileSet()
package types
import (
- "fmt"
"go/token"
. "internal/types/errors"
"sort"
// we can get rid of the mpos map below and simply use the cloned method's
// position.
- var todo []*Func
var seen objset
var allMethods []*Func
mpos := make(map[*Func]token.Pos) // method specification or method embedding position, for good error messages
allMethods = append(allMethods, m)
mpos[m] = pos
case explicit:
- if check == nil {
- panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name))
+ if check != nil {
+ check.errorf(atPos(pos), DuplicateDecl, "duplicate method %s", m.name)
+ check.errorf(atPos(mpos[other.(*Func)]), DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
}
- // check != nil
- check.errorf(atPos(pos), DuplicateDecl, "duplicate method %s", m.name)
- check.errorf(atPos(mpos[other.(*Func)]), DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
default:
// We have a duplicate method name in an embedded (not explicitly declared) method.
// Check method signatures after all types are computed (go.dev/issue/33656).
// If we're pre-go1.14 (overlapping embeddings are not permitted), report that
// error here as well (even though we could do it eagerly) because it's the same
// error message.
- if check == nil {
- // check method signatures after all locally embedded interfaces are computed
- todo = append(todo, m, other.(*Func))
- break
+ if check != nil {
+ check.later(func() {
+ if !check.allowVersion(m.pkg, atPos(pos), go1_14) || !Identical(m.typ, other.Type()) {
+ check.errorf(atPos(pos), DuplicateDecl, "duplicate method %s", m.name)
+ check.errorf(atPos(mpos[other.(*Func)]), DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
+ }
+ }).describef(atPos(pos), "duplicate method check for %s", m.name)
}
- // check != nil
- check.later(func() {
- if !check.allowVersion(m.pkg, atPos(pos), go1_14) || !Identical(m.typ, other.Type()) {
- check.errorf(atPos(pos), DuplicateDecl, "duplicate method %s", m.name)
- check.errorf(atPos(mpos[other.(*Func)]), DuplicateDecl, "\tother declaration of %s", m.name) // secondary error, \t indented
- }
- }).describef(atPos(pos), "duplicate method check for %s", m.name)
}
}
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
- // process todo's (this only happens if check == nil)
- for i := 0; i < len(todo); i += 2 {
- m := todo[i]
- other := todo[i+1]
- if !Identical(m.typ, other.typ) {
- panic(fmt.Sprintf("%v: duplicate method %s", m.pos, m.name))
- }
- }
-
ityp.tset.comparable = allComparable
if len(allMethods) != 0 {
sortMethods(allMethods)