From 428b65816019580368938939489e4e1800167d59 Mon Sep 17 00:00:00 2001 From: Ethan Reesor Date: Fri, 2 Apr 2021 02:08:04 -0500 Subject: [PATCH] Allow colon-equal to override variable type If I execute the following: ``` I := interp.New(interp.Options{}) I.Eval(`x := 1`) I.Eval(`x := "foobar"`) ``` I expect the second declaration to override the first. `var x string` will override the previous type, and redeclaring a type, function, const, etc will override it, but the `:=` operator will not. Currently, the result is: `reflect.Set: value of type string is not assignable to type int` --- interp/gta.go | 4 +--- interp/interp_eval_test.go | 5 +++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/interp/gta.go b/interp/gta.go index 0880842b5..a1db163f0 100644 --- a/interp/gta.go +++ b/interp/gta.go @@ -80,9 +80,7 @@ func (interp *Interpreter) gta(root *node, rpath, importPath string) ([]*node, e if typ.isBinMethod { typ = &itype{cat: valueT, rtype: typ.methodCallType(), isBinMethod: true, scope: sc} } - if sc.sym[dest.ident] == nil || sc.sym[dest.ident].typ.incomplete { - sc.sym[dest.ident] = &symbol{kind: varSym, global: true, index: sc.add(typ), typ: typ, rval: val, node: n} - } + sc.sym[dest.ident] = &symbol{kind: varSym, global: true, index: sc.add(typ), typ: typ, rval: val, node: n} if n.anc.kind == constDecl { sc.sym[dest.ident].kind = constSym if childPos(n) == len(n.anc.child)-1 { diff --git a/interp/interp_eval_test.go b/interp/interp_eval_test.go index 593762d14..f24f21f76 100644 --- a/interp/interp_eval_test.go +++ b/interp/interp_eval_test.go @@ -123,6 +123,7 @@ func TestEvalAssign(t *testing.T) { {src: "h := 1; h >>= 8", res: "0"}, {src: "i := 1; j := &i; (*j) = 2", res: "2"}, {src: "i64 := testpkg.val; i64 == 11", res: "true"}, + {pre: func() { eval(t, i, "k := 1") }, src: `k := "Hello world"`, res: "Hello world"}, // allow reassignment in subsequent evaluations }) } @@ -139,8 +140,8 @@ func TestEvalBuiltin(t *testing.T) { {src: `g := cap(a)`, res: "1"}, {src: `g := len("test")`, res: "4"}, {src: `g := len(map[string]string{"a": "b"})`, res: "1"}, - {src: `a := len()`, err: "not enough arguments in call to len"}, - {src: `a := len([]int, 0)`, err: "too many arguments for len"}, + {src: `n := len()`, err: "not enough arguments in call to len"}, + {src: `n := len([]int, 0)`, err: "too many arguments for len"}, {src: `g := cap("test")`, err: "1:37: invalid argument for cap"}, {src: `g := cap(map[string]string{"a": "b"})`, err: "1:37: invalid argument for cap"}, {src: `h := make(chan int, 1); close(h); len(h)`, res: "0"},