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:
parent
3827909f21
commit
9fc9dd9a01
|
@ -1081,7 +1081,7 @@ func (check *checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||||
check.indexedElts(e.Elts, utyp.elem, -1)
|
check.indexedElts(e.Elts, utyp.elem, -1)
|
||||||
|
|
||||||
case *Map:
|
case *Map:
|
||||||
visited := make(map[interface{}]bool, len(e.Elts))
|
visited := make(map[interface{}][]Type, len(e.Elts))
|
||||||
for _, e := range e.Elts {
|
for _, e := range e.Elts {
|
||||||
kv, _ := e.(*ast.KeyValueExpr)
|
kv, _ := e.(*ast.KeyValueExpr)
|
||||||
if kv == nil {
|
if kv == nil {
|
||||||
|
@ -1096,11 +1096,24 @@ func (check *checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if x.mode == constant {
|
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)
|
check.errorf(x.pos(), "duplicate key %s in map literal", x.val)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
visited[x.val] = true
|
|
||||||
}
|
}
|
||||||
check.exprWithHint(x, kv.Value, utyp.elem)
|
check.exprWithHint(x, kv.Value, utyp.elem)
|
||||||
if !check.assignment(x, utyp.elem) {
|
if !check.assignment(x, utyp.elem) {
|
||||||
|
|
|
@ -291,6 +291,9 @@ func slice_literals() {
|
||||||
|
|
||||||
const index2 int = 2
|
const index2 int = 2
|
||||||
|
|
||||||
|
type N int
|
||||||
|
func (N) f() {}
|
||||||
|
|
||||||
func map_literals() {
|
func map_literals() {
|
||||||
type M0 map[string]int
|
type M0 map[string]int
|
||||||
type M1 map[bool]int
|
type M1 map[bool]int
|
||||||
|
@ -302,6 +305,23 @@ func map_literals() {
|
||||||
_ = M0{"foo": "bar" /* ERROR "cannot convert" */ }
|
_ = M0{"foo": "bar" /* ERROR "cannot convert" */ }
|
||||||
_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
|
_ = 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
|
// map keys must be resolved correctly
|
||||||
key1 := "foo"
|
key1 := "foo"
|
||||||
_ = M0{key1: 1}
|
_ = M0{key1: 1}
|
||||||
|
|
Loading…
Reference in New Issue