From 6c74ab7becad4a2a4bf7913da4c9cbd1f198c010 Mon Sep 17 00:00:00 2001 From: Marc Vertes Date: Mon, 13 Jun 2022 08:42:08 +0000 Subject: [PATCH] interp: allow conversions of untyped complex For untyped numerical types, conversions to different numerical types can be allowed if there is no overflow (not checked here). Fixes #1402. --- interp/interp_eval_test.go | 5 ++++- interp/type.go | 9 +++++++-- interp/typecheck.go | 4 ++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/interp/interp_eval_test.go b/interp/interp_eval_test.go index d7d98a500..903e7ded5 100644 --- a/interp/interp_eval_test.go +++ b/interp/interp_eval_test.go @@ -176,7 +176,7 @@ func TestEvalBuiltin(t *testing.T) { {src: `m := complex(3, 2); real(m)`, res: "3"}, {src: `m := complex(3, 2); imag(m)`, res: "2"}, {src: `m := complex("test", 2)`, err: "1:33: invalid types string and int"}, - {src: `imag("test")`, err: "1:33: cannot convert \"test\" to complex128"}, + {src: `imag("test")`, err: "1:33: cannot convert untyped string to untyped complex"}, {src: `imag(a)`, err: "1:33: invalid argument type []int for imag"}, {src: `real(a)`, err: "1:33: invalid argument type []int for real"}, {src: `t := map[int]int{}; t[123]++; t`, res: "map[123:1]"}, @@ -184,6 +184,9 @@ func TestEvalBuiltin(t *testing.T) { {src: `t := map[int]int{}; t[123] += 1; t`, res: "map[123:1]"}, {src: `t := map[int]int{}; t[123] -= 1; t`, res: "map[123:-1]"}, {src: `println("hello", _)`, err: "1:28: cannot use _ as value"}, + {src: `f := func() complex64 { return complex(0, 0) }()`, res: "(0+0i)"}, + {src: `f := func() float32 { return real(complex(2, 1)) }()`, res: "2"}, + {src: `f := func() int8 { return imag(complex(2, 1)) }()`, res: "1"}, }) } diff --git a/interp/type.go b/interp/type.go index c6955d41a..ecc390597 100644 --- a/interp/type.go +++ b/interp/type.go @@ -585,12 +585,12 @@ func nodeType2(interp *Interpreter, sc *scope, n *node, seen []*node) (t *itype, } if !t.incomplete { switch k := t.TypeOf().Kind(); { + case t.untyped && isNumber(t.TypeOf()): + t = untypedFloat() case k == reflect.Complex64: t = sc.getType("float32") case k == reflect.Complex128: t = sc.getType("float64") - case t.untyped && isNumber(t.TypeOf()): - t = valueTOf(floatType, withUntyped(true), withScope(sc)) default: err = n.cfgErrorf("invalid complex type %s", k) } @@ -1219,6 +1219,11 @@ func (t *itype) assignableTo(o *itype) bool { return true } + if t.untyped && isNumber(t.TypeOf()) && isNumber(o.TypeOf()) { + // Assignability depends on constant numeric value (overflow check), to be tested elsewhere. + return true + } + n := t.node if n == nil || !n.rval.IsValid() { return false diff --git a/interp/typecheck.go b/interp/typecheck.go index 0c3e9a4ab..7d30742a8 100644 --- a/interp/typecheck.go +++ b/interp/typecheck.go @@ -815,7 +815,7 @@ func (check typecheck) builtin(name string, n *node, child []*node, ellipsis boo case !typ0.untyped && typ1.untyped: err = check.convertUntyped(p1.nod, typ0) case typ0.untyped && typ1.untyped: - fltType := check.scope.getType("float64") + fltType := untypedFloat() err = check.convertUntyped(p0.nod, fltType) if err != nil { break @@ -838,7 +838,7 @@ func (check typecheck) builtin(name string, n *node, child []*node, ellipsis boo p := params[0] typ := p.Type() if typ.untyped { - if err := check.convertUntyped(p.nod, check.scope.getType("complex128")); err != nil { + if err := check.convertUntyped(p.nod, untypedComplex()); err != nil { return err } }