From 4e46182d3e5bd89c573142d30397876b5e89a944 Mon Sep 17 00:00:00 2001 From: Emmanuel T Odeke Date: Thu, 13 Feb 2025 22:51:01 +0200 Subject: [PATCH] fix(gnolang): prescriptively reject *ast.(IndexListExpr, GoStmt) as unrecognized for Gno The *ast.IndexListExpr is used for generics but in assignment operations it is illegal to use. This change returns a proper error and matches Go's output. Also *ast.GoStmt is for spawning Go routines but those are forbidden in Gno, hence reject them prescriptively instead of just spewing out the raw ast type. Fixes #3731 Updates #3751 --- gnovm/cmd/gno/tool_lint.go | 9 ++++++++- gnovm/pkg/gnolang/go2gno.go | 8 ++++++++ gnovm/tests/files/goroutine_not_supported.gno | 16 ++++++++++++++++ gnovm/tests/files/parse_indexListExpr.gno | 16 ++++++++++++++++ 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 gnovm/tests/files/goroutine_not_supported.gno create mode 100644 gnovm/tests/files/parse_indexListExpr.gno diff --git a/gnovm/cmd/gno/tool_lint.go b/gnovm/cmd/gno/tool_lint.go index 812a2baf103..50183979fb0 100644 --- a/gnovm/cmd/gno/tool_lint.go +++ b/gnovm/cmd/gno/tool_lint.go @@ -265,11 +265,12 @@ var reParseRecover = regexp.MustCompile(`^([^:]+)((?::(?:\d+)){1,2}):? *(.*)$`) func catchRuntimeError(pkgPath string, stderr goio.WriteCloser, action func()) (hasError bool) { defer func() { - // Errors catched here mostly come from: gnovm/pkg/gnolang/preprocess.go + // Errors caught here mostly come from: gnovm/pkg/gnolang/preprocess.go r := recover() if r == nil { return } + hasError = true switch verr := r.(type) { case *gno.PreprocessError: @@ -303,6 +304,12 @@ func issueFromError(pkgPath string, err error) lintIssue { issue.Confidence = 1 issue.Code = lintGnoError + if ewp, ok := err.(*gno.LocationPlusError); ok { + issue.Location = ewp.Location() + issue.Msg = ewp.Message() + return issue + } + parsedError := strings.TrimSpace(err.Error()) parsedError = strings.TrimPrefix(parsedError, pkgPath+"/") diff --git a/gnovm/pkg/gnolang/go2gno.go b/gnovm/pkg/gnolang/go2gno.go index b98136b13b5..7a21cc941c8 100644 --- a/gnovm/pkg/gnolang/go2gno.go +++ b/gnovm/pkg/gnolang/go2gno.go @@ -441,6 +441,7 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { if len(gon.Recv.List) > 1 { panicWithPos("method has multiple receivers") } + if len(gon.Recv.List) == 0 { panicWithPos("method has no receiver") } @@ -478,6 +479,13 @@ func Go2Gno(fs *token.FileSet, gon ast.Node) (n Node) { } case *ast.EmptyStmt: return &EmptyStmt{} + case *ast.IndexListExpr: + if len(gon.Indices) > 1 { + panicWithPos("invalid operation: more than one index"}) + } + panicWithPos("invalid operation: indexList is not permitted in Gno"}) + case *ast.GoStmt: + panicWithPos("goroutines are not permitted"}) default: panicWithPos("unknown Go type %v: %s\n", reflect.TypeOf(gon), diff --git a/gnovm/tests/files/goroutine_not_supported.gno b/gnovm/tests/files/goroutine_not_supported.gno new file mode 100644 index 00000000000..c9e9d01e010 --- /dev/null +++ b/gnovm/tests/files/goroutine_not_supported.gno @@ -0,0 +1,16 @@ +// https://github.com/gnolang/gno/issues/3751 + +package math + +import "testing" + +func Add(a, b int) int { + return a + b +} + +func TestAdd(t *testing.T) { + go Add(1, 1) +} + +// Error: +// files/goroutine_not_supported.gno:12:5: goroutines are not permitted diff --git a/gnovm/tests/files/parse_indexListExpr.gno b/gnovm/tests/files/parse_indexListExpr.gno new file mode 100644 index 00000000000..e876bf88291 --- /dev/null +++ b/gnovm/tests/files/parse_indexListExpr.gno @@ -0,0 +1,16 @@ +// https://github.com/gnolang/gno/issues/3731 + +package main + +type node struct { + r []int +} + +func (n *node) foo(targ, wndex int) { + _ = n.r[targ, wndex] +} + +func main() {} + +// ERROR: +// files/parse_indexListExpr.gno:10:6: invalid operation: more than one index