semicolon_separator: ; between expressions

March separates the expressions of a block with newlines; ; is not part of the language at all, so the lexer stops at it. The fix replaces the ; (and the blanks after it) with a line break at the current indentation, or deletes a ; that ends its line.

A program that triggers it

mod Main do
  needs IO.Console
  fn total() : Int do
    let x = 1; let y = 2
    x + y
  end

  fn main(_console : Cap(IO.Console)) do
    println(int_to_string(total()))
  end
end

The fix

Put each expression on its own line.

mod Main do
  needs IO.Console
  fn total() : Int do
    let x = 1
    let y = 2
    x + y
  end

  fn main(_console : Cap(IO.Console)) do
    println(int_to_string(total()))
  end
end

Why the rule exists

Block structure comes from do … end and line breaks, so a block never needs a terminator and the grammar has no sequencing operator. ; is caught in the lexer, at the character, because it would otherwise surface as an unhelpful “unexpected character”.

See also: the language reference.

See it in the error tour