It is now an error to have void foo() { return 42; }

The language team several times agreed to make it an error when a
non-void expression `e` is used in `return e;` in the body of a
function whose return type is `void`.

When `void` is changed from a near-bottom type to a top type, the
wording in the language specification (dartLangSpec.tex) does _not_
ensure that this is an error, because all types are assignable to
`void`, so we need a specific rule saying that it is an error.

This CL adds such a rule to the feature spec for generalized void.
It also adds a rule that makes it an error to have return type `void`
in a function marked `async*` or `sync*`, based on the reasoning
that they "are returning a Future/Stream/Iterable semantically",
and it would now be an error if they did that explicitly.

Change-Id: I22fed9e9fc6097bb50100a151b964045e41ef173
Reviewed-on: https://dart-review.googlesource.com/35680
Reviewed-by: Leaf Petersen <leafp@google.com>
Commit-Queue: Erik Ernst <eernst@google.com>
This commit is contained in:
Erik Ernst
2018-02-14 11:15:12 +00:00
committed by commit-bot@chromium.org
parent 90f3a603cd
commit 9f9987f709
@@ -287,6 +287,31 @@ hence ignored), except when explicitly subjected to a type cast. This
open for the cases where the developer knows that the typing misrepresents
the actual situation.*
We define void equivalent types inductively as follows: A type `T` is
_void equivalent_ if `T` is `void` or `T` is a type of the form
`FutureOr<S>` where `S` is a void equivalent type.
*The subtype rules for `FutureOr` ensure that whenever `T` is a void
equivalent type we can show `T <: void` and `void <: T`. In that sense we
may consider void equivalent types to be "the same type". However, we will
not necessarily treat them identically for all purposes. For instance,
it is useful to be able to test `if (x is Future<void>) ..` in the case
where `x` is a variable of type `FutureOr<void>`, but that is not allowed
when `x` has type `void`.*
It is a static warning (in Dart 2: a compile-time error) if a return
statement `return e;` occurs such that the innermost enclosing function
has return type `void` and the static type of `e` is not a void equivalent
type.
It is a static warning (in Dart 2: a compile-time error) if a function
marked `async*`, or `sync*` has return type `void`.
*Note that it is allowed for an `async` function to have return type
`void`. This serves to indicate that said function performs a
"fire-and-forget" operation, that is, it is not even useful for the caller
to synchronize with the completion of that task.*
During bounds checking, it is possible that a bound of a formal type
parameter of a generic class or function is statically known to be the type
void. In this case, the bound is considered to be the built-in class