Add informal spec for invalid returns.

This mostly documents and regularizes existing (post bug fix) semantics,
with a small additional restriction on returning `void` from an async
function.

Change-Id: Ic1a302aeb666fa73ca2b7e23072394490bb4fe76
Reviewed-on: https://dart-review.googlesource.com/60401
Reviewed-by: Lasse R.H. Nielsen <lrn@google.com>
This commit is contained in:
Leaf Petersen 2018-07-26 22:07:14 +00:00
parent 1336802dee
commit 02ba125a14

View file

@ -0,0 +1,124 @@
# Dart 2 function return checking
leafp@google.com
**Note: Also see alternative presentation at the bottom for a dual presentation
of these rules in terms of which things are errors, rather than which things are
valid*.*
## Errors for sync and async function return values in Dart 2
### Expression bodied functions
An asynchronous expression bodied function with return type `T` and return
expression `e` has a valid return if:
* `flatten(T)` is `void`
* or `return exp;` is a valid return for an equivalent block bodied function
with return type `T` as defined below.
A synchronous expression bodied function with return type `T` and return expression
`e` has a valid return if:
* `T` is `void`
* or `return exp;` is a valid return for an equivalent block bodied function
with return type `T` as defined below.
### Block bodied functions
#### Synchronous functions
The rules for a synchronous non-generator function with declared return type `T`
are:
* `return;` is a valid return if any of the following are true:
* `T` is `void`
* `T` is `dynamic`
* `T` is `Null`.
* `return exp;` where `exp` has static type `S` is a valid return if:
* `S` is `void`
* and `T` is `void` or `dynamic` or `Null`
* `return exp;` where `exp` has static type `S` is a valid return if:
* `T` is `void`
* and `S` is `void` or `dynamic` or `Null`
* `return exp;` where `exp` has static type `S` is a valid return if:
* `T` is not `void`
* and `S` is not `void`
* and `S` is assignable to `T`
#### Asynchronous functions
The rules for an asynchronous non-generator function with declared return type
`T` are:
* `return;` is a valid return if any of the following are true:
* `flatten(T)` is `void`
* `flatten(T)` is `dynamic`
* `flatten(T)` is `Null`.
* `return exp;` where `exp` has static type `S` is a valid return if:
* `flatten(S)` is `void`
* and `flatten(T)` is `void`, `dynamic` or `Null`
* `return exp;` where `exp` has static type `S` is a valid return if:
* `flatten(T)` is `void`
* and `flatten(S)` is `void`, `dynamic` or `Null`
* `return exp;` where `exp` has static type `S` is a valid return if:
* `flatten(T)` is not `void`
* and `flatten(S)` is not `void`
* and `Future<flatten(S)>` is assignable to `T`
## Errors for sync and async function return values in Dart 2: Alternative presentation in terms of which things *are* errors
### Expression bodied functions
It is an error if an asynchronous expression bodied function with return type `T`
has return expression `exp` and both:
* `flatten(T)` is not `void`
* `return exp;` would be an error in an equivalent block bodied function
with return type `T` as defined below.
It is an error if a synchronous expression bodied function with return type `T`
has return expression `exp` and both:
* `T` is not `void`
* `return exp;` would be an error in an equivalent block bodied function
with return type `T` as defined below.
### Block bodied functions
#### Synchronous functions
The rules for a synchronous non-generator function with declared return type `T`
are:
* `return;` is an error if `T` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `T` is `void` and
`S` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `S` is `void` and
`T` is not `void`, or `dynamic` or `Null`.
* `return exp;` where `exp` has static type `S` is an error if `S` is not
assignable to `T`.
#### Asynchronous functions
The rules for an asynchronous non-generator function with declared return type
`T` are:
* `return;` is an error if `flatten(T)` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `flatten(T)` is
`void` and `flatten(S)` is not `void`, `dynamic`, or `Null`
* `return exp;` where `exp` has static type `S` is an error if `flatten(S)` is
`void` and `flatten(T)` is not `void`, `dynamic`, or `Null`.
* `return exp;` where `exp` has static type `S` is an error if
`Future<flatten(S)>` is not assignable to `T`.