Type Compatibility

Basic Datatypes Compatibility

Basic data types are inherently compatible from largest to smallest. Meaning the larger type is usually compatible with the smaller one. The other way around does require type casting, the reason for that is to guarentee safety and developer awareness of potential data loss. Here is a table of basic types compatibility:

FromToWith Casting
u8u16, u32, u64, f32, f64No
i8i16, i32, i64, f32, f64No
u16u32, u64, f32, f64No
i16i32, i64, f32, f64No
u32u64, f32, f64No
i32i64, f32, f64No
u64f64No
i64f64No
f32f64No
boolu8, i8, u16, i16, u32, i32, u64, i64, f32, f64Yes
i8, i16, i32, i64u8, u16, u32, u64Yes
u8, u16, u32, u64i8, i16, i32, i64Yes

Ideally, developers would write code where data types are inherently compatible. However, that is not always the case and sometimes it is required to force cast some types into others. For instance abs(x) would take a signed number but always returns non-signed number.

Class - Interface Compatibility

Similar to C++ and Java, inheritance allows you easily go down the hierarchy, but not up. Meaning, a child class is always compatible with its parent class, but not the other way around. This is because the child class has all the properties of the parent class, but not the other way around. Here is an example:

Hence in such cases, we will need to up-cast the object to the desired type. This is done using the \lstinline|as| keyword, which is discussed later.

Class-Class compatibility

Two classes are compatible if they they have the exact same attributes and methods. This check is performed by the compiler using type-signatures. Meaning, classes are not compatible if they have simply compatible types.

Struct Compatibility

As mentioned previously, structs whose field names are the same, are inherently compatible. The conditions are:

  • Field names: The field names must be the same.
  • Field types: The field types must be inherently compatible.

Let's review an example:

The order of the fields doesn't matter, as long as the field names are the same. However, if the field names are different, then the structs are not compatible. Now let's make a small change to our previous example:

In our new example, the field age has different type in each struct. u32 and i32 are not inherently compatible in our direction, we cannot cast Employee.age: i32 to Person.age: u32

Enum Compatibility:

Both enum types must have the same field names, matching same order and same assigned values.

Variant Compatibility:

Both variant types must have the constructors, with the compatible arguments and same order.

Functions

Functions are compatible if they have the same signature. The signature of a function is defined by its name, return type and argument types.


Kudos! Keep reading!