Skip to content

Adjust the initial actual returned type to avoid spurious Null #4718

Description

@eernstg

Thanks to @sgrekhov for bringing up this topic. Consider the following program:

var f1 = () sync* {
  return;
};

var f2 = () sync* {};

The specification in this section implies that the function literal that contains return; has a return type of Iterable<Never>. This makes sense because the returned iterable is empty, which means that it is safe to claim that every returned object has whichever type you want.

The reason why the return is Iterable<Never> rather than Iterable<Null> is that PR #4210 disabled the action taken when a return; is encountered: With that PR, the actual returned type is not updated to include Null when the function is a generator. This is working correctly because return; in a sync* body doesn't actually add a null to the returned iterable. Similarly for async* generators and Stream.

However, the rules imply that the second function literal — the one that does not contain a return; statement — has a return type of Iterable<Null> for sync* and Stream<Null> for async*.

The culprit is that the initial value of the 'actual returned value' is chosen to be Null in the case where the end of the function body is reachable. This is suboptimal in the case of generators for the same reason as the one in #4210. Hence, we should change the relevant sentence as follows. This is the wording that we currently have:

The actual returned type of a function literal with a block body is computed as follows. Let T be Never ...

We can change it as follows:

The actual returned type of a function literal with a block body is computed as follows. If the function literal is a generator then let T be Never. Otherwise, let T be Never ...

@dart-lang/language-team, WDYT? Does it need breaking change processing, or can we just go ahead and fix it?

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThere is a mistake in the language specification or in an active documentspecification

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions