Skip to content

Commit

Permalink
interp: fix handling interface in operators
Browse files Browse the repository at this point in the history
In case of interface values, make sure that the concrete type is preserved during type inference.

Fixes #1466.
  • Loading branch information
mvertes committed Oct 25, 2022
1 parent 7865c90 commit 4a80936
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 5 deletions.
24 changes: 24 additions & 0 deletions _test/issue-1466.go
Original file line number Diff line number Diff line change
@@ -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
6 changes: 2 additions & 4 deletions interp/cfg.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
5 changes: 4 additions & 1 deletion interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 4a80936

Please sign in to comment.