There's nothing exactly wrong with the expression, though it does play into the current weakness of the type checking.
This is because +-*/
operators are somewhat overused.
Even among concrete types, Int
, Double
, Float
, and now all of SIMD
use them to certain extent. Further, most of them also conform to ExpressibleByIntegerLiteral
, and SIMD
even allow heterogeneous operator, e.g. Int + SIMD<Int>
. So the compiler needs to try all sorts of combination (potentially exponentially to the number of terms).
IIRC there's some shortcut taken when all the terms are literals, but I'll leave that to someone more knowledgeable.
The reason this works is because type checker can easily split expression around initialiser and as
keyword. For something like Int(a) + b
, the type of a
is independent of the type of b
, but the same can not be said with a + b
.
So Int(2 + (4 * 6)) * Int((3 + 5) + 7)
does split the whole expression into two, much smaller, parts
// This
Int(2 + (4 * 6)) * Int((3 + 5) + 7)
// is more or less the same as this
let tmp1 = Int(2 + (4 * 6))
let tmp2 = Int((3 + 5) + 7)
tmp1 * tmp2
resulting in a much more manageable chunk.
Even better, if you give compiler a nudge, it'll do much better. Try
(2 + (4 * 6)) * ((3 + 5) + 7) as Int
(2 + (4 * 6)) * ((3 + 5) + 7 as Int)
(2 + (4 * 6)) * ((3 as Int + 5) + 7)
With all that said, there's no need to be very defensive around type checker, like putting as
on everything. Compiler does get smarter over time and the need for this should lessen as well. I sometimes go back to my code base and remove unnecessary as
.