diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ddc72c3a048..4331e2aed9e 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -884,17 +884,22 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { // Left not const, Right not const ------------------ if n.Op == EQL || n.Op == NEQ { // If == or !=, no conversions. - } else if lnt, ok := lt.(*NativeType); ok { + } else if lnt, ok := lt.(*NativeType); ok && isNative(rt) { if debug { if !isShift { assertSameTypes(lt, rt) } } - // If left and right are native type, + // If left and right are native type, and same type // convert left and right to gno, then // convert result back to native. // // get concrete native base type. + if lt.TypeID() != rt.TypeID() { + panic(fmt.Sprintf( + "incompatible types in binary expression: %v %v %v", + lt.TypeID(), n.Op, rt.TypeID())) + } pt := go2GnoBaseType(lnt.Type).(PrimitiveType) // convert n.Left to (gno) pt type, ln := Expr(Call(pt.String(), n.Left)) @@ -932,7 +937,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if lt.TypeID() != rt.TypeID() { panic(fmt.Sprintf( "incompatible types in binary expression: %v %v %v", - n.Left, n.Op, n.Right)) + lt.TypeID(), n.Op, rt.TypeID())) } } else { checkOrConvertType(store, last, &n.Left, rt, false) @@ -945,7 +950,7 @@ func Preprocess(store Store, ctx BlockNode, n Node) Node { if lt.TypeID() != rt.TypeID() { panic(fmt.Sprintf( "incompatible types in binary expression: %v %v %v", - n.Left, n.Op, n.Right)) + lt.TypeID(), n.Op, rt.TypeID())) } } } diff --git a/gnovm/pkg/gnolang/preprocess_test.go b/gnovm/pkg/gnolang/preprocess_test.go new file mode 100644 index 00000000000..2419a385e14 --- /dev/null +++ b/gnovm/pkg/gnolang/preprocess_test.go @@ -0,0 +1,60 @@ +package gnolang + +import ( + "fmt" + "reflect" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestPreprocess_BinaryExpressionOneNative(t *testing.T) { + pn := NewPackageNode("time", "time", nil) + pn.DefineGoNativeValue("Millisecond", time.Millisecond) + pn.DefineGoNativeValue("Second", time.Second) + pn.DefineGoNativeType(reflect.TypeOf(time.Duration(0))) + pv := pn.NewPackage() + store := gonativeTestStore(pn, pv) + store.SetBlockNode(pn) + + const src = `package main + import "time" +func main() { + var a int64 = 2 + println(time.Second * a) + +}` + n := MustParseFile("main.go", src) + + defer func() { + err := recover() + assert.Contains(t, fmt.Sprint(err), "incompatible types in binary expression") + }() + Preprocess(store, pn, n) +} + +func TestPreprocess_BinaryExpressionBothNative(t *testing.T) { + pn := NewPackageNode("time", "time", nil) + pn.DefineGoNativeValue("March", time.March) + pn.DefineGoNativeValue("Wednesday", time.Wednesday) + pn.DefineGoNativeType(reflect.TypeOf(time.Month(0))) + pn.DefineGoNativeType(reflect.TypeOf(time.Weekday(0))) + pv := pn.NewPackage() + store := gonativeTestStore(pn, pv) + store.SetBlockNode(pn) + + const src = `package main + import "time" +func main() { + println(time.March * time.Wednesday) + +}` + n := MustParseFile("main.go", src) + + defer func() { + err := recover() + assert.Contains(t, fmt.Sprint(err), "incompatible types in binary expression") + }() + Preprocess(store, pn, n) +} diff --git a/gnovm/tests/files/op7.gno b/gnovm/tests/files/op7.gno index c92a567110d..7167171035b 100644 --- a/gnovm/tests/files/op7.gno +++ b/gnovm/tests/files/op7.gno @@ -14,4 +14,4 @@ func main() { } // Error: -// main/files/op7.gno:11: incompatible types in binary expression: err GTR invalidT +// main/files/op7.gno:11: incompatible types in binary expression: .uverse.error GTR main.T diff --git a/gnovm/tests/files/time16_native.gno b/gnovm/tests/files/time16_native.gno new file mode 100644 index 00000000000..1789fcbef4f --- /dev/null +++ b/gnovm/tests/files/time16_native.gno @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + var a int64 = 2 + fmt.Println(time.Second * a) +} + +// Error: +// main/files/time16_native.gno:10: incompatible types in binary expression: go:time.Duration MUL int64 diff --git a/gnovm/tests/files/type31.gno b/gnovm/tests/files/type31.gno index a80d07d70f2..a613c67525c 100644 --- a/gnovm/tests/files/type31.gno +++ b/gnovm/tests/files/type31.gno @@ -9,4 +9,4 @@ func main() { } // Error: -// main/files/type31.gno:8: incompatible types in binary expression: x ADD y +// main/files/type31.gno:8: incompatible types in binary expression: string ADD main.String diff --git a/gnovm/tests/files/type32.gno b/gnovm/tests/files/type32.gno index b679543cf9f..bc943d90186 100644 --- a/gnovm/tests/files/type32.gno +++ b/gnovm/tests/files/type32.gno @@ -12,4 +12,4 @@ func main() { } // Error: -// main/files/type32.gno:9#1: incompatible types in binary expression: a + (const (":" string)) ADD b +// main/files/type32.gno:9#1: incompatible types in binary expression: string ADD main.S