diff --git a/_test/assign13.go b/_test/assign13.go new file mode 100644 index 00000000..62bde505 --- /dev/null +++ b/_test/assign13.go @@ -0,0 +1,19 @@ +package main + +import "fmt" + +func getStr() string { + return "test" +} + +func main() { + m := make(map[string]string, 0) + m["a"] = fmt.Sprintf("%v", 0.1) + m["b"] = string(fmt.Sprintf("%v", 0.1)) + m["c"] = getStr() + + fmt.Println(m) +} + +// Output: +// map[a:0.1 b:0.1 c:test] diff --git a/interp/cfg.go b/interp/cfg.go index a3346321..e39be2e9 100644 --- a/interp/cfg.go +++ b/interp/cfg.go @@ -521,7 +521,7 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) { // Propagate type // TODO: Check that existing destination type matches source type switch { - case n.action == aAssign && isCall(src) && dest.typ.cat != interfaceT && !isRecursiveField(dest): + case n.action == aAssign && isCall(src) && dest.typ.cat != interfaceT && !isMapEntry(dest) && !isRecursiveField(dest): // Call action may perform the assignment directly. n.gen = nop src.level = level diff --git a/interp/run.go b/interp/run.go index 99afa401..9f41c47d 100644 --- a/interp/run.go +++ b/interp/run.go @@ -1121,9 +1121,11 @@ func callBin(n *node) { } default: switch n.anc.action { - case aAssign, aAssignX: + case aAssignX: // The function call is part of an assign expression, store results direcly // to assigned location, to avoid an additional frame copy. + // The optimization of aAssign is handled in assign(), and should not + // be handled here. rvalues := make([]func(*frame) reflect.Value, funcType.NumOut()) for i := range rvalues { c := n.anc.child[i] @@ -1166,7 +1168,9 @@ func callBin(n *node) { in[i] = v(f) } out := callFn(value(f), in) - copy(f.data[n.findex:], out) + for i := 0; i < len(out); i++ { + f.data[n.findex+i].Set(out[i]) + } return tnext } }