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.
This commit is contained in:
Marc Vertes
2022-06-13 08:42:08 +00:00
committed by GitHub
parent d64563edee
commit 6c74ab7bec
3 changed files with 13 additions and 5 deletions

View File

@@ -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"},
})
}

View File

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

View File

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