From a38d19288fcaba4557cb80284abf14fe96520b58 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Fri, 30 Oct 2020 16:20:04 +0100 Subject: [PATCH] interp: fix testing for nil interface values Fixes #924. --- _test/nil3.go | 28 ++++++++++++++++++++++++++++ interp/run.go | 26 ++++++++++++++++++-------- 2 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 _test/nil3.go diff --git a/_test/nil3.go b/_test/nil3.go new file mode 100644 index 000000000..fc884e72c --- /dev/null +++ b/_test/nil3.go @@ -0,0 +1,28 @@ +package main + +type I interface { + Hello() +} + +type T struct { + h I +} + +func (t *T) Hello() { println("Hello") } + +func main() { + t := &T{} + println(t.h != nil) + println(t.h == nil) + t.h = t + println(t.h != nil) + println(t.h == nil) + t.h.Hello() +} + +// Output: +// false +// true +// true +// false +// Hello diff --git a/interp/run.go b/interp/run.go index 03c736387..9dadbee16 100644 --- a/interp/run.go +++ b/interp/run.go @@ -3091,9 +3091,9 @@ func isNil(n *node) { fnext := getExec(n.fnext) if c0.typ.cat == interfaceT { n.exec = func(f *frame) bltn { - vi := value(f).Interface().(valueInterface) - if (vi == valueInterface{} || - vi.node.kind == basicLit && vi.node.typ.cat == nilT) { + v := value(f) + vi, ok := v.Interface().(valueInterface) + if ok && (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) || v.IsNil() { dest(f).SetBool(true) return tnext } @@ -3113,7 +3113,12 @@ func isNil(n *node) { } else { if c0.typ.cat == interfaceT { n.exec = func(f *frame) bltn { - dest(f).SetBool(value(f).Interface().(valueInterface) == valueInterface{}) + v := value(f) + if vi, ok := v.Interface().(valueInterface); ok { + dest(f).SetBool(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) + } else { + dest(f).SetBool(v.IsNil()) + } return tnext } } else { @@ -3140,9 +3145,9 @@ func isNotNil(n *node) { fnext := getExec(n.fnext) if c0.typ.cat == interfaceT { n.exec = func(f *frame) bltn { - vi := value(f).Interface().(valueInterface) - if (vi == valueInterface{} || - vi.node.kind == basicLit && vi.node.typ.cat == nilT) { + v := value(f) + vi, ok := v.Interface().(valueInterface) + if ok && (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) || v.IsNil() { dest(f).SetBool(false) return fnext } @@ -3162,7 +3167,12 @@ func isNotNil(n *node) { } else { if c0.typ.cat == interfaceT { n.exec = func(f *frame) bltn { - dest(f).SetBool(!(value(f).Interface().(valueInterface) == valueInterface{})) + v := value(f) + if vi, ok := v.Interface().(valueInterface); ok { + dest(f).SetBool(!(vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)) + } else { + dest(f).SetBool(!v.IsNil()) + } return tnext } } else {