I get why the inferred return type of max({}) is Null (and I think it's awesome how that function works with empty/possibly-empty/non-empty iterables), but why is using an empty named argument list—max{}—inferred to return Nothing? Why are those cases different? Is that intended?
This compiles and runs just fine,
Nothing foo = max{};
although I would've expected it to fail immediately if it actually evaluated nothing. Since Nothing is the subtype of everything, you can even do this,
Integer bar = max{};
and the compiler won't complain, but running that produces a java.lang.NullPointerException. What?! I thought we were never supposed to see that in Ceylon!
Wow, nice one! It took me a few minutes thinking to understand what is going on here. So, as I guess you know, this:
Is supposed to be, in theory, the same thing as these:
Now, if you write either of those permutations, you will get the correct return type
Nullinferred formax(). And, indeed, if you execute either example, the result is, correctly,null.Indeed, even if I run the following program:
It prints
<null>, as we would expect.So what's going on here is that I have a bug in my type argument inference algorithm, where it fails to take into account the "implicit" empty iterable argument, a
{Nothing*}, when inferring type args. Therefore, you're getting the inferred typeNothingfor both type parameters ofmax(), because the type parameters are treated as unconstrained. Then, sinceNothingis a subtype ofInteger, the typechecker lets you assign the result toInteger. Of course the null value that is actually returned by the function is not assignable toInteger, so you get an NPE that of course should never happen.The solution is I need to fix the bug. It will be a tiny one liner.
If you don't mind, would you submit a bug report to ceylon-spec please, and I will fix it tomorrow.
Thanks!