Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 18 additions & 7 deletions resources/type-system/inference.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ Status: Draft

## CHANGELOG

2026.07.09
- Remove a spurious `Null` from the element type inferred for a generator
function literal when the end of the body is reachable.

2024.12.17
- Change the function literal return type inference rules to ignore
`return;` statements in generators (it doesn't actually cause null to be
Expand Down Expand Up @@ -318,13 +322,20 @@ inferred type of the expression body, using the local type inference algorithm
described below with a typing context as computed above.

The actual returned type of a function literal with a block body is computed as
follows. Let `T` be `Never` if every control path through the block exits the
block without reaching the end of the block, as computed by the **definite
completion** analysis specified elsewhere. Let `T` be `Null` if any control
path reaches the end of the block without exiting the block, as computed by the
**definite completion** analysis specified elsewhere. Let `K` be the typing
context for the function body as computed above from the imposed return type
schema.
follows.

- When the function literal is a generator, let `T` be `Never`.
- When the function literal is not a generator:
- Let `T` be `Never` if every control path through the block exits the
block without reaching the end of the block, as computed by the
**definite completion** analysis specified elsewhere.
- Let `T` be `Null` if any control path reaches the end of the block
without exiting the block, as computed by the **definite completion**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is "without exiting the block" redundant? Or just confusing?
If control reaches the end, then it definitely didn't exit before that.
On the other hand, it will exit as the very next thing, so does it really "reach then end of the block without exiting" when it "reaches the block and exits"?

analysis specified elsewhere.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(You can probably guess I'd prefer that case to have type void 😁 . Not returning something is not the same as returning null. It's the same as not returning anything useful. Alas, not where we are today.)


Let `K` be the typing context for the function body as computed above from the
imposed return type schema.

- For each `return e;` statement in the block, let `S` be the inferred type of
`e`, using the local type inference algorithm described below with typing
context `K`, and update `T` to be `UP(flatten(S), T)` if the enclosing
Expand Down