@@ -6,6 +6,11 @@ Status: Draft
66
77## CHANGELOG
88
9+ 2023.06.15
10+ - Adjust function literal return type inference to avoid spurious application
11+ of ` flatten ` , and make sure return statements do not affect generator
12+ functions.
13+
9142022.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
@@ -286,9 +291,9 @@ type schema `S` as follows:
286291 ` Stream<S1> ` for some ` S1 ` , then the context type is ` S1 ` .
287292 - If the function expression is declared ` sync* ` and ` S ` is of the form
288293 ` Iterable<S1> ` for some ` S1 ` , then the context type is ` S1 ` .
289- - Otherwise, without null safety, the context type is ` FutureOr< flatten(T)> `
294+ - Otherwise, without null safety, the context type is ` flatten(T) `
290295 where ` T ` is the imposed return type schema; with null safety, the context
291- type is ` FutureOr< futureValueTypeSchema(S)> ` .
296+ type is ` futureValueTypeSchema(S) ` .
292297
293298The function ** futureValueTypeSchema** is defined as follows:
294299
@@ -299,7 +304,7 @@ The function **futureValueTypeSchema** is defined as follows:
299304- ** futureValueTypeSchema** (` void ` ) = ` void ` .
300305- ** futureValueTypeSchema** (` dynamic ` ) = ` dynamic ` .
301306- ** futureValueTypeSchema** (` _ ` ) = ` _ ` .
302- - Otherwise, for all ` S ` , ** futureValueTypeSchema** (` S ` ) = ` Object? ` .
307+ - Otherwise, for all other ` S ` , ** futureValueTypeSchema** (` S ` ) = ` Object? ` .
303308
304309_ Note that it is a compile-time error unless the return type of an asynchronous
305310non-generator function is a supertype of ` Future<Never> ` , which means that
@@ -315,45 +320,60 @@ described below with a typing context as computed above.
315320The actual returned type of a function literal with a block body is computed as
316321follows. Let ` T ` be ` Never ` if every control path through the block exits the
317322block without reaching the end of the block, as computed by the ** definite
318- completion** analysis specified elsewhere. Let ` T ` be ` Null ` if any control
323+ completion** analysis specified elsewhere, or if the function is a generator
324+ function.
325+ Let ` T ` be ` Null ` if the function is a non-generator function and any control
319326path reaches the end of the block without exiting the block, as computed by the
320327** definite completion** analysis specified elsewhere. Let ` K ` be the typing
321328context for the function body as computed above from the imposed return type
322329schema.
323- - For each ` return e; ` statement in the block, let ` S ` be the inferred type of
324- ` e ` , using the local type inference algorithm described below with typing
325- context ` K ` , and update ` T ` to be ` UP(flatten(S), T) ` if the enclosing
326- function is ` async ` , or ` UP(S, T) ` otherwise.
327- - For each ` return; ` statement in the block, update ` T ` to be ` UP(Null, T) ` .
330+ - If the enclosing function is a non-` async ` non-generator function,
331+ for each ` return e; ` statement in the block, let ` S ` be the inferred type
332+ of ` e ` , using the local type inference algorithm described below with typing
333+ context ` K ` , and update ` T ` to be ` UP(S, T) ` .
334+ - If the enclosing function is marekd ` async ` , for each ` return e; ` statement
335+ in the block, let ` S ` be the inferred type of ` e ` , using the local type
336+ inference algorithm described below with typing context ` FutureOr<K> ` ,
337+ and update ` T ` to be ` UP(flatten(S), T) ` .
338+ - If the enclosing function is a non-generator function, for each ` return; `
339+ statement in the block, update ` T ` to be ` UP(Null, T) ` .
328340 - For each ` yield e; ` statement in the block, let ` S ` be the inferred type of
329341 ` e ` , using the local type inference algorithm described below with typing
330342 context ` K ` , and update ` T ` to be ` UP(S, T) ` .
331343 - If the enclosing function is marked ` sync* ` , then for each ` yield* e; `
332344 statement in the block, let ` S ` be the inferred type of ` e ` , using the
333345 local type inference algorithm described below with a typing context of
334- ` Iterable<K> ` ; let ` E ` be the type such that ` Iterable<E> ` is a
335- super-interface of ` S ` ; and update ` T ` to be ` UP(E, T) ` .
346+ ` Iterable<K> ` . If there exists a type ` E ` such that ` Iterable<E> ` is a
347+ super-interface of ` S ` , update ` T ` to be ` UP(E, T) ` . Otherwise update
348+ ` T ` to be ` UP(S, T) ` .
349+ _ It is a compile-time error if * S* is not a assignable to
350+ ` Iterable<Object?> ` , so either * S* implements ` Iterable ` , or it is one of
351+ ` dynamic ` or ` Never ` ._
336352 - If the enclosing function is marked ` async* ` , then for each ` yield* e; `
337353 statement in the block, let ` S ` be the inferred type of ` e ` , using the
338354 local type inference algorithm described below with a typing context of
339- ` Stream<K> ` ; let ` E ` be the type such that ` Stream<E> ` is a super-interface
340- of ` S ` ; and update ` T ` to be ` UP(E, T) ` .
355+ ` Stream<K> ` . If there exists a type ` E ` such that ` Stream<E> ` is a
356+ super-interface of ` S ` , update ` T ` to be ` UP(E, T) ` . Otherwise update
357+ ` T ` to be ` UP(S, T) ` .
358+ _ It is a compile-time error if * S* is not a assignable to
359+ ` Stream<Object?> ` , so either * S* implements ` Iterable ` , or it is one of
360+ ` dynamic ` or ` Never ` ._
341361
342362The ** actual returned type** of the function literal is the value of ` T ` after
343363all ` return ` and ` yield ` statements in the block body have been considered.
344364
345365Let ` T ` be the ** actual returned type** of a function literal as computed above.
346366Let ` R ` be the greatest closure of the typing context ` K ` as computed above.
347367
348- With null safety: if ` R ` is ` void ` , or the function literal is marked ` async `
349- and ` R ` is ` FutureOr<void> ` , let ` S ` be ` void ` (without null-safety: no special
350- treatment is applicable to ` void ` ).
368+ With null safety, if ` R ` is ` void ` , let ` S ` be ` void `
369+ _ (without null-safety: no special treatment is applicable to ` void ` )_ .
351370
352- Otherwise, if ` T <: R ` then let ` S ` be ` T ` . Otherwise, let ` S ` be ` R ` . The
371+ Otherwise (_ without null safety or if ` R ` is not ` void ` _ ),
372+ if ` T <: R ` then let ` S ` be ` T ` . Otherwise, let ` S ` be ` R ` . The
353373inferred return type of the function literal is then defined as follows:
354374
355375 - If the function literal is marked ` async ` then the inferred return type is
356- ` Future<flatten(S) > ` .
376+ ` Future<S > ` .
357377 - If the function literal is marked ` async* ` then the inferred return type is
358378 ` Stream<S> ` .
359379 - If the function literal is marked ` sync* ` then the inferred return type is
0 commit comments