diff --git a/_test/map21.go b/_test/map21.go new file mode 100644 index 000000000..48a06bdab --- /dev/null +++ b/_test/map21.go @@ -0,0 +1,15 @@ +package main + +var m = map[int]string{ + 1: "foo", +} + +func main() { + var ok bool + if _, ok = m[1]; ok { + println("ok") + } +} + +// Output: +// ok diff --git a/_test/map22.go b/_test/map22.go new file mode 100644 index 000000000..3df2780dd --- /dev/null +++ b/_test/map22.go @@ -0,0 +1,14 @@ +package main + +var m = map[int]string{ + 1: "foo", +} + +func main() { + var s string + s, _ = m[1] + println(s) +} + +// Output: +// foo diff --git a/_test/map23.go b/_test/map23.go new file mode 100644 index 000000000..d9528fd25 --- /dev/null +++ b/_test/map23.go @@ -0,0 +1,13 @@ +package main + +var m = map[int]string{ + 1: "foo", +} + +func main() { + _, _ = m[1] + println("ok") +} + +// Output: +// ok diff --git a/interp/run.go b/interp/run.go index cb4e22562..2f396040b 100644 --- a/interp/run.go +++ b/interp/run.go @@ -1096,46 +1096,74 @@ func getIndexMap2(n *node) { value2 := genValue(n.anc.child[1]) // status next := getExec(n.tnext) typ := n.anc.child[0].typ + doValue := n.anc.child[0].ident != "_" + doStatus := n.anc.child[1].ident != "_" + if !doValue && !doStatus { + nop(n) + return + } if n.child[1].rval.IsValid() { // constant map index mi := n.child[1].rval - if typ.cat == interfaceT { + switch { + case !doValue: + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(mi) + value2(f).SetBool(v.IsValid()) + return next + } + case typ.cat == interfaceT: n.exec = func(f *frame) bltn { v := value0(f).MapIndex(mi) if v.IsValid() { dest(f).Set(v.Elem()) } - value2(f).SetBool(v.IsValid()) + if doStatus { + value2(f).SetBool(v.IsValid()) + } return next } - } else { + default: n.exec = func(f *frame) bltn { v := value0(f).MapIndex(mi) if v.IsValid() { dest(f).Set(v) } - value2(f).SetBool(v.IsValid()) + if doStatus { + value2(f).SetBool(v.IsValid()) + } return next } } } else { value1 := genValue(n.child[1]) // map index - if typ.cat == interfaceT { + switch { + case !doValue: + n.exec = func(f *frame) bltn { + v := value0(f).MapIndex(value1(f)) + value2(f).SetBool(v.IsValid()) + return next + } + case typ.cat == interfaceT: n.exec = func(f *frame) bltn { v := value0(f).MapIndex(value1(f)) if v.IsValid() { dest(f).Set(v.Elem()) } - value2(f).SetBool(v.IsValid()) + if doStatus { + value2(f).SetBool(v.IsValid()) + } return next } - } else { + default: n.exec = func(f *frame) bltn { v := value0(f).MapIndex(value1(f)) if v.IsValid() { dest(f).Set(v) } - value2(f).SetBool(v.IsValid()) + if doStatus { + value2(f).SetBool(v.IsValid()) + } return next } } diff --git a/interp/value.go b/interp/value.go index a5df4628a..a3eed74bd 100644 --- a/interp/value.go +++ b/interp/value.go @@ -164,7 +164,7 @@ func genValueInterface(n *node) func(*frame) reflect.Value { return func(f *frame) reflect.Value { v := value(f) nod := n - for { + for v.IsValid() { // traverse interface indirections to find out concrete type vi, ok := v.Interface().(valueInterface) if !ok {