Skip to content

Commit

Permalink
interp: allow conversions of untyped complex
Browse files Browse the repository at this point in the history
For untyped numerical types, conversions to different numerical
types can be allowed if there is no overflow (not checked here).

Fixes traefik#1402.
  • Loading branch information
mvertes committed May 24, 2022
1 parent d64563e commit f43e41a
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 5 deletions.
5 changes: 4 additions & 1 deletion interp/interp_eval_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -176,14 +176,17 @@ 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]"},
{src: `t := map[int]int{}; t[123]--; t`, res: "map[123:-1]"},
{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: `func() complex64 { return complex(0, 0) }()`, res: "(0+0i)"},
{src: `func() float32 { return real(complex(2, 1)) }()`, res: "2"},
{src: `func() int8 { return imag(complex(2, 1)) }()`, res: "1"},
})
}

Expand Down
9 changes: 7 additions & 2 deletions interp/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions interp/typecheck.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
}
}
Expand Down

0 comments on commit f43e41a

Please sign in to comment.