Open getify opened 5 years ago
Definitely yes, should throw an error for first foo(x)
and not for second. Just because the function is declared later in the code, it is declared with a certain signature that developer added with a purpose to be respected. The fact we're doing multi passes and that function is hoisted should not play a role, it is just a technical detail.
I actually think this is a very good example in how typl differs from other static type checkers and is suited to JS style.
:)
BTW, the reason why the second pass matters here is, if I wasn't careful to preserve this behavior, on the second pass x
would just always be a number, and therefore neither of the function calls would report an error.
The way this works is, if an identifier is determined to be undef
(on any pass), that is actually stored for that node. Subsequent passes do not update node types that are already assigned (even if undef
), but they can update an unknown
.
So, in the first pass, the x
node in foo(x)
is set to undef
because at that moment, it hasn't been assigned any other type (and it's local to that scope, not a param). Then the x = 3
forces an update to the scope binding for x
, setting it to number
.
On the second pass, even though the scope binding for x
is now number
, the x
in foo(x)
is still undef
from the first pass.
That's basically how Typl uses the lexical ordering to infer different types (specifically undef
vs any other type) throughout the lifetime of that scope.
There's nothing to do for this issue... I just want to document this quirk somewhere.
Think carefully about this code. What do you expect to happen? Any errors?
This code requires a second pass, because of the
foo(..)
hoisting. On the first pass,x
is initially implied asundef
, then it's re-implied asnumber
. So... on the second pass, would we expect the firstfoo(x)
to throw an error or not?I claim: yes it should throw an error. Even though
x
becomesnumber
later in the code, at the moment we first seefoo(x)
, it's stillundef
. On that second pass, we knowfoo(..)
expects anumber
, so we should get an error about argument type mismatch.Likewise, for the second
foo(x)
... since that one comes aftera = 3
, by that moment (even on the first pass), we know thatfoo(x)
is trying to pass a number. So... since that's valid, no error should be thrown for that line.The output (currently) is: