From 03ccda1a699de3504f3a8cad40ef9976b016e4e0 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Thu, 25 Aug 2022 12:04:08 +0200 Subject: [PATCH] interp: fix type switch on arbitrary expressions If the value on which to type-switch was already set (i.e. a variable), there was no problem. But if it had to be obtained through a complex expression (func call, array index, etc...), then the code to retrieve the value prior type-switch was not scheduled. This is now fixed. This issue is nasty because the behavior is silently changed, leading potentially to further unrelated issues or runtime panics. Fixes #1444. --- _test/switch39.go | 17 +++++++++++++++++ _test/switch40.go | 17 +++++++++++++++++ interp/cfg.go | 9 ++++++++- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 _test/switch39.go create mode 100644 _test/switch40.go diff --git a/_test/switch39.go b/_test/switch39.go new file mode 100644 index 000000000..881a1d3ac --- /dev/null +++ b/_test/switch39.go @@ -0,0 +1,17 @@ +package main + +func f(params ...interface{}) { + switch p0 := params[0].(type) { + case string: + println("string:", p0) + default: + println("not a string") + } +} + +func main() { + f("Hello") +} + +// Output: +// string: Hello diff --git a/_test/switch40.go b/_test/switch40.go new file mode 100644 index 000000000..348e6ddc6 --- /dev/null +++ b/_test/switch40.go @@ -0,0 +1,17 @@ +package main + +func f(params ...interface{}) { + switch params[0].(type) { + case string: + println("a string") + default: + println("not a string") + } +} + +func main() { + f("Hello") +} + +// Output: +// a string diff --git a/interp/cfg.go b/interp/cfg.go index 34c1df0c9..bd579662e 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -2051,7 +2051,14 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string } sbn.start = clauses[0].start n.start = n.child[0].start - n.child[0].tnext = sbn.start + if n.kind == typeSwitch { + // Handle the typeSwitch init (the type assert expression). + init := n.child[1].lastChild().child[0] + init.tnext = sbn.start + n.child[0].tnext = init.start + } else { + n.child[0].tnext = sbn.start + } case switchIfStmt: // like an if-else chain sc = sc.pop()