arnodel / golua

A Lua compiler / runtime in Go
Apache License 2.0
93 stars 10 forks source link

panic: Cannot compile r2 := Op(257)(r1, r4) on go 1.18 #87

Closed TorchedSammy closed 2 years ago

TorchedSammy commented 2 years ago

hi, seems that using golua with go 1.18.1 causes a panic about an invalid op on valid lua code. this doesn't happen with go 1.17.9. for reference, im trying to run this lua file

discovered this after some people using hilbish (a shell i develop) reported it. that issue includes a full stacktrace.

while i do have a fork, there's minimal changes (see at Rosettea/golua) and it still happens on normal golua

willeccles commented 2 years ago

I've done some testing and narrowed down the issue. This appears to me to be a bug in go 1.18[.1]. I've extracted the contents of ops/ops.go and run a test program (see below) with go 1.18.1 and go 1.17.9. The results are indeed different. As far as I can tell, iota is supposed to reset to 0 every time const appears (or at least, that's how it used to work, anyway). As of 1.18[.1], this does not appear to happen. If you run the program below in both versions, you'll see that they work differently. As an example: OpAnd is the second occurrence of iota. Previously, this would result in 1 + (0)<<8. In go 1.18.1, however, it's instead doing 1 + (1)<<8, changing the value of OpAnd from 1 to 257. Again, I am not sure if this is a go bug or not, but I don't see this mentioned anywhere in any release notes.

The test program (copy the contents of ops/ops.go into the top of this program):

func main() {
    fmt.Println("OpOr", OpOr)
    fmt.Println("OpAnd", OpAnd)
    fmt.Println("OpLt", OpLt)
    fmt.Println("OpLeq", OpLeq)
    fmt.Println("OpGt", OpGt)
    fmt.Println("OpGeq", OpGeq)
    fmt.Println("OpEq", OpEq)
    fmt.Println("OpNeq", OpNeq)
    fmt.Println("OpBitOr", OpBitOr)
    fmt.Println("OpBitXor", OpBitXor)
    fmt.Println("OpBitAnd", OpBitAnd)
    fmt.Println("OpShiftL", OpShiftL)
    fmt.Println("OpShiftR", OpShiftR)
    fmt.Println("OpConcat", OpConcat)
    fmt.Println("OpAdd", OpAdd)
    fmt.Println("OpSub", OpSub)
    fmt.Println("OpMul", OpMul)
    fmt.Println("OpDiv", OpDiv)
    fmt.Println("OpFloorDiv", OpFloorDiv)
    fmt.Println("OpMod", OpMod)
    fmt.Println("OpNeg", OpNeg)
    fmt.Println("OpNot", OpNot)
    fmt.Println("OpLen", OpLen)
    fmt.Println("OpBitNot", OpBitNot)
    fmt.Println("OpId", OpId)
    fmt.Println("OpPow", OpPow)
}
willeccles commented 2 years ago

This appears to be a bug in go 1.18.1, as the go language spec requires that iota reset to 0 on each constant declaration.

willeccles commented 2 years ago

I have opened a go issue here: https://github.com/golang/go/issues/52438.

@TorchedSammy I believe for the time being, a workaround may be to manually set the values in this file in your fork to their expected values.

TorchedSammy commented 2 years ago

since this is a go bug (and there's already a fix), i'm just gonna close

arnodel commented 2 years ago

Thank you for the report!