Skip to content

Commit

Permalink
feat(gnovm): returns error like in Golang when assignment with a func…
Browse files Browse the repository at this point in the history
…tion which does not return any value (gnolang#3049)

This PR aims at resolving this issue:
gnolang#1082

This depends on gnolang#3017 because it
refactored the code to sync the logic/code between AssignStmt vs
ValueDecl.

Related gnolang#2695

<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
</details>

---------

Co-authored-by: hieu.ha <[email protected]>
Co-authored-by: Mikael VALLENET <[email protected]>
  • Loading branch information
3 people authored and r3v4s committed Dec 10, 2024
1 parent f08779d commit 57dc54c
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 13 deletions.
20 changes: 7 additions & 13 deletions gnovm/pkg/gnolang/preprocess.go
Original file line number Diff line number Diff line change
Expand Up @@ -2373,7 +2373,7 @@ func defineOrDecl(
sts := make([]Type, numNames) // static types
tvs := make([]TypedValue, numNames)

if numNames > 1 && len(valueExprs) == 1 {
if numVals == 1 && numNames > 1 {
parseMultipleAssignFromOneExpr(sts, tvs, store, bn, nameExprs, typeExpr, valueExprs[0])
} else {
parseAssignFromExprList(sts, tvs, store, bn, isConst, nameExprs, typeExpr, valueExprs)
Expand Down Expand Up @@ -2410,7 +2410,7 @@ func parseAssignFromExprList(
for _, v := range valueExprs {
if cx, ok := v.(*CallExpr); ok {
tt, ok := evalStaticTypeOfRaw(store, bn, cx).(*tupleType)
if ok && len(tt.Elts) != 1 {
if ok && len(tt.Elts) > 1 {
panic(fmt.Sprintf("multiple-value %s (value of type %s) in single-value context", cx.Func.String(), tt.Elts))
}
}
Expand Down Expand Up @@ -3132,18 +3132,12 @@ func gnoTypeOf(store Store, t Type) Type {
// but rather computes the type OF x.
func evalStaticTypeOf(store Store, last BlockNode, x Expr) Type {
t := evalStaticTypeOfRaw(store, last, x)
if tt, ok := t.(*tupleType); ok {
if len(tt.Elts) != 1 {
panic(fmt.Sprintf(
"evalStaticTypeOf() only supports *CallExpr with 1 result, got %s",
tt.String(),
))
} else {
return tt.Elts[0]
}
} else {
return t

if tt, ok := t.(*tupleType); ok && len(tt.Elts) == 1 {
return tt.Elts[0]
}

return t
}

// like evalStaticTypeOf() but returns the raw *tupleType for *CallExpr.
Expand Down
8 changes: 8 additions & 0 deletions gnovm/pkg/gnolang/type_check.go
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,14 @@ func assertValidAssignRhs(store Store, last BlockNode, n Node) {
tt = evalStaticType(store, last, exp)
panic(fmt.Sprintf("%s (type) is not an expression", tt.String()))
}

// Ensures that function used in ValueDecl or AssignStmt must return at least 1 value.
if cx, ok := exp.(*CallExpr); ok {
tType, ok := tt.(*tupleType)
if ok && len(tType.Elts) == 0 {
panic(fmt.Sprintf("%s (no value) used as value", cx.Func.String()))
}
}
}
}

Expand Down
10 changes: 10 additions & 0 deletions gnovm/tests/files/assign37.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

func f() { }

func main() {
a := f()
}

// Error:
// main/files/assign37.gno:6:2: f<VPBlock(3,0)> (no value) used as value
12 changes: 12 additions & 0 deletions gnovm/tests/files/assign37b.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import "fmt"

func f() { }

func main() {
a, b := f(), f()
}

// Error:
// main/files/assign37b.gno:8:2: f<VPBlock(3,0)> (no value) used as value
10 changes: 10 additions & 0 deletions gnovm/tests/files/var34.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

func f() {}

func main() {
var t = f()
}

// Error:
// main/files/var34.gno:6:6: f<VPBlock(3,0)> (no value) used as value
11 changes: 11 additions & 0 deletions gnovm/tests/files/var34b.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package main

func f() {}

func main() {
var a int
a = f()
}

// Error:
// main/files/var34b.gno:7:2: f<VPBlock(3,0)> (no value) used as value
10 changes: 10 additions & 0 deletions gnovm/tests/files/var34c.gno
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package main

func f() {}

func main() {
var a, b int = f(), 1
}

// Error:
// main/files/var34c.gno:6:6: f<VPBlock(3,0)> (no value) used as value

0 comments on commit 57dc54c

Please sign in to comment.