From 3adb2ac390f60467e6d77c3aa7ff4507cb37e0e8 Mon Sep 17 00:00:00 2001 From: 6h057 <15034695+omarsy@users.noreply.github.com> Date: Tue, 14 Jan 2025 21:29:49 +0100 Subject: [PATCH] feat(gnovm): align Gno constant handling with Go specifications (#2828) Related Issues: Closes #2628 This PR aims to align Gno's constant handling with the Go specification regarding constant expressions (see [Go Specification on Constants](https://go.dev/ref/spec#Constant_expressions)). 1. **Primitive Type Requirement** - **Should Work:** ```go const t = 1 ``` - **Should Return an Error:** ```go const t = []string{"1"} ``` **Error:** ``` (const (slice[("1" string)] []string)) (value of type []string) is not constant ``` 2. **Function Calls Disallowed** Only built-in functions should be allowed. - **Should Work:** ```go const t = len("s") ``` - **Should Return an Error:** ```go func v() string { return "" } const t = v() ``` **Error:** ``` v() (value of type string) is not constant ``` 3. **Constant Operands Requirement** Constant expressions may contain only constant operands and are evaluated at compile time. - **Should Work:** ```go const t = 1 const v = t ``` - **Should Raise an Error:** ```go t := 1 const v = t ``` **Error:** ``` t (variable of type int) is not constant ``` 4. **Type Assertion Forbidden** - This code: ```go var i interface{} = 1 const t, ok = i.(int) ``` - **Should Raise This Error:** ``` i.(int) (comma, ok expression of type int) is not constant ``` 5. **Index Expression Forbidden** - This code: ```go var i = []string{} const t, ok = i[0] ``` - **Should Return This Error:** ``` i[0] (variable of type string) is not constant ```
Contributors' checklist... - [ ] 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).
--- .../r/demo/keystore/keystore_test.gno | 4 - gnovm/pkg/gnolang/preprocess.go | 1 + gnovm/pkg/gnolang/type_check.go | 145 ++++++++++++++++++ gnovm/tests/files/const23.gno | 11 ++ gnovm/tests/files/const24.gno | 82 ++++++++++ gnovm/tests/files/const25.gno | 11 ++ gnovm/tests/files/const26.gno | 15 ++ gnovm/tests/files/const27.gno | 16 ++ gnovm/tests/files/const28.gno | 12 ++ gnovm/tests/files/const29.gno | 12 ++ gnovm/tests/files/const30.gno | 15 ++ gnovm/tests/files/const31.gno | 15 ++ gnovm/tests/files/const32.gno | 11 ++ gnovm/tests/files/const33.gno | 12 ++ gnovm/tests/files/const34.gno | 10 ++ gnovm/tests/files/const35.gno | 12 ++ gnovm/tests/files/const36.gno | 13 ++ gnovm/tests/files/const37_native.gno | 10 ++ gnovm/tests/files/const37_stdlibs.gno | 10 ++ gnovm/tests/files/const38.gno | 11 ++ gnovm/tests/files/const39.gno | 14 ++ gnovm/tests/files/const40.gno | 8 + gnovm/tests/files/const41.gno | 8 + gnovm/tests/files/const42.gno | 8 + gnovm/tests/files/const43.gno | 10 ++ gnovm/tests/files/const44.gno | 10 ++ gnovm/tests/files/const45_a.gno | 14 ++ gnovm/tests/files/const45_b.gno | 14 ++ gnovm/tests/files/const46.gno | 10 ++ gnovm/tests/files/const47.gno | 10 ++ gnovm/tests/files/const48.gno | 9 ++ gnovm/tests/files/const49.gno | 16 ++ gnovm/tests/files/const50.gno | 12 ++ 33 files changed, 567 insertions(+), 4 deletions(-) create mode 100644 gnovm/tests/files/const23.gno create mode 100644 gnovm/tests/files/const24.gno create mode 100644 gnovm/tests/files/const25.gno create mode 100644 gnovm/tests/files/const26.gno create mode 100644 gnovm/tests/files/const27.gno create mode 100644 gnovm/tests/files/const28.gno create mode 100644 gnovm/tests/files/const29.gno create mode 100644 gnovm/tests/files/const30.gno create mode 100644 gnovm/tests/files/const31.gno create mode 100644 gnovm/tests/files/const32.gno create mode 100644 gnovm/tests/files/const33.gno create mode 100644 gnovm/tests/files/const34.gno create mode 100644 gnovm/tests/files/const35.gno create mode 100644 gnovm/tests/files/const36.gno create mode 100644 gnovm/tests/files/const37_native.gno create mode 100644 gnovm/tests/files/const37_stdlibs.gno create mode 100644 gnovm/tests/files/const38.gno create mode 100644 gnovm/tests/files/const39.gno create mode 100644 gnovm/tests/files/const40.gno create mode 100644 gnovm/tests/files/const41.gno create mode 100644 gnovm/tests/files/const42.gno create mode 100644 gnovm/tests/files/const43.gno create mode 100644 gnovm/tests/files/const44.gno create mode 100644 gnovm/tests/files/const45_a.gno create mode 100644 gnovm/tests/files/const45_b.gno create mode 100644 gnovm/tests/files/const46.gno create mode 100644 gnovm/tests/files/const47.gno create mode 100644 gnovm/tests/files/const48.gno create mode 100644 gnovm/tests/files/const49.gno create mode 100644 gnovm/tests/files/const50.gno diff --git a/examples/gno.land/r/demo/keystore/keystore_test.gno b/examples/gno.land/r/demo/keystore/keystore_test.gno index 41597016ea3..9b5fafa2f95 100644 --- a/examples/gno.land/r/demo/keystore/keystore_test.gno +++ b/examples/gno.land/r/demo/keystore/keystore_test.gno @@ -11,10 +11,6 @@ import ( ) func TestRender(t *testing.T) { - // https://github.com/gnolang/gno/pull/3375 changed const -> var : - // For some reason non native functions fails on constants with - // constant overflows (code=2), this does not happens when using a variable - // TODO: check this issue after and if this PR is merged var ( author1 std.Address = testutils.TestAddress("author1") author2 std.Address = testutils.TestAddress("author2") diff --git a/gnovm/pkg/gnolang/preprocess.go b/gnovm/pkg/gnolang/preprocess.go index ddfd1851989..ffa0f518331 100644 --- a/gnovm/pkg/gnolang/preprocess.go +++ b/gnovm/pkg/gnolang/preprocess.go @@ -2294,6 +2294,7 @@ func preprocess1(store Store, ctx BlockNode, n Node) Node { // NOTE: may or may not be a *ConstExpr, // but if not, make one now. for i, vx := range n.Values { + assertValidConstExpr(store, last, n, vx) n.Values[i] = evalConst(store, last, vx) } } else { diff --git a/gnovm/pkg/gnolang/type_check.go b/gnovm/pkg/gnolang/type_check.go index 70166116fcc..f96cb71e4b6 100644 --- a/gnovm/pkg/gnolang/type_check.go +++ b/gnovm/pkg/gnolang/type_check.go @@ -215,6 +215,151 @@ func assertAssignableTo(n Node, xt, dt Type, autoNative bool) { } } +func assertValidConstExpr(store Store, last BlockNode, n *ValueDecl, expr Expr) { + if n.Type != nil { + nt := evalStaticType(store, last, n.Type) + if xnt, ok := nt.(*NativeType); ok { + nt = go2GnoBaseType(xnt.Type) + } + + if _, ok := baseOf(nt).(PrimitiveType); !ok { + panic(fmt.Sprintf("invalid constant type %s", nt.String())) + } + } + + nt := evalStaticTypeOf(store, last, expr) + if xnt, ok := nt.(*NativeType); ok { + nt = go2GnoBaseType(xnt.Type) + } + + if nt == nil { + panic(fmt.Sprintf("%s (variable of type nil) is not constant", expr)) + } + + if _, ok := baseOf(nt).(PrimitiveType); !ok { + panic(fmt.Sprintf("%s (variable of type %s) is not constant", expr, nt)) + } + + assertValidConstValue(store, last, expr) +} + +func assertValidConstValue(store Store, last BlockNode, currExpr Expr) { +Main: + switch currExpr := currExpr.(type) { + case *ConstExpr: + case *UnaryExpr: + // *, & is filter out previously since they are not primitive + assertValidConstValue(store, last, currExpr.X) + case *TypeAssertExpr: + ty := evalStaticTypeOf(store, last, currExpr) + if _, ok := ty.(*TypeType); ok { + ty = evalStaticType(store, last, currExpr) + } + panic(fmt.Sprintf("%s (comma, ok expression of type %s) is not constant", currExpr.String(), currExpr.Type)) + case *CallExpr: + ift := evalStaticTypeOf(store, last, currExpr.Func) + switch baseOf(ift).(type) { + case *FuncType: + tup := evalStaticTypeOfRaw(store, last, currExpr).(*tupleType) + + // check for built-in functions + if cx, ok := currExpr.Func.(*ConstExpr); ok { + if fv, ok := cx.V.(*FuncValue); ok { + if fv.PkgPath == uversePkgPath { + // TODO: should support min, max, real, imag + switch { + case fv.Name == "len": + at := evalStaticTypeOf(store, last, currExpr.Args[0]) + if _, ok := baseOf(at).(*ArrayType); ok { + // ok + break Main + } + assertValidConstValue(store, last, currExpr.Args[0]) + break Main + case fv.Name == "cap": + at := evalStaticTypeOf(store, last, currExpr.Args[0]) + if _, ok := baseOf(at).(*ArrayType); ok { + // ok + break Main + } + assertValidConstValue(store, last, currExpr.Args[0]) + break Main + } + } + } + } + + switch { + case len(tup.Elts) == 0: + panic(fmt.Sprintf("%s (no value) used as value", currExpr.String())) + case len(tup.Elts) == 1: + panic(fmt.Sprintf("%s (value of type %s) is not constant", currExpr.String(), tup.Elts[0])) + default: + panic(fmt.Sprintf("multiple-value %s (value of type %s) in single-value context", currExpr.String(), tup.Elts)) + } + case *TypeType: + for _, arg := range currExpr.Args { + assertValidConstValue(store, last, arg) + } + case *NativeType: + // Todo: should add a test after the fix of https://github.com/gnolang/gno/issues/3006 + ty := evalStaticType(store, last, currExpr.Func) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", currExpr.String(), ty)) + default: + panic(fmt.Sprintf( + "unexpected func type %v (%v)", + ift, reflect.TypeOf(ift))) + } + case *BinaryExpr: + assertValidConstValue(store, last, currExpr.Left) + assertValidConstValue(store, last, currExpr.Right) + case *SelectorExpr: + xt := evalStaticTypeOf(store, last, currExpr.X) + switch xt := xt.(type) { + case *PackageType: + var pv *PackageValue + if cx, ok := currExpr.X.(*ConstExpr); ok { + // NOTE: *Machine.TestMemPackage() needs this + // to pass in an imported package as *ConstEzpr. + pv = cx.V.(*PackageValue) + } else { + // otherwise, packages can only be referred to by + // *NameExprs, and cannot be copied. + pvc := evalConst(store, last, currExpr.X) + pv_, ok := pvc.V.(*PackageValue) + if !ok { + panic(fmt.Sprintf( + "missing package in selector expr %s", + currExpr.String())) + } + pv = pv_ + } + if pv.GetBlock(store).Source.GetIsConst(store, currExpr.Sel) { + break Main + } + + tt := pv.GetBlock(store).Source.GetStaticTypeOf(store, currExpr.Sel) + panic(fmt.Sprintf("%s (variable of type %s) is not constant", currExpr.String(), tt)) + case *PointerType, *DeclaredType, *StructType, *InterfaceType, *TypeType, *NativeType: + ty := evalStaticTypeOf(store, last, currExpr) + if _, ok := ty.(*TypeType); ok { + ty = evalStaticType(store, last, currExpr) + } + panic(fmt.Sprintf("%s (variable of type %s) is not constant", currExpr.String(), ty)) + default: + panic(fmt.Sprintf( + "unexpected selector expression type %v", + reflect.TypeOf(xt))) + } + default: + ift := evalStaticTypeOf(store, last, currExpr) + if _, ok := ift.(*TypeType); ok { + ift = evalStaticType(store, last, currExpr) + } + panic(fmt.Sprintf("%s (variable of type %s) is not constant", currExpr.String(), ift)) + } +} + // checkValDefineMismatch checks for mismatch between the number of variables and values in a ValueDecl or AssignStmt. func checkValDefineMismatch(n Node) { var ( diff --git a/gnovm/tests/files/const23.gno b/gnovm/tests/files/const23.gno new file mode 100644 index 00000000000..f445c3e8eb2 --- /dev/null +++ b/gnovm/tests/files/const23.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t []string = []string{} + fmt.Println(t) +} + +// Error: +// main/files/const23.gno:6:8: invalid constant type []string diff --git a/gnovm/tests/files/const24.gno b/gnovm/tests/files/const24.gno new file mode 100644 index 00000000000..d82c50c86aa --- /dev/null +++ b/gnovm/tests/files/const24.gno @@ -0,0 +1,82 @@ +package main + +import ( + "fmt" + "time" +) + +func main() { + const a int = 1_000_000 + const b byte = byte(1) + const c float64 = 1_000_000.000 + const d string = "Hello, World!" + const e rune = 'a' + const g bool = true + const h uint = 1_000 + const i int8 = 1 + const j int16 = 1 + const k int32 = 1 + const l int64 = 1 + const m uint8 = 1 + const n uint16 = 1 + const o uint32 = 1 + const p uint64 = 1 + const r float32 = 1_000_000.000 + const s = r + const t = len("s") + const u = 1 + len("s") + 3 + ars := [10]string{} + const v = len(ars) + const w = cap(ars) + const x = time.Second + const y = +len("ay") + + fmt.Println(a) + fmt.Println(b) + fmt.Println(c) + fmt.Println(d) + fmt.Println(e) + fmt.Println(g) + fmt.Println(h) + fmt.Println(i) + fmt.Println(j) + fmt.Println(k) + fmt.Println(l) + fmt.Println(m) + fmt.Println(n) + fmt.Println(o) + fmt.Println(p) + fmt.Println(r) + fmt.Println(s) + fmt.Println(t) + fmt.Println(u) + fmt.Println(v) + fmt.Println(w) + println(x) + fmt.Println(y) +} + +// Output: +// 1000000 +// 1 +// 1e+06 +// Hello, World! +// 97 +// true +// 1000 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1 +// 1e+06 +// 1e+06 +// 1 +// 5 +// 10 +// 10 +// 1s +// 2 diff --git a/gnovm/tests/files/const25.gno b/gnovm/tests/files/const25.gno new file mode 100644 index 00000000000..64e0358bdef --- /dev/null +++ b/gnovm/tests/files/const25.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t = []string{"1"} + fmt.Println(t) +} + +// Error: +// main/files/const25.gno:6:8: [](const-type string){(const ("1" string))} (variable of type []string) is not constant diff --git a/gnovm/tests/files/const26.gno b/gnovm/tests/files/const26.gno new file mode 100644 index 00000000000..a1533e98c57 --- /dev/null +++ b/gnovm/tests/files/const26.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() string { + return "" +} + +func main() { + const t = v() + fmt.Println(t) +} + +// Error: +// main/files/const26.gno:10:8: v() (value of type string) is not constant diff --git a/gnovm/tests/files/const27.gno b/gnovm/tests/files/const27.gno new file mode 100644 index 00000000000..4be731e16a7 --- /dev/null +++ b/gnovm/tests/files/const27.gno @@ -0,0 +1,16 @@ +package main + +import "fmt" + +func v() string { + return "" +} + +func main() { + var i interface{} = 1 + const t, ok = i.(int) + fmt.Println(t, ok) +} + +// Error: +// main/files/const27.gno:11:8: i.((const-type int)) (comma, ok expression of type (const-type int)) is not constant diff --git a/gnovm/tests/files/const28.gno b/gnovm/tests/files/const28.gno new file mode 100644 index 00000000000..e4762c3205c --- /dev/null +++ b/gnovm/tests/files/const28.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + var s []string = []string{"1"} + const t, ok = s[0] + fmt.Println(t, ok) +} + +// Error: +// main/files/const28.gno:7:8: s[(const (0 int))] (variable of type string) is not constant diff --git a/gnovm/tests/files/const29.gno b/gnovm/tests/files/const29.gno new file mode 100644 index 00000000000..41d8d0a816d --- /dev/null +++ b/gnovm/tests/files/const29.gno @@ -0,0 +1,12 @@ +package main + +import "fmt" + +func main() { + s := "1" + const t = s + fmt.Println(t) +} + +// Error: +// main/files/const29.gno:7:8: s (variable of type string) is not constant diff --git a/gnovm/tests/files/const30.gno b/gnovm/tests/files/const30.gno new file mode 100644 index 00000000000..4a166013cdc --- /dev/null +++ b/gnovm/tests/files/const30.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() { + return +} + +func main() { + const t = v() + fmt.Println(t) +} + +// Error: +// main/files/const30.gno:10:8: v (no value) used as value diff --git a/gnovm/tests/files/const31.gno b/gnovm/tests/files/const31.gno new file mode 100644 index 00000000000..e37577789e6 --- /dev/null +++ b/gnovm/tests/files/const31.gno @@ -0,0 +1,15 @@ +package main + +import "fmt" + +func v() (string, string) { + return "", "" +} + +func main() { + const t, v = v() + fmt.Println(t) +} + +// Error: +// main/files/const31.gno:10:8: (const (v func()( string, string)))() (variable of type (string,string)) is not constant diff --git a/gnovm/tests/files/const32.gno b/gnovm/tests/files/const32.gno new file mode 100644 index 00000000000..83d3ae5e73c --- /dev/null +++ b/gnovm/tests/files/const32.gno @@ -0,0 +1,11 @@ +package main + +import "fmt" + +func main() { + const t = 1 + 2 + len([]string{}) + fmt.Println(t) +} + +// Error: +// main/files/const32.gno:6:8: [](const-type string){} (variable of type []string) is not constant diff --git a/gnovm/tests/files/const33.gno b/gnovm/tests/files/const33.gno new file mode 100644 index 00000000000..42652d3b458 --- /dev/null +++ b/gnovm/tests/files/const33.gno @@ -0,0 +1,12 @@ +package main + +var x = 1 +var y = 1 + +const b = x == y + +func main() { + println("ok") +} +// Error: +// main/files/const33.gno:6:7: x (variable of type int) is not constant diff --git a/gnovm/tests/files/const34.gno b/gnovm/tests/files/const34.gno new file mode 100644 index 00000000000..9c79cf86b88 --- /dev/null +++ b/gnovm/tests/files/const34.gno @@ -0,0 +1,10 @@ +package main + +const a = func() { println("hey") } + +func main() { + println("ok") +} + +// Error: +// main/files/const34.gno:3:7: func func(){ (const (println func(xs ...interface{})()))((const ("hey" string))) } (variable of type func()()) is not constant diff --git a/gnovm/tests/files/const35.gno b/gnovm/tests/files/const35.gno new file mode 100644 index 00000000000..e85d68eb8db --- /dev/null +++ b/gnovm/tests/files/const35.gno @@ -0,0 +1,12 @@ +package main + +var x = 1 + +const ff = +(1 << x) + +func main() { + println("ok") +} + +// Error: +// main/files/const35.gno:5:7: x (variable of type int) is not constant diff --git a/gnovm/tests/files/const36.gno b/gnovm/tests/files/const36.gno new file mode 100644 index 00000000000..8a677a35be9 --- /dev/null +++ b/gnovm/tests/files/const36.gno @@ -0,0 +1,13 @@ +package main + +type s struct { + x int +} + +func main() { + s := s{1} + const v = s.x +} + +// Error: +// main/files/const36.gno:9:8: s.x (variable of type int) is not constant diff --git a/gnovm/tests/files/const37_native.gno b/gnovm/tests/files/const37_native.gno new file mode 100644 index 00000000000..6a164328a3b --- /dev/null +++ b/gnovm/tests/files/const37_native.gno @@ -0,0 +1,10 @@ +package main + +import "time" + +func main() { + const v = time.UTC +} + +// Error: +// main/files/const37_native.gno:6:8: time.UTC (variable of type *time.Location) is not constant diff --git a/gnovm/tests/files/const37_stdlibs.gno b/gnovm/tests/files/const37_stdlibs.gno new file mode 100644 index 00000000000..9ec614f2538 --- /dev/null +++ b/gnovm/tests/files/const37_stdlibs.gno @@ -0,0 +1,10 @@ +package main + +import "time" + +func main() { + const v = time.UTC +} + +// Error: +// main/files/const37_stdlibs.gno:6:8: time.UTC (variable of type *time.Location) is not constant \ No newline at end of file diff --git a/gnovm/tests/files/const38.gno b/gnovm/tests/files/const38.gno new file mode 100644 index 00000000000..815e74fa76a --- /dev/null +++ b/gnovm/tests/files/const38.gno @@ -0,0 +1,11 @@ +package main + +import "std" + +func main() { + v := std.Coin{} + const c = v.Denom +} + +// Error: +// main/files/const38.gno:7:8: v.Denom (variable of type string) is not constant diff --git a/gnovm/tests/files/const39.gno b/gnovm/tests/files/const39.gno new file mode 100644 index 00000000000..68ff7dd5630 --- /dev/null +++ b/gnovm/tests/files/const39.gno @@ -0,0 +1,14 @@ +package main + +type T struct { + a int +} + +func (tv T) Mv(a int) int { return 0 } + +func main() { + const t = T.Mv +} + +// Error: +// main/files/const39.gno:10:8: T.Mv (variable of type func(tv main.T,a int)( int)) is not constant diff --git a/gnovm/tests/files/const40.gno b/gnovm/tests/files/const40.gno new file mode 100644 index 00000000000..d1dedc382e6 --- /dev/null +++ b/gnovm/tests/files/const40.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t = [0]string{} +} + +// Error: +// main/files/const40.gno:4:8: [(const (0 int))](const-type string){} (variable of type [0]string) is not constant diff --git a/gnovm/tests/files/const41.gno b/gnovm/tests/files/const41.gno new file mode 100644 index 00000000000..b4424dcef94 --- /dev/null +++ b/gnovm/tests/files/const41.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t [0]string = [0]string{} +} + +// Error: +// main/files/const41.gno:4:8: invalid constant type [0]string \ No newline at end of file diff --git a/gnovm/tests/files/const42.gno b/gnovm/tests/files/const42.gno new file mode 100644 index 00000000000..5763a2fc121 --- /dev/null +++ b/gnovm/tests/files/const42.gno @@ -0,0 +1,8 @@ +package main + +func main() { + const t int +} + +// Error: +// main/files/const42.gno:4:8: missing init expr for t \ No newline at end of file diff --git a/gnovm/tests/files/const43.gno b/gnovm/tests/files/const43.gno new file mode 100644 index 00000000000..d929e526579 --- /dev/null +++ b/gnovm/tests/files/const43.gno @@ -0,0 +1,10 @@ +package main + +func main() { + a := [2]int{1, 2} + + const b = a +} + +// Error: +// main/files/const43.gno:6:8: a (variable of type [2]int) is not constant diff --git a/gnovm/tests/files/const44.gno b/gnovm/tests/files/const44.gno new file mode 100644 index 00000000000..69924b8ea9d --- /dev/null +++ b/gnovm/tests/files/const44.gno @@ -0,0 +1,10 @@ +package main + +const a = interface{}(nil) + +func main() { + println("ok") +} + +// Error: +// main/files/const44.gno:3:7: (const (undefined)) (variable of type interface{}) is not constant diff --git a/gnovm/tests/files/const45_a.gno b/gnovm/tests/files/const45_a.gno new file mode 100644 index 00000000000..fef13e2fc68 --- /dev/null +++ b/gnovm/tests/files/const45_a.gno @@ -0,0 +1,14 @@ +package main + +type MyStruct struct { + arr [2]int +} + +const a = len(MyStruct{arr: [2]int{1, 2}}.arr) + +func main() { + println("ok") +} + +// Output: +// ok diff --git a/gnovm/tests/files/const45_b.gno b/gnovm/tests/files/const45_b.gno new file mode 100644 index 00000000000..7da25d3268c --- /dev/null +++ b/gnovm/tests/files/const45_b.gno @@ -0,0 +1,14 @@ +package main + +type MyStruct struct { + arr []int +} + +const a = len(MyStruct{arr: []int{1, 2}}.arr) + +func main() { + println("ok") +} + +// Error: +// main/files/const45_b.gno:7:7: MyStruct{arr: [](const-type int){(const (1 int)), (const (2 int))}}.arr (variable of type []int) is not constant diff --git a/gnovm/tests/files/const46.gno b/gnovm/tests/files/const46.gno new file mode 100644 index 00000000000..4722cba294e --- /dev/null +++ b/gnovm/tests/files/const46.gno @@ -0,0 +1,10 @@ +package main + +const a = len(map[string][2]int{"arr": {1, 2}}["arr"]) + +func main() { + println("ok") +} + +// Output: +// ok diff --git a/gnovm/tests/files/const47.gno b/gnovm/tests/files/const47.gno new file mode 100644 index 00000000000..528ba469562 --- /dev/null +++ b/gnovm/tests/files/const47.gno @@ -0,0 +1,10 @@ +package main + +const a = len(map[string][2]interface{}{"arr": {1, 2}}["arr"]) + +func main() { + println("ok") +} + +// Output: +// ok diff --git a/gnovm/tests/files/const48.gno b/gnovm/tests/files/const48.gno new file mode 100644 index 00000000000..001fd911fa5 --- /dev/null +++ b/gnovm/tests/files/const48.gno @@ -0,0 +1,9 @@ +package main + +func main() { + const a = len(map[string][]int{"arr": {1, 2}}) + println("ok", a) +} + +// Error: +// main/files/const48.gno:4:8: map[(const-type string)] [](const-type int){(const ("arr" string)): (const-type []int){(const (1 int)), (const (2 int))}} (variable of type map[string][]int) is not constant diff --git a/gnovm/tests/files/const49.gno b/gnovm/tests/files/const49.gno new file mode 100644 index 00000000000..4b3f38e4d5e --- /dev/null +++ b/gnovm/tests/files/const49.gno @@ -0,0 +1,16 @@ +package main + +import "io" + +type ( + s [2]int + m s +) + +func main() { + const v = len(m{1, 2}) + println(v) +} + +// Output: +// 2 diff --git a/gnovm/tests/files/const50.gno b/gnovm/tests/files/const50.gno new file mode 100644 index 00000000000..5144173bf74 --- /dev/null +++ b/gnovm/tests/files/const50.gno @@ -0,0 +1,12 @@ +package main + +var x = "a" + +const v = len(x) + +func main() { + println("ok") +} + +// Error: +// main/files/const50.gno:5:7: x (variable of type string) is not constant