interp: fix nil value check in case of interface
A wrong logic was leading to panic in recover. Simplify the workflow for clarity. Fixes #1022.
This commit is contained in:
17
_test/issue-1022.go
Normal file
17
_test/issue-1022.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
if r != nil {
|
||||
fmt.Println(r)
|
||||
}
|
||||
}()
|
||||
|
||||
panic("Ho Ho Ho!")
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Ho Ho Ho!
|
||||
161
interp/run.go
161
interp/run.go
@@ -3381,46 +3381,56 @@ func isNil(n *node) {
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
if c0.typ.cat == interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
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
|
||||
}
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
} else {
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if c0.typ.cat == interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
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 {
|
||||
if n.fnext == nil {
|
||||
if c0.typ.cat != interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(value(f).IsNil())
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
n.exec = func(f *frame) bltn {
|
||||
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
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fnext := getExec(n.fnext)
|
||||
|
||||
if c0.typ.cat != interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
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) {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3435,46 +3445,57 @@ func isNotNil(n *node) {
|
||||
tnext := getExec(n.tnext)
|
||||
dest := genValue(n)
|
||||
|
||||
if n.fnext != nil {
|
||||
fnext := getExec(n.fnext)
|
||||
if c0.typ.cat == interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
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
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
} else {
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if c0.typ.cat == interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
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 {
|
||||
if n.fnext == nil {
|
||||
if c0.typ.cat != interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
dest(f).SetBool(!value(f).IsNil())
|
||||
return tnext
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
n.exec = func(f *frame) bltn {
|
||||
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
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
fnext := getExec(n.fnext)
|
||||
|
||||
if c0.typ.cat != interfaceT {
|
||||
n.exec = func(f *frame) bltn {
|
||||
if value(f).IsNil() {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
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) {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
if v.IsNil() {
|
||||
dest(f).SetBool(false)
|
||||
return fnext
|
||||
}
|
||||
dest(f).SetBool(true)
|
||||
return tnext
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user