Reproduction Steps
Copy/paste this script into a blank place:
Source Code
--!strict
local function Counter(maxValue: number): ((invariant: any, index: number) -> (number?), any, number)
return function(invariant: any, index: number)
if index + 1 <= maxValue then
return index + 1;
else
--Signal end of iteration.
return nil;
end
end, nil, 0;
end
for value in Counter(5) do
print(value * 2);
--> 2
--> 4
--> 6
--> 8
--> 10
end
Notice that the type checker is unhappy.
Expected Behavior
I expect there to be no type errors.
Actual Behavior
There is a type error.
You can see it’s unhappy because the iterator returns a number?
. However, the contract for a for loop is that if the first returned value is nil, the for loop should terminate. Thus, we will never have value == nil
inside of the for loop body, and so the type of value
should be considered number
, NOT number?
Workaround
You can put an assertion on the first line of the for loop.
assert(value ~= nil);
This adds a bit of runtime cost for something the language already guarantees, so that’s a bit lame.
You can also go HAM on any
-casting. If you make the return type of my Counter
iterator number
and just cast nil
to any
, you can circumvent this issue.
Issue Area: Studio
Issue Type: Other
Impact: Moderate
Frequency: Rarely