[[painless-casting]]
=== Casting

A cast converts the value of an original type to the equivalent value of a
target type. An implicit cast infers the target type and automatically occurs
during certain <<painless-operators, operations>>. An explicit cast specifies
the target type and forcefully occurs as its own operation.  Use the *cast
operator* to specify an explicit cast.

*Errors*

* If during a cast there exists no equivalent value for the target type.
* If an implicit cast is given, but an explicit cast is required.

*Grammar*
[source,ANTLR4]
----
cast: '(' TYPE ')' expression
----

*Examples*

* Valid casts.
+
[source,Painless]
----
<1> int i = (int)5L;
<2> Map m = new HashMap();
<3> HashMap hm = (HashMap)m;
----
+
<1> declare `int i`;
    explicit cast `long 5` to `int 5` -> `int 5`;
    assign `int 5` to `i`
<2> declare `Map m`;
    allocate `HashMap` instance -> `HashMap reference`;
    implicit cast `HashMap reference` to `Map reference` -> `Map reference`;
    assign `Map reference` to `m`
<3> declare `HashMap hm`;
    access `m` -> `Map reference`;
    explicit cast `Map reference` to `HashMap reference` -> `HashMap reference`;
    assign `HashMap reference` to `hm`

[[numeric-type-casting]]
==== Numeric Type Casting

A <<primitive-types, numeric type>> cast converts the value of an original
numeric type to the equivalent value of a target numeric type. A cast between
two numeric type values results in data loss when the value of the original
numeric type is larger than the target numeric type can accommodate. A cast
between an integer type value and a floating point type value can result in
precision loss.

The allowed casts for values of each numeric type are shown as a row in the
following table:

|====
|        | byte     | short    | char     | int      | long     | float    | double
| byte   |          | implicit | implicit | implicit | implicit | implicit | implicit
| short  | explicit |          | explicit | implicit | implicit | implicit | implicit
| char   | explicit | explicit |          | implicit | implicit | implicit | implicit
| int    | explicit | explicit | explicit |          | implicit | implicit | implicit
| long   | explicit | explicit | explicit | explicit |          | implicit | implicit
| float  | explicit | explicit | explicit | explicit | explicit |          | implicit
| double | explicit | explicit | explicit | explicit | explicit | explicit |
|====

*Examples*

* Valid numeric type casts.
+
[source,Painless]
----
<1> int a = 1;
<2> long b = a;
<3> short c = (short)b;
<4> double e = (double)a;
----
+
<1> declare `int a`;
    assign `int 1` to `a`
<2> declare `long b`;
    access `a` -> `int 1`;
    implicit cast `int 1` to `long 1` -> `long 1`;
    assign `long 1` to `b`
<3> declare `short c`;
    access `b` -> `long 1`;
    explicit cast `long 1` to `short 1` -> `short 1`;
    assign `short 1` value to `c`
<4> declare `double e`;
    access `a` -> `int 1`;
    explicit cast `int 1` to `double 1.0`;
    assign `double 1.0` to `e`;
    (note the explicit cast is extraneous since an implicit cast is valid)
+
* Invalid numeric type casts resulting in errors.
+
[source,Painless]
----
<1> int a = 1.0; // error
<2> int b = 2;
<3> byte c = b;  // error
----
+
<1> declare `int i`;
    *error* -> cannot implicit cast `double 1.0` to `int 1`;
    (note an explicit cast is valid)
<2> declare `int b`;
    assign `int 2` to `b`
<3> declare byte `c`;
    access `b` -> `int 2`;
    *error* -> cannot implicit cast `int 2` to `byte 2`;
    (note an explicit cast is valid)

[[reference-type-casting]]
==== Reference Type Casting

A <<reference-types, reference type>> cast converts the value of an original
reference type to the equivalent value of a target reference type. An implicit
cast between two reference type values is allowed when the original reference
type is a descendant of the target type. An explicit cast between two reference
type values is allowed when the original type is a descendant of the target type
or the target type is a descendant of the original type.

