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
Null
inferred 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 typeNothing
for both type parameters ofmax()
, because the type parameters are treated as unconstrained. Then, sinceNothing
is 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!