Skip to main content

Type Inference

Swirl implements type-inference to allow avoiding explicit declaration of types where possible and reduce verbosity.

Bound Type​

The compiler's type-inference and correctness checks depend on this concept. The 'bound type' of a context is the currently expected type that an expression which belongs to that context, must be implicitly convertible to. For example:

let global: i32 = <expr_1>;

fn a_function(): i64 {
return <expr_2>;
}

the first context is a variable which is explicitly declared to be an i32, hence that is its bound type. <expr_1> must therefore be a value whose type is compatible with i32. Similarly, <expr_2> is in the context of a function's return, since the function's return type is explicitly declared, the bound type in that context is <i64> (Note: the angular brackets <> are just placeholders to convey that the expression is arbitrary, they are not supposed to have any syntactical role here).

Without Bound Types​

In the absence of bound types, the type inference system kicks in again, the following "axioms" are used to serve as the basis of inference:

ValueAssume as type
String literalstr
Integer literali32
Float literalf64
Random identifierthe type of that identifier

How are discrepancies resolved among sub-expression types? In that case the compiler chooses a type such that there's no implicit data-loss, if this is not possible, the compiler will report an error and ask the programmer to either do an explicit type conversion (via the <expr> as <type> operator), or reconsider their life choices.

Stay informed​