Skip to content

Commit

Permalink
Equality is incorrect when nil is used as the left argument of ==
Browse files Browse the repository at this point in the history
hi!

this issue is sorta blocking for me so i thought i would try to fix it. 

im still learning the codebase and understanding how yaegi works, but I thought I would attempt to add a test in the style of other tests as a start.

please let me know if there is anything i need to change / run, or if anyone knows perhaps a good place to start for tackling this issue

Fixes #1496
  • Loading branch information
elee1766 authored Mar 23, 2023
1 parent c4a297c commit ce2bb79
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 54 deletions.
16 changes: 16 additions & 0 deletions _test/issue-1496.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package main

func main() {
a := []byte{} == nil
b := nil == []byte{}
c := nil == &struct{}{}
i := 100
d := nil == &i
var v interface{}
f := nil == v
g := v == nil
println(a, b, c, d, f, g)
}

// Output:
// false false false false true true
6 changes: 5 additions & 1 deletion interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,11 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string
n.typ = sc.getType("bool")
if c0.sym == nilSym || c1.sym == nilSym {
if n.action == aEqual {
n.gen = isNil
if c1.sym == nilSym {
n.gen = isNilChild(0)
} else {
n.gen = isNilChild(1)
}
} else {
n.gen = isNotNil
}
Expand Down
107 changes: 54 additions & 53 deletions interp/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -3863,31 +3863,44 @@ func slice0(n *node) {
}
}

func isNil(n *node) {
var value func(*frame) reflect.Value
c0 := n.child[0]
value = genValue(c0)
typ := n.typ.concrete().TypeOf()
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
tnext := getExec(n.tnext)
dest := genValue(n)

if n.fnext == nil {
if !isInterfaceSrc(c0.typ) {
if isInterface {
func isNilChild(child int) func(n *node) {
return func(n *node) {
var value func(*frame) reflect.Value
child := n.child[child]
value = genValue(child)
typ := n.typ.concrete().TypeOf()
isInterface := n.typ.TypeOf().Kind() == reflect.Interface
tnext := getExec(n.tnext)
dest := genValue(n)
if n.fnext == nil {
if !isInterfaceSrc(child.typ) {
if isInterface {
n.exec = func(f *frame) bltn {
dest(f).Set(reflect.ValueOf(value(f).IsNil()).Convert(typ))
return tnext
}
return
}
n.exec = func(f *frame) bltn {
dest(f).Set(reflect.ValueOf(value(f).IsNil()).Convert(typ))
dest(f).SetBool(value(f).IsNil())
return tnext
}
return
}
n.exec = func(f *frame) bltn {
dest(f).SetBool(value(f).IsNil())
return tnext
if isInterface {
n.exec = func(f *frame) bltn {
v := value(f)
var r bool
if vi, ok := v.Interface().(valueInterface); ok {
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
} else {
r = v.IsNil()
}
dest(f).Set(reflect.ValueOf(r).Convert(typ))
return tnext
}
return
}
return
}
if isInterface {
n.exec = func(f *frame) bltn {
v := value(f)
var r bool
Expand All @@ -3896,55 +3909,43 @@ func isNil(n *node) {
} else {
r = v.IsNil()
}
dest(f).Set(reflect.ValueOf(r).Convert(typ))
dest(f).SetBool(r)
return tnext
}
return
}
n.exec = func(f *frame) bltn {
v := value(f)
var r bool
if vi, ok := v.Interface().(valueInterface); ok {
r = (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT)
} else {
r = v.IsNil()
}
dest(f).SetBool(r)
return tnext
}
return
}

fnext := getExec(n.fnext)
fnext := getExec(n.fnext)

if !isInterfaceSrc(c0.typ) {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(true)
return tnext
if !isInterfaceSrc(child.typ) {
n.exec = func(f *frame) bltn {
if value(f).IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
dest(f).SetBool(false)
return fnext
return
}
return
}

n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
if (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) {
n.exec = func(f *frame) bltn {
v := value(f)
if vi, ok := v.Interface().(valueInterface); ok {
if (vi == valueInterface{} || vi.node.kind == basicLit && vi.node.typ.cat == nilT) {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
if v.IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
if v.IsNil() {
dest(f).SetBool(true)
return tnext
}
dest(f).SetBool(false)
return fnext
}
}

Expand Down

0 comments on commit ce2bb79

Please sign in to comment.