diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index 26e67e71fad..7a23bb35cdd 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -1402,6 +1402,19 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { if !constConverted { convertConst(store, last, n, arg0, nil) } + + // check legal type for nil + if arg0.IsUndefined() { + switch ct.Kind() { // special case for nil conversion check. + case SliceKind, PointerKind, FuncKind, MapKind, InterfaceKind, ChanKind: + convertConst(store, last, n, arg0, ct) + default: + panic(fmt.Sprintf( + "cannot convert %v to %v", + arg0, ct.Kind())) + } + } + // evaluate the new expression. cx := evalConst(store, last, n) // Though cx may be undefined if ct is interface, diff --git a/gnovm/pkg/gnolang/values_conversions.go b/gnovm/pkg/gnolang/values_conversions.go index f6e39bd1912..920ed655ec9 100644 --- a/gnovm/pkg/gnolang/values_conversions.go +++ b/gnovm/pkg/gnolang/values_conversions.go @@ -75,6 +75,11 @@ func ConvertTo(alloc *Allocator, store Store, tv *TypedValue, t Type, isConst bo GNO_CASE: // special case for interface target if t.Kind() == InterfaceKind { + if tv.IsUndefined() && tv.T == nil { + if _, ok := t.(*NativeType); !ok { // no support for native now + tv.T = t + } + } return } // special case for undefined/nil source diff --git a/gnovm/tests/files/convert4.gno b/gnovm/tests/files/convert4.gno index e03e1d07ce3..03c7d454b82 100644 --- a/gnovm/tests/files/convert4.gno +++ b/gnovm/tests/files/convert4.gno @@ -5,4 +5,4 @@ func main() { } // Error: -// main/files/convert4.gno:4:10: cannot convert (undefined) to int +// main/files/convert4.gno:4:10: cannot convert (const (undefined)) to IntKind diff --git a/gnovm/tests/files/convert5.gno b/gnovm/tests/files/convert5.gno index e2e16c5eb83..1e785abdd7b 100644 --- a/gnovm/tests/files/convert5.gno +++ b/gnovm/tests/files/convert5.gno @@ -7,4 +7,4 @@ func main() { } // Error: -// main/files/convert5.gno:3:1: cannot convert (undefined) to int +// main/files/convert5.gno:3:1: cannot convert (const (undefined)) to IntKind diff --git a/gnovm/tests/files/types/cmp_iface_0_stdlibs.gno b/gnovm/tests/files/types/cmp_iface_0_stdlibs.gno new file mode 100644 index 00000000000..fb4ac682243 --- /dev/null +++ b/gnovm/tests/files/types/cmp_iface_0_stdlibs.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if Error(0) == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/cmp_iface_3_stdlibs.gno b/gnovm/tests/files/types/cmp_iface_3_stdlibs.gno new file mode 100644 index 00000000000..9c4cb0e5ea0 --- /dev/null +++ b/gnovm/tests/files/types/cmp_iface_3_stdlibs.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if Error(1) == errCmp { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Output: +// something else diff --git a/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno new file mode 100644 index 00000000000..e706c74808e --- /dev/null +++ b/gnovm/tests/files/types/cmp_iface_5_stdlibs.gno @@ -0,0 +1,27 @@ +package main + +import ( + "errors" + "strconv" +) + +type Error int64 + +func (e Error) Error() string { + return "error: " + strconv.Itoa(int(e)) +} + +var errCmp = errors.New("XXXX") + +// special case: +// one is interface +func main() { + if errCmp == int64(1) { + println("what the firetruck?") + } else { + println("something else") + } +} + +// Error: +// main/files/types/cmp_iface_5_stdlibs.gno:19:5: int64 does not implement .uverse.error (missing method Error) diff --git a/gnovm/tests/files/types/typed_nil_a.gno b/gnovm/tests/files/types/typed_nil_a.gno new file mode 100644 index 00000000000..f212c677bab --- /dev/null +++ b/gnovm/tests/files/types/typed_nil_a.gno @@ -0,0 +1,18 @@ +package main + +import "fmt" + +type integer int + +func main() { + // illegal conversion + // should not work + if integer(nil) == nil { + fmt.Println("integer is nil") + } else { + fmt.Println("integer is not nil") + } +} + +// Error: +// main/files/types/typed_nil_a.gno:10:5: cannot convert (const (undefined)) to IntKind diff --git a/gnovm/tests/files/types/typed_nil_b.gno b/gnovm/tests/files/types/typed_nil_b.gno new file mode 100644 index 00000000000..fb1492dd02b --- /dev/null +++ b/gnovm/tests/files/types/typed_nil_b.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +type integer *int + +func main() { + println(integer(nil)) + fmt.Println(integer(nil)) + fmt.Printf("%T\n", integer(nil)) +} + +// Output: +// (nil main.integer) +// +// *int diff --git a/gnovm/tests/files/types/typed_nil_c.gno b/gnovm/tests/files/types/typed_nil_c.gno new file mode 100644 index 00000000000..c8a556ea0c1 --- /dev/null +++ b/gnovm/tests/files/types/typed_nil_c.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + println(interface{}(nil) == (*int)(nil)) + fmt.Printf("%T\n", interface{}(nil)) +} + +// Output: +// false +//