*Examples*

* Valid reference type casts.
+
[source,Painless]
----
<1> List x;
<2> ArrayList y = new ArrayList();
<3> x = y;
<4> y = (ArrayList)x;
<5> x = (List)y;
----
+
<1> declare `List x`;
    assign default value `null` to `x`
<2> declare `ArrayList y`;
    allocate `ArrayList` instance -> `ArrayList reference`;
    assign `ArrayList reference` to `y`;
<3> access `y` -> `ArrayList reference`;
    implicit cast `ArrayList reference` to `List reference` -> `List reference`;
    assign `List reference` to `x`;
    (note `ArrayList` is a descendant of `List`)
<4> access `x` -> `List reference`;
    explicit cast `List reference` to `ArrayList reference`
            -> `ArrayList reference`;
    assign `ArrayList reference` to `y`;
<5> access `y` -> `ArrayList reference`;
    explicit cast `ArrayList reference` to `List reference` -> `List reference`;
    assign `List reference` to `x`;
    (note the explicit cast is extraneous, and an implicit cast is valid)
+
* Invalid reference type casts resulting in errors.
+
[source,Painless]
----
<1> List x = new ArrayList();
<2> ArrayList y = x;          // error
<3> Map m = (Map)x;           // error
----
+
<1> declare `List x`;
    allocate `ArrayList` instance -> `ArrayList reference`;
    implicit cast `ArrayList reference` to `List reference` -> `List reference`;
    assign `List reference` to `x`
<2> declare `ArrayList y`;
    access `x` -> `List reference`;
    *error* -> cannot implicit cast `List reference` to `ArrayList reference`;
    (note an explicit cast is valid since `ArrayList` is a descendant of `List`)
<3> declare `ArrayList y`;
    access `x` -> `List reference`;
    *error* -> cannot explicit cast `List reference` to `Map reference`;
    (note no cast would be valid since neither `List` nor `Map` is a descendant
            of the other)

[[dynamic-type-casting]]
==== Dynamic Type Casting

A <<dynamic-types, dynamic (`def`) type>> cast converts the value of an original
`def` type to the equivalent value of any target type or converts the value of
any original type to the equivalent value of a target `def` type.

An implicit cast from any original type value to a `def` type value is always
allowed. An explicit cast from any original type value to a `def` type value is
always allowed but never necessary.

An implicit or explicit cast from an original `def` type value to
any target type value is allowed if and only if the cast is normally allowed
based on the current type value the `def` type value represents.

*Examples*

* Valid dynamic type casts with any original type to a target `def` type.
+
[source,Painless]
----
<1> def d0 = 3;
<2> d0 = new ArrayList();
<3> Object o = new HashMap();
<4> def d1 = o;
<5> int i = d1.size();
----
+
<1> declare `def d0`;
    implicit cast `int 3` to `def`;
    assign `int 3` to `d0`
<2> allocate `ArrayList` instance -> `ArrayList reference`;
    implicit cast `ArrayList reference` to `def` -> `def`;
    assign `def` to `d0`
<3> declare `Object o`;
    allocate `HashMap` instance -> `HashMap reference`;
    implicit cast `HashMap reference` to `Object reference`
            -> `Object reference`;
    assign `Object reference` to `o`
<4> declare `def d1`;
    access `o` -> `Object reference`;
    implicit cast `Object reference` to `def` -> `def`;
    assign `def` to `d1`
