Godot version:
3.1 Beta 8
OS/device including version:
Windows 10 64bit
Issue description:
I don't really understand what is happening. But using a random number to access an array causes strange things to happen. I haven't noticed this with anything else.
For example in the script below there is an array with a size of 10. Inside the loop a random index is chosen and then 1 is added to it. After adding every number in the array together the expected result is 100, since the loop ran 100 times. This works in the first case with array a because the random number is assigned to a variable first. But this does not work with array b where the random number is used directly. Array b's total will sometimes be below and even above 100.
func _ready():
randomize()
# Random number assigned to a variable first.
# Total will always be 100
var a : = []
for i in 10:
a.append(0)
for i in 100:
var r : int = randi() % 10
a[r] += 1
var a_total : = 0
for i in 10:
a_total += a[i]
print("total: ", a_total)
print(a, "\n")
# Random number not assigned to variable.
# Total will sometimes be above or below 100
var b : = []
for i in 10:
b.append(0)
for i in 100:
# Issue happens here
b[randi() % 10] += 1
var b_total : = 0
for i in 10:
b_total += b[i]
print("total: ", b_total)
print(b)
Would this mean that:
b[randi() % 10] += 1
compiles as bytecode which actually does this:
var tmp = b[randi() % 10]
tmp += 1
b[randi() % 10] = tmp
Which is incorrect, the indexer expression must only be evaluated once, especially in cases where it's not just a variable or constant.
To test this theory, I tried this:
func _ready():
randomize()
var a = []
for i in 10:
a.append(0)
for i in 10:
print("---")
a[ran()] += 1
func ran():
print("Exec")
return randi() % 10
Surprise.
---
Exec
Exec
---
Exec
Exec
---
Exec
Exec
...
This also happens with dictionaries, and all the way from 2.1.5 to 3.1 beta7.
I get the same result without the randi().
func ran():
print("Exec")
return 1
Most helpful comment
Would this mean that:
compiles as bytecode which actually does this:
Which is incorrect, the indexer expression must only be evaluated once, especially in cases where it's not just a variable or constant.
To test this theory, I tried this:
Surprise.
This also happens with dictionaries, and all the way from 2.1.5 to 3.1 beta7.