How to understand the Int Double conversion in Swift?

Extend the example in “The Swift Programming Language” (Swift 5.5) “Integer and Floating-Point Conversion”:

3 + 0.14 // allowed

let three = 3
let rest = 0.14

3 + rest // allowed
0.14 + three // compile error
three + 0.14 // compile error

I don’t understand why the last two lines are taken as compile error. Can anyone help to explain a bit? Thanks.

The + operator takes two arguments of the same type, and the types of variables and constants are inferred considering only their initializations and not how they're later used. rest is inferred to have Double type, so 3 + rest is only allowed if the literal 3 can have Double type. Similarly, three is inferred to have Int type, so three + 0.14 is only allowed if the literal 0.14 can have Int type. But while 3 can have Double type (since integers are usually expressible as Doubles), 0.14 cannot have Int type (since fractions are not expressible as Ints).

3 Likes

You might appreciate this read: Swift Literals - NSHipster

1 Like

There are two related things going on in the sample code: type inference (of variables) and coercion of literals to a type.

With type inference of variable declarations, the compiler uses the type(s) of the assigned value(s) to infer the variable's type.

let x: Double = 3.14
let y = x // <== y is inferred to be a Double because it has been assigned a value that is known to be of type Double

Coercion of literals is the process of determining what type to give a literal (usually a number-like string of characters). For this, the compiler will use the variable declaration (such as x in my example above), the function to which the literal is being passed as a parameter, or other context that is available.

Now that we have this information, let's take your code line-by-line.

3 + 0.14

In Swift, operators are functions. The + operator takes two parameters (its operands). All overloads of + that take numbers take numbers of the same type. The compiler determines that 0.14 is not expressing an Int, so it assigns it a type of Double. Now the compiler looks at 3, knowing that it must have the same type as 0.14 to be valid for the + operator. As 3 can express a Double, the compiler performs the implicit conversion and 3 is given a type of Double.

let three = 3

This is inferring the type of the literal and assigning that type to the variable three. The compiler prefers conversions to Int over conversions to Double. As 3 is parsable as an Int, the compiler implicitly converts the literal to an Int. As an Int is being assigned to three, the type of three will be Int. This line combines both literal coercion and type inference of variables.

let rest = 0.14

This is the same as the previous line, except that 0.14 isn't parsable as Int, so the compiler parses it as a Double.

3 + rest

As in the first line, the compiler knows that rest is of type Double, so it infers that 3 must be given the same type. As this is possible, the compiler goes ahead and does it.

0.14 + three

As explained above, 0.14 can't be given a type of Int, and three is of type Int. As the + operator requires its operands to have the same type, the compiler produces an error.

three + 0.14

Same as the previous, as you've only reversed the order of arguments.

2 Likes