Issue Type: Other
Impact: Moderate
Frequency: Constantly
Date First Experienced: 2021-04-10 00:04:00 (-06:00)
Date Last Experienced: 2021-04-10 00:04:00 (-06:00)
Reproduction Steps:
Reproducing this is fairly simple. Simply compare the following snippets:
--!nocheck
local function usesFoo()
local x: number = foo
end
local foo = 'fighters'
--!strict
local function usesFoo()
local x: number = foo
end
local foo = 'fighters'
Both of these will emit a warning; however, the warning in the strict mode example is not the correct warning.
Now consider the two following snippets:
--!nocheck
local function usesFoo()
local x: string = foo
end
local foo = 'fighters'
--!strict
local function usesFoo()
local x: string = foo
end
local foo = 'fighters'
In this case, the --!nocheck
mode snippet will correctly identify the global variable as missing; however, in --!strict mode, there is no warning.
This matters because I ran into a bug that affected my code at runtime but was not caught in static analysis.
Expected Behavior:
I expect the following snippets to only emit an “unknown global” warning.
--!strict
local function usesFoo()
local x: string = foo
end
local foo = 'fighters'
--!strict
local function usesFoo()
local x: number = foo
end
local foo = 'fighters'
Actual Behavior:
In the first example (–!nocheck mode), the variable is correctly identified as an “unknown global” and a warning shows up
However, in strict or nonstrict mode, this variable’s type will be exposed even if the variable is out of scope with the function referencing it.
If I type
x
as “string” instead of “number”, the warning disappears entirely:Workaround:
You could, hypothetically, set your code to --!nocheck
mode to catch unknown globals, then switch it back to --!strict
mode for everything else I guess?