3.1. Resolution in practice
The rest of this section states the typing rules precisely. In everyday use they come down to a short list, and a front end that respects these will rarely be surprised:
-
literals synthesize their primitive type; a local synthesizes its declared type;
-
a field synthesizes its declared type after looking the receiver up by its static type;
-
an assignment checks its right-hand side against the target's type, and yields that type;
-
a declaration extends only the enclosing block's scope;
-
a call checks arguments against the declared inputs and synthesizes the output type;
-
a multi-output call has an internal multi-value type and must be unpacked with
assign; -
an
ifchecks both branches against the expected type when there is one, and otherwise joins the two synthesized branch types; -
a block's last item carries the block's value;
-
loop conditions, invariants, and contract clauses check against
bool; -
arithmetic needs operands of one compatible numeric type — there are no implicit numeric promotions;
-
equality needs consistent operand types;
isandasneed related types; -
return echeckseagainst the sole declared output; -
names and types are pre-registered, so declaration order does not matter.
When a rule fails, resolution substitutes an internal unresolved or Unknown node so that one
mistake does not cascade into a list of derived errors. Compilation stops before any analysis
runs if a real diagnostic remains.