Mike Beckerle
Mike Beckerle

Reputation: 847

why doesn't scala infer type Any or AnyVal from Int and Double?

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

Answers (1)

Michael Zajac
Michael Zajac

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

Related Questions