Reputation: 847
There is what scala does, and then there is why.
My question is why does scala prefer to convert the Int to Double rather than infer AnyVal or Any:
// test1:
scala> val foo = if (true) 5 else 5.0
foo: Double = 5.0 // Why isn't this AnyVal or Any ?
// I can force it this way... once I realized this was my problem.
scala> val foo: Any = if (true) 5 else 5.0
foo: Any = 5
// or this way, which is better actually
scala> val bar : java.lang.Number = if (true) 5 else 5.0
bar: Number = 5
But my question isn't what it does, but why is the behavior of converting the Int to Double correct or rational?
I wasted quite a bit of time isolating this as what was causing a bug, and to avoid this in the future I'd like to develop some intuition for these conversions.
Upvotes: 1
Views: 401
Reputation: 55569
It's called numeric widening. See SLS 6.23.1 - Value Conversions:
If e has a primitive number type which weakly conforms to the expected type, it is widened to the expected type using one of the numeric conversion methods toShort, toChar, toInt, toLong, toFloat, toDouble defined here.
Where weak conformance is defined in SLS 3.5.3:
Byte <:w Short
Short <:w Int
Char <:w Int
Int <:w Long
Long <:w Float
Float <:w Double
Int
(transitively) weakly conforms to Double
, so the compiler infers Double
instead of AnyVal
, and uses Int#toDouble
to make the conversion.
Why is this okay? You haven't actually presented a bug caused by this. As long as the weak conformance relation is followed, the type conversions will not lose any information. It makes more sense to infer Double
instead of AnyVal
, because you lose type information you could have otherwise kept (as AnyVal
isn't necessarily a number).
Upvotes: 3