Section 5.2

Every path must return

A method that announces a return type must honour it everywhere, and the three ways to forget a path.

A method that declares a return type must return a value on every one of its paths. No exception.

@entry(start)
object MyProgram {
    start() {
        Console.print(text: self.name(day: 2));
        Console.print(text: self.name(day: 7));
    }

    name(day: int) -> str {
        switch (day) {
            case 1:
                return "Monday";
            case 2:
                return "Tuesday";
            default:
                return "some other day";
        }
    }
}

Three cases, three returns, and the default that answers for everything else. No path leaves the body without having returned something.

What happens if you forget one

Remove the default and its two lines, then run:

error[D012]: 'name' returns 'str', but a path reaches the end of the body
without 'return' or 'throw': it would yield 0, which this language reads as absence

The compiler did not merely note the fact: it says what would follow. With no default, a day of 7 crosses the switch without finding anything, reaches the end of the body, and something would have to be returned.

The three ways to leave a path open

They are all familiar to you, and this is the moment to read them together:

  • an if with no else (section 3.2) — when the condition is false, the body ends;
  • a switch with no default (section 4.4) — when no case matches;
  • a loop whose condition may be false (section 4.1) — if the body runs no times at all, a return placed inside it never leaves.

A return inside one of these three constructions therefore never counts for the whole method. You must always ask what happens when you do not enter it.

throw ends a method as well as return does: a method that finishes by throwing is complete. That keyword is introduced in section 8.

Your turn

  • Remove the default and read the diagnostic in full.
  • Replace the default with a return "some other day"; placed after the switch, outside its braces: the method is complete again, differently.
  • Write isEven(value: int) -> bool with a single if (value % 2 = 0) { return true; } and nothing after it. The refusal lands, and you will know how to read it.