interp: fix handling interface in operators

In case of interface values, make sure that the concrete type is preserved during type inference.

Fixes #1466.
This commit is contained in:
Marc Vertes
2022-10-25 14:02:05 +02:00
committed by GitHub
parent 7865c90737
commit 4a8093609f
3 changed files with 30 additions and 5 deletions

24
_test/issue-1466.go Normal file
View File

@@ -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

View File

@@ -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)

View File

@@ -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