Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(gnovm): align Gno constant handling with Go specifications #2828

Open
wants to merge 11 commits into
base: master
Choose a base branch
from

Conversation

omarsy
Copy link
Member

@omarsy omarsy commented Sep 21, 2024

Related Issues:
#2628

This PR aims to align Gno's constant handling with the Go specification regarding constant expressions (see Go Specification on Constants).

  1. Primitive Type Requirement

    • Should Work:
      const t = 1
    • Should Return an Error:
      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:
      const t = len("s")
    • Should Return an Error:
      func v() string {
          return ""
      }
      const t = v()
      Error:
      v<VPBlock(3,0)>() (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:
      const t = 1
      const v = t
    • Should Raise an Error:
      t := 1
      const v = t
      Error:
      t (variable of type int) is not constant
      
  4. Type Assertion Forbidden

    • This code:
      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:
      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, if any. More info here.

@github-actions github-actions bot added the 📦 🤖 gnovm Issues or PRs gnovm related label Sep 21, 2024
Copy link

codecov bot commented Sep 21, 2024

Codecov Report

Attention: Patch coverage is 78.07018% with 25 lines in your changes missing coverage. Please review.

Project coverage is 63.40%. Comparing base (1a57e81) to head (3a52e14).
Report is 11 commits behind head on master.

Files with missing lines Patch % Lines
gnovm/pkg/gnolang/type_check.go 77.77% 19 Missing and 3 partials ⚠️
gnovm/pkg/gnolang/preprocess.go 80.00% 2 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2828      +/-   ##
==========================================
+ Coverage   63.37%   63.40%   +0.03%     
==========================================
  Files         561      565       +4     
  Lines       79199    80149     +950     
==========================================
+ Hits        50189    50821     +632     
- Misses      25625    25912     +287     
- Partials     3385     3416      +31     
Flag Coverage Δ
contribs/gnodev 60.57% <ø> (ø)
contribs/gnofaucet 15.77% <ø> (ø)
gno.land 67.37% <ø> (-0.01%) ⬇️
gnovm 67.94% <78.07%> (+<0.01%) ⬆️
misc/genstd 79.72% <ø> (ø)
tm2 62.45% <ø> (+0.19%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@omarsy omarsy marked this pull request as ready for review October 18, 2024 20:52
@omarsy omarsy changed the title feat(gnovm): align Gno constant handling with Go specifications WIP feat(gnovm): align Gno constant handling with Go specifications Oct 18, 2024
@jefft0
Copy link
Contributor

jefft0 commented Oct 19, 2024

@omarsy , can you fix the lint-pr-title CI check?

@jefft0 jefft0 added the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Oct 19, 2024
@omarsy omarsy changed the title WIP feat(gnovm): align Gno constant handling with Go specifications feat(gnovm): align Gno constant handling with Go specifications Oct 19, 2024
@Kouteki Kouteki added this to the 🚀 Mainnet launch milestone Oct 22, 2024
@ltzmaxwell
Copy link
Contributor

ltzmaxwell commented Oct 22, 2024

consider this one, it should be handled:

package main

var x = 1

const ff = +(1 << x)

func main() {
	println("ok")
}

and this one:

package main

const a = func() { println("hey") }

func main() {
	println("ok")
}

this triggers an error message like:
"func func(){ (const (println func(xs ...interface{})()))((const ("hey" string))) } is not a type",
which is not the intended outcome.

for _, arg := range vx.Args {
checkConstantExpr(store, last, arg)
}
case *NativeType:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a better msg? a test?

Copy link
Member Author

@omarsy omarsy Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved the message, but testing this branch is on hold until we resolve #3006.
related commit: b80a890

@jefft0 jefft0 removed the review/triage-pending PRs opened by external contributors that are waiting for the 1st review label Oct 22, 2024
@jefft0
Copy link
Contributor

jefft0 commented Oct 22, 2024

Removed the review/triage-pending label because all CI tests passed, this has been declared as a priority, and core dev ltzmaxwell is reviewing it.

}
case *BinaryExpr:
checkConstantExpr(store, last, vx.Left)
checkConstantExpr(store, last, vx.Right)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider this one as a special case:

package main

var x = 1
var y = 1

const b = x == y

func main() {
	println("ok")
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this one return an error in my PR, I think. Do you want I added as a test ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

@omarsy omarsy Oct 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that when you run it, you'll encounter an error like x (variable of type int) is not constant. While it's not the same error, I think the description of the error in my PR better clarifies the issue we have.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO, it would be more natural that the RHS is not const, rather than its child node.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find the current error message a bit unclear. For example, consider the following code:

package main

const x = 1

var y = 1

const b = x == y

func main() {
	println("ok")
}

In Go, this will produce the error: x == y (untyped bool value) is not constant. However, in the PR, the error we get is: y (variable of type int) is not constant.

This difference suggests that we should change our code to make it work, like so:

package main

const x = 1

const y = 1

const b = x == y

func main() {
	println("ok")
}

The Go error message is more informative, indicating that the expression itself is not considered constant rather than simply pointing out that y is a variable.

Copy link
Member Author

@omarsy omarsy Oct 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I can the logic of the code if you think it is a blocker (to be more go like)

// break Main
// }
// panic(fmt.Sprintf("%s (variable of type %s) is not constant", vx.String(), xt))
case *PointerType, *DeclaredType, *StructType, *InterfaceType:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

more tests on this?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

right, done here: e74e6e9

@ltzmaxwell
Copy link
Contributor

Partial, will have a final one after.

@omarsy
Copy link
Member Author

omarsy commented Oct 23, 2024

consider this one, it should be handled:

package main

var x = 1

const ff = +(1 << x)

func main() {
	println("ok")
}

and this one:

package main

const a = func() { println("hey") }

func main() {
	println("ok")
}

this triggers an error message like: "func func(){ (const (println func(xs ...interface{})()))((const ("hey" string))) } is not a type", which is not the intended outcome.

nice catch @ltzmaxwell ^^
improved the error message here 90c8c5b

@omarsy omarsy force-pushed the fix/2628 branch 2 times, most recently from 955eb18 to 90bd7a8 Compare October 24, 2024 19:55
case *FuncType:
tup := evalStaticTypeOfRaw(store, last, vx).(*tupleType)

// check for built-in functions
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If real and imag are added later, it would need to be handled here as well.
Can you add a comment for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
📦 🤖 gnovm Issues or PRs gnovm related 🧾 package/realm Tag used for new Realms or Packages.
Projects
Status: No status
Status: In Review
Development

Successfully merging this pull request may close these issues.

6 participants