mirror of https://github.com/golang/go.git
go/types: report error if type list contains duplicate entries
Passes all.bash. Change-Id: I9a795c931100af662c9c62223d4e4ca0103d2af3 Reviewed-on: https://team-review.git.corp.google.com/c/golang/go2-dev/+/765675 Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
61c4506052
commit
7307dda747
|
|
@ -149,7 +149,6 @@ func _(type T)(r R2(T, int), p *R2(string, T)) {
|
|||
}
|
||||
|
||||
// An interface can (explicitly) declare at most one type list.
|
||||
// Only the first respective error is reported.
|
||||
type _ interface {
|
||||
m0()
|
||||
type int, string, bool
|
||||
|
|
@ -157,7 +156,20 @@ type _ interface {
|
|||
m1()
|
||||
m2()
|
||||
type /* ERROR multiple type lists */ complex64, complex128
|
||||
type /* ERROR multiple type lists */ bool
|
||||
type /* ERROR multiple type lists */ rune
|
||||
}
|
||||
|
||||
// Interface type lists may contain each type at most once.
|
||||
// (If there are multiple lists, we assume the author intended
|
||||
// for them to be all in a single list, and we report the error
|
||||
// as well.)
|
||||
type _ interface {
|
||||
type int, int /* ERROR duplicate type int */
|
||||
type /* ERROR multiple type lists */ int /* ERROR duplicate type int */
|
||||
}
|
||||
|
||||
type _ interface {
|
||||
type struct{f int}, struct{g int}, struct /* ERROR duplicate type */ {f int}
|
||||
}
|
||||
|
||||
// Embedding of interfaces with type lists leads to interfaces
|
||||
|
|
|
|||
|
|
@ -362,12 +362,9 @@ func typeSet(list []Type) []Type {
|
|||
// Quadratic algorithm, but probably good enough for now.
|
||||
// TODO(gri) we need a fast quick type ID/hash for all types.
|
||||
result := make([]Type, 0, len(list)) // assume types are unique
|
||||
L:
|
||||
for _, t := range list {
|
||||
for _, e := range result {
|
||||
if Identical(t, e) {
|
||||
continue L // t already in result
|
||||
}
|
||||
if contains(result, t) {
|
||||
continue
|
||||
}
|
||||
result = append(result, t)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -933,11 +933,8 @@ func intersect(x, y Type) (r Type) {
|
|||
// TODO(gri) fix this
|
||||
var rtypes []Type
|
||||
for _, x := range xtypes {
|
||||
for _, y := range ytypes {
|
||||
if Identical(x, y) {
|
||||
rtypes = append(rtypes, x)
|
||||
break
|
||||
}
|
||||
if contains(ytypes, x) {
|
||||
rtypes = append(rtypes, x)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1106,21 +1103,37 @@ func (check *Checker) collectTypeConstraints(pos token.Pos, types []ast.Expr) []
|
|||
}
|
||||
typ := check.typ(texpr)
|
||||
// A type constraint may be a predeclared type or a
|
||||
// composite type composed only of predeclared types.
|
||||
// TODO(gri) should we keep this restriction?
|
||||
// composite type composed of only predeclared types.
|
||||
var why string
|
||||
if !check.typeConstraint(typ, &why) {
|
||||
check.errorf(texpr.Pos(), "invalid type constraint %s (%s)", typ, why)
|
||||
continue
|
||||
}
|
||||
// add type
|
||||
// add type if not already in list
|
||||
// Overall, this produces a quadratic algorithm,
|
||||
// but probably good enough for now.
|
||||
// TODO(gri) fix this
|
||||
if contains(list, typ) {
|
||||
check.errorf(texpr.Pos(), "duplicate type %s in type list", typ)
|
||||
continue
|
||||
}
|
||||
list = append(list, typ)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
// TODO(gri) does this simply check for the absence of defined types?
|
||||
// (if so, should choose a better name)
|
||||
// contains reports whether typ is in list
|
||||
func contains(list []Type, typ Type) bool {
|
||||
for _, e := range list {
|
||||
if Identical(typ, e) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// typeConstraint checks that typ may be used in a type list.
|
||||
// For now this just checks for the absence of defined (*Named) types.
|
||||
func (check *Checker) typeConstraint(typ Type, why *string) bool {
|
||||
switch t := typ.(type) {
|
||||
case *Basic:
|
||||
|
|
@ -1165,7 +1178,7 @@ func (check *Checker) typeConstraint(typ Type, why *string) bool {
|
|||
case *Chan:
|
||||
return check.typeConstraint(t.elem, why)
|
||||
case *Named:
|
||||
*why = check.sprintf("%s is not a type literal", t)
|
||||
*why = check.sprintf("contains defined type %s", t)
|
||||
return false
|
||||
case *TypeParam:
|
||||
// ok, e.g.: func f (type T interface { type T }) ()
|
||||
|
|
|
|||
Loading…
Reference in New Issue