Skip to content

Commit f9c9aa3

Browse files
authored
Adjust function literal return type inference to avoid spurious null (#4210)
This PR changes one item in the list of actions taken during function literal return type inference: A `return;` statement only adds `Null` to the return type in cases where the given function literal is a non-generator. Before this change, `Null` was added to the return type also in cases like `() sync* { yield 1; return; }` such that this function literal gets the inferred return type `Iterable<int?>`. This is an unnecessary loss of typing precision because null is never actually added to the returned iterable. With this update, the inferred return type is `Iterable<int>`. See dart-lang/sdk#59669 for some background discussion.
1 parent e76334e commit f9c9aa3

File tree

1 file changed

+12
-1
lines changed

1 file changed

+12
-1
lines changed

resources/type-system/inference.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ Status: Draft
66

77
## CHANGELOG
88

9+
2024.12.17
10+
- Change the function literal return type inference rules to ignore
11+
`return;` statements in generators (it doesn't actually cause null to be
12+
returned).
13+
914
2022.05.12
1015
- Define the notions of "constraint solution for a set of type variables" and
1116
"Grounded constraint solution for a set of type variables". These
@@ -324,7 +329,8 @@ schema.
324329
`e`, using the local type inference algorithm described below with typing
325330
context `K`, and update `T` to be `UP(flatten(S), T)` if the enclosing
326331
function is `async`, or `UP(S, T)` otherwise.
327-
- For each `return;` statement in the block, update `T` to be `UP(Null, T)`.
332+
- If the enclosing function is not marked `sync*` or `async*`: For each
333+
`return;` statement in the block, update `T` to be `UP(Null, T)`.
328334
- For each `yield e;` statement in the block, let `S` be the inferred type of
329335
`e`, using the local type inference algorithm described below with typing
330336
context `K`, and update `T` to be `UP(S, T)`.
@@ -339,6 +345,11 @@ schema.
339345
`Stream<K>`; let `E` be the type such that `Stream<E>` is a super-interface
340346
of `S`; and update `T` to be `UP(E, T)`.
341347

348+
In these rules, 'in the block' refers to return and yield statements that
349+
will complete the execution of the function literal under inference, not
350+
the ones, if any, that will complete the execution of a nested function
351+
body.
352+
342353
The **actual returned type** of the function literal is the value of `T` after
343354
all `return` and `yield` statements in the block body have been considered.
344355

0 commit comments

Comments
 (0)