From 4a8093609f8efe4f1c4eb13a3871b0ef7f609214 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Tue, 25 Oct 2022 14:02:05 +0200 Subject: [PATCH] interp: fix handling interface in operators In case of interface values, make sure that the concrete type is preserved during type inference. Fixes #1466. --- _test/issue-1466.go | 24 ++++++++++++++++++++++++ interp/cfg.go | 6 ++---- interp/type.go | 5 ++++- 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 _test/issue-1466.go diff --git a/_test/issue-1466.go b/_test/issue-1466.go new file mode 100644 index 00000000..7f1d74c6 --- /dev/null +++ b/_test/issue-1466.go @@ -0,0 +1,24 @@ +package main + +import ( + "fmt" +) + +func SomeFunc(defaultValue interface{}) interface{} { + switch v := defaultValue.(type) { + case string: + return v + " abc" + case int: + return v - 234 + } + panic("whoops") +} + +func main() { + fmt.Println(SomeFunc(1234)) + fmt.Println(SomeFunc("test")) +} + +// Output: +// 1000 +// test abc diff --git a/interp/cfg.go b/interp/cfg.go index 778bbb88..27809cdb 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -679,7 +679,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string n.gen = nop src.findex = dest.findex src.level = level - case len(n.child) < 4 && isArithmeticAction(src): + case len(n.child) < 4 && isArithmeticAction(src) && !isInterface(dest.typ): // Optimize single assignments from some arithmetic operations. src.typ = dest.typ src.findex = dest.findex @@ -828,9 +828,7 @@ func (interp *Interpreter) cfg(root *node, sc *scope, importPath, pkgName string case n.anc.kind == returnStmt: // To avoid a copy in frame, if the result is to be returned, store it directly // at the frame location reserved for output arguments. - pos := childPos(n) - n.typ = sc.def.typ.ret[pos] - n.findex = pos + n.findex = childPos(n) default: // Allocate a new location in frame, and store the result here. n.findex = sc.add(n.typ) diff --git a/interp/type.go b/interp/type.go index e9b3d451..ddfda1cf 100644 --- a/interp/type.go +++ b/interp/type.go @@ -598,7 +598,10 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype, } if isInterfaceSrc(dt) { - dt.val = t + // Set a new interface type preserving the concrete type (.val field). + t2 := *dt + t2.val = t + dt = &t2 } t = dt