diff --git a/pkg/compiler/codegen.go b/pkg/compiler/codegen.go index 7f565ab3d..7e838946c 100644 --- a/pkg/compiler/codegen.go +++ b/pkg/compiler/codegen.go @@ -712,6 +712,7 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { name string numArgs = len(n.Args) isBuiltin bool + isFunc bool ) switch fun := n.Fun.(type) { @@ -721,6 +722,10 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { if !ok && !isBuiltin { name = fun.Name } + // distinguish lambda invocations from type conversions + if fun.Obj != nil && fun.Obj.Kind == ast.Var { + isFunc = true + } case *ast.SelectorExpr: // If this is a method call we need to walk the AST to load the struct locally. // Otherwise this is a function call from a imported package and we can call it @@ -767,9 +772,11 @@ func (c *codegen) Visit(node ast.Node) ast.Visitor { // We can be sure builtins are of type *ast.Ident. c.convertBuiltin(n) case name != "": - // Function was not found thus is can be only an invocation of func-typed variable. - c.emitLoadVar(name) - emit.Opcode(c.prog.BinWriter, opcode.CALLA) + // Function was not found thus is can be only an invocation of func-typed variable or type conversion. + if isFunc { + c.emitLoadVar(name) + emit.Opcode(c.prog.BinWriter, opcode.CALLA) + } case isSyscall(f): c.convertSyscall(n, f.selector.Name, f.name) default: diff --git a/pkg/compiler/convert_test.go b/pkg/compiler/convert_test.go index e768d7573..613e1af3a 100644 --- a/pkg/compiler/convert_test.go +++ b/pkg/compiler/convert_test.go @@ -72,3 +72,17 @@ func TestTypeAssertion(t *testing.T) { }` eval(t, src, big.NewInt(1)) } + +func TestTypeConversion(t *testing.T) { + src := `package foo + type myInt int + func Main() int32 { + var a int32 = 41 + b := myInt(a) + incMy := func(x myInt) myInt { return x + 1 } + c := incMy(b) + return int32(c) + }` + + eval(t, src, big.NewInt(42)) +}