go.tools/go/types: dup check interface keys in composite map literals correctly

Specifically, take into account the key type.

LGTM=gri
R=gri
CC=golang-codereviews
https://golang.org/cl/103080044
This commit is contained in:
Peter Collingbourne 2014-06-11 10:01:51 -07:00 committed by Robert Griesemer
parent 3827909f21
commit 9fc9dd9a01
2 changed files with 36 additions and 3 deletions

View File

@ -1081,7 +1081,7 @@ func (check *checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
check.indexedElts(e.Elts, utyp.elem, -1)
case *Map:
visited := make(map[interface{}]bool, len(e.Elts))
visited := make(map[interface{}][]Type, len(e.Elts))
for _, e := range e.Elts {
kv, _ := e.(*ast.KeyValueExpr)
if kv == nil {
@ -1096,11 +1096,24 @@ func (check *checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
continue
}
if x.mode == constant {
if visited[x.val] {
duplicate := false
// if the key is of interface type, the type is also significant when checking for duplicates
if _, ok := utyp.key.Underlying().(*Interface); ok {
for _, vtyp := range visited[x.val] {
if Identical(vtyp, x.typ) {
duplicate = true
break
}
}
visited[x.val] = append(visited[x.val], x.typ)
} else {
_, duplicate = visited[x.val]
visited[x.val] = nil
}
if duplicate {
check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
continue
}
visited[x.val] = true
}
check.exprWithHint(x, kv.Value, utyp.elem)
if !check.assignment(x, utyp.elem) {

View File

@ -291,6 +291,9 @@ func slice_literals() {
const index2 int = 2
type N int
func (N) f() {}
func map_literals() {
type M0 map[string]int
type M1 map[bool]int
@ -302,6 +305,23 @@ func map_literals() {
_ = M0{"foo": "bar" /* ERROR "cannot convert" */ }
_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
_ = map[interface{}]int{2: 1, 2 /* ERROR "duplicate key" */ : 1}
_ = map[interface{}]int{int(2): 1, int16(2): 1}
_ = map[interface{}]int{int16(2): 1, int16 /* ERROR "duplicate key" */ (2): 1}
type S string
_ = map[interface{}]int{"a": 1, "a" /* ERROR "duplicate key" */ : 1}
_ = map[interface{}]int{"a": 1, S("a"): 1}
_ = map[interface{}]int{S("a"): 1, S /* ERROR "duplicate key" */ ("a"): 1}
type I interface {
f()
}
_ = map[I]int{N(0): 1, N(2): 1}
_ = map[I]int{N(2): 1, N /* ERROR "duplicate key" */ (2): 1}
// map keys must be resolved correctly
key1 := "foo"
_ = M0{key1: 1}