Skip to content

Commit

Permalink
fix(gnovm): fix type equality with native values in binary expressions (
Browse files Browse the repository at this point in the history
gnolang#2016)

fixes gnolang#1966 
<!-- please provide a detailed description of the changes made in this
pull request. -->

<details><summary>Contributors' checklist...</summary>

- [ ] Added new tests, or not needed, or not feasible
- [ ] Provided an example (e.g. screenshot) to aid review or the PR is
self-explanatory
- [ ] Updated the official documentation or not needed
- [ ] No breaking changes were made, or a `BREAKING CHANGE: xxx` message
was included in the description
- [ ] Added references to related issues and PRs
- [ ] Provided any useful hints for running manual tests
- [ ] Added new benchmarks to [generated
graphs](https://gnoland.github.io/benchmarks), if any. More info
[here](https://github.com/gnolang/gno/blob/master/.benchmarks/README.md).
</details>
  • Loading branch information
omarsy authored May 23, 2024
1 parent 16ed32f commit f3ddc44
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 7 deletions.
13 changes: 9 additions & 4 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand Down Expand Up @@ -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)
Expand All @@ -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()))
}
}
}
Expand Down
60 changes: 60 additions & 0 deletions gnovm/pkg/gnolang/preprocess_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
2 changes: 1 addition & 1 deletion gnovm/tests/files/op7.gno
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ func main() {
}

// Error:
// main/files/op7.gno:11: incompatible types in binary expression: err<VPBlock(2,0)> GTR invalidT<VPBlock(4,2)>
// main/files/op7.gno:11: incompatible types in binary expression: .uverse.error GTR main.T
14 changes: 14 additions & 0 deletions gnovm/tests/files/time16_native.gno
Original file line number Diff line number Diff line change
@@ -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
2 changes: 1 addition & 1 deletion gnovm/tests/files/type31.gno
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@ func main() {
}

// Error:
// main/files/type31.gno:8: incompatible types in binary expression: x<VPBlock(1,0)> ADD y<VPBlock(1,1)>
// main/files/type31.gno:8: incompatible types in binary expression: string ADD main.String
2 changes: 1 addition & 1 deletion gnovm/tests/files/type32.gno
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ func main() {
}

// Error:
// main/files/type32.gno:9#1: incompatible types in binary expression: a<VPBlock(2,0)> + (const (":" string)) ADD b<VPBlock(2,1)>
// main/files/type32.gno:9#1: incompatible types in binary expression: string ADD main.S

0 comments on commit f3ddc44

Please sign in to comment.