<5> declare `int i`;
    access `d1` -> `def`;
    implicit cast `def` to `HashMap reference` -> HashMap reference`;
    call `size` on `HashMap reference` -> `int 0`;
    assign `int 0` to `i`;
    (note `def` was implicit cast to `HashMap reference` since `HashMap` is the
            child-most descendant type value that the `def` type value
            represents)
+
* Valid dynamic type casts with an original `def` type to any target type.
+
[source,Painless]
----
<1> def d = 1.0;
<2> int i = (int)d;
<3> d = 1;
<4> float f = d;
<5> d = new ArrayList();
<6> List l = d;
----
+
<1> declare `def d`;
    implicit cast `double 1.0` to `def` -> `def`;
    assign `def` to `d`
<2> declare `int i`;
    access `d` -> `def`;
    implicit cast `def` to `double 1.0` -> `double 1.0`;
    explicit cast `double 1.0` to `int 1` -> `int 1`;
    assign `int 1` to `i`;
    (note the explicit cast is necessary since a `double` value cannot be
     converted to an `int` value implicitly)
<3> assign `int 1` to `d`;
    (note the switch in the type `d` represents from `double` to `int`)
<4> declare `float i`;
    access `d` -> `def`;
    implicit cast `def` to `int 1` -> `int 1`;
    implicit cast `int 1` to `float 1.0` -> `float 1.0`;
    assign `float 1.0` to `f`
<5> allocate `ArrayList` instance -> `ArrayList reference`;
    assign `ArrayList reference` to `d`;
    (note the switch in the type `d` represents from `int` to `ArrayList`)
<6> declare `List l`;
    access `d` -> `def`;
    implicit cast `def` to `ArrayList reference` -> `ArrayList reference`;
    implicit cast `ArrayList reference` to `List reference` -> `List reference`;
    assign `List reference` to `l`
+
* Invalid dynamic type casts resulting in errors.
+
[source,Painless]
----
<1> def d = 1;
<2> short s = d;       // error
<3> d = new HashMap();
<4> List l = d;        // error
----
<1> declare `def d`;
    implicit cast `int 1` to `def` -> `def`;
    assign `def` to `d`
<2> declare `short s`;
    access `d` -> `def`;
    implicit cast `def` to `int 1` -> `int 1`;
    *error* -> cannot implicit cast `int 1` to `short 1`;
    (note an explicit cast is valid)
<3> allocate `HashMap` instance -> `HashMap reference`;
    implicit cast `HashMap reference` to `def` -> `def`;
    assign `def` to `d`
<4> declare `List l`;
    access `d` -> `def`;
    implicit cast `def` to `HashMap reference`;
    *error* -> cannot implicit cast `HashMap reference` to `List reference`;
    (note no cast would be valid since neither `HashMap` nor `List` is a
            descendant of the other)

[[string-character-casting]]
==== String to Character Casting

Use the *cast operator* to convert a <<string-type, `String` type>> value into a
<<primitive-types, `char` type>> value.

*Errors*

* If the `String` type value isn't one character in length.
* If the `String` type value is `null`.

*Examples*

* Casting string literals into `char` type values.
+
[source,Painless]
----
<1> char c = (char)"C"
<2> c = (char)'c'
----
+
<1> declare `char c`;
    explicit cast `String "C"` to `char C` -> `char C`;
    assign `char C` to `c`
<2> explicit cast `String 'c'` to `char c` -> `char c`;
    assign `char c` to `c`
+
* Casting a `String` reference into a `char` value.
+
[source,Painless]
----
<1> String s = "s";
<2> char c = (char)s;
----
<1> declare `String s`;
    assign `String "s"` to `s`;
<2> declare `char c`
    access `s` -> `String "s"`;
    explicit cast `String "s"` to `char s` -> `char s`;
    assign `char s` to `c`

[[boxing-unboxing]]
==== Boxing and Unboxing

Boxing is a special type of cast used to convert a primitive type to its
corresponding reference type. Unboxing is the reverse used to convert a
reference type to its corresponding primitive type.

Implicit boxing/unboxing occurs during the following operations:

* Conversions between a `def` type and a primitive type will be implicitly
  boxed/unboxed as necessary, though this is referred to as an implicit cast
  throughout the documentation.
* Method/function call arguments will be implicitly boxed/unboxed as necessary.
* A primitive type value will be implicitly boxed when a reference type method
  call is invoked on it.

Explicit boxing/unboxing is not allowed. Use the reference type API to
explicitly convert a primitive type value to its respective reference type
value and vice versa.

*Errors*

* If an explicit cast is made to box/unbox a primitive type.

*Examples*

* Uses of implicit boxing/unboxing.
+
[source,Painless]
----
<1> List l = new ArrayList();
<2> l.add(1);
<3> Integer I = Integer.valueOf(0);
<4> int i = l.get(i);
----
+
<1> declare `List l`;
    allocate `ArrayList` instance -> `ArrayList reference`;
    assign `ArrayList reference` to `l`;
<2> access `l` -> `List reference`;
    implicit cast `int 1` to `def` -> `def`;
    call `add` on `List reference` with arguments (`def`);
    (note internally `int 1` is boxed to `Integer 1` to store as a `def` type
            value)
<3> declare `Integer I`;
    call `valueOf` on `Integer` with arguments of (`int 0`) -> `Integer 0`;
    assign `Integer 0` to `I`;
<4> declare `int i`;
    access `I` -> `Integer 0`;
    unbox `Integer 0` -> `int 0`;
    access `l` -> `List reference`;
    call `get` on `List reference` with arguments (`int 0`) -> `def`;
    implicit cast `def` to `int 1` -> `int 1`;
    assign `int 1` to `i`;
    (note internally `int 1` is unboxed from `Integer 1` when loaded from a
            `def` type value)
+
* Uses of invalid boxing/unboxing resulting in errors.
+
[source,Painless]
----
<1> Integer x = 1;                   // error
<2> Integer y = (Integer)1;          // error
<3> int a = Integer.valueOf(1);      // error
<4> int b = (int)Integer.valueOf(1); // error
----
+
<1> declare `Integer x`;
    *error* -> cannot implicit box `int 1` to `Integer 1` during assignment
<2> declare `Integer y`;
    *error* -> cannot explicit box `int 1` to `Integer 1` during assignment
<3> declare `int a`;
    call `valueOf` on `Integer` with arguments of (`int 1`) -> `Integer 1`;
    *error* -> cannot implicit unbox `Integer 1` to `int 1` during assignment
<4> declare `int a`;
    call `valueOf` on `Integer` with arguments of (`int 1`) -> `Integer 1`;
    *error* -> cannot explicit unbox `Integer 1` to `int 1` during assignment

[[promotion]]
==== Promotion

Promotion is when a single value is implicitly cast to a certain type or
multiple values are implicitly cast to the same type as required for evaluation
by certain operations. Each operation that requires promotion has a promotion
table that shows all required implicit casts based on the type(s) of value(s). A
value can be promoted to a `def` type at compile-time; however, the promoted
type value is derived from what the `def` type value represents at run-time.

*Errors*

* If a specific operation cannot find an allowed promotion type for the type(s)
  of value(s) given.

*Examples*

* Uses of promotion.
+
[source,Painless]
----
<1> double d = 2 + 2.0;
<2> def x = 1;
<3> float f = x + 2.0F;
----
<1> declare `double d`;
    promote `int 2` and `double 2.0 @0` -> `double 2.0 @0`;
    implicit cast `int 2` to `double 2.0 @1` -> `double 2.0 @1`;
    add `double 2.0 @1` and `double 2.0 @0` -> `double 4.0`;
    assign `double 4.0` to `d`
<2> declare `def x`;
    implicit cast `int 1` to `def` -> `def`;
    assign `def` to `x`;
<3> declare `float f`;
    access `x` -> `def`;
    implicit cast `def` to `int 1` -> `int 1`;
    promote `int 1` and `float 2.0` -> `float 2.0`;
    implicit cast `int 1` to `float 1.0` -> `float `1.0`;
    add `float 1.0` and `float 2.0` -> `float 3.0`;
    assign `float 3.0` to `f`;
    (note this example illustrates promotion done at run-time as promotion
            done at compile-time would have resolved to a `def` type value)
