@@ -6,10 +6,12 @@ Status: Draft
6
6
7
7
## CHANGELOG
8
8
9
- 2023.06.15
9
+ 2023.06.24
10
10
- Adjust function literal return type inference to avoid spurious application
11
11
of ` flatten ` , and make sure return statements do not affect generator
12
12
functions.
13
+ - Specify the value context to use for generator functions for more
14
+ non-trivial return types (not just ` Iterable<X> ` for some ` X ` ).
13
15
14
16
2022.05.12
15
17
- Define the notions of "constraint solution for a set of type variables" and
@@ -265,11 +267,11 @@ unlike normal fields, the initializer for a `late` field may reference `this`.
265
267
Function literals which are inferred in an empty typing context (see below) are
266
268
inferred using the declared type for all of their parameters. If a parameter
267
269
has no declared type, it is treated as if it was declared with type ` dynamic ` .
268
- Inference for each returned expression in the body of the function literal is
269
- done in an empty typing context (see below).
270
+ Inference for each returned or yielded expression in the body of the function
271
+ literal is done with an empty _ value context _ scheme (see below).
270
272
271
273
Function literals which are inferred in an non-empty typing context where the
272
- context type is a function type are inferred as described below .
274
+ context type is a function type are inferred as described here .
273
275
274
276
Each parameter is assumed to have its declared type if present. If no type is
275
277
declared for a parameter and there is a corresponding parameter in the context
@@ -281,19 +283,21 @@ corresponding parameter in the context type schema, the variable is treated as
281
283
having type ` dynamic ` .
282
284
283
285
The return type of the context function type is used at several points during
284
- inference. We refer to this type as the ** imposed return type
285
- schema** . Inference for each returned or yielded expression in the body of the
286
- function literal is done using a context type derived from the imposed return
287
- type schema ` S ` as follows:
286
+ inference. We refer to this type as the ** imposed return type schema** .
287
+
288
+ Inference for each returned or yielded expression in the body of the
289
+ function literal is done using a ** value context** type scheme derived from the
290
+ imposed return type schema ` S ` as follows:
291
+ - If function is declared ` async ` , then without null safety,
292
+ the value context scheme is ** flatten** (` S ` );
293
+ with null safety the value context scheme is
294
+ ** futureValueTypeSchema** (` S ` ), as defined below.
295
+ - If the function expression is declared ` async* ` then the value context
296
+ scheme is ** streamElementTypeSchema** (` S ` ), as defined below.
297
+ - If the function expression is declared ` sync* ` then the value context
298
+ scheme is ** iterableElementTypeSchema** (` S ` ), as defined below.
288
299
- If the function expression is neither ` async ` nor a generator, then the
289
- context type is ` S ` .
290
- - If the function expression is declared ` async* ` and ` S ` is of the form
291
- ` Stream<S1> ` for some ` S1 ` , then the context type is ` S1 ` .
292
- - If the function expression is declared ` sync* ` and ` S ` is of the form
293
- ` Iterable<S1> ` for some ` S1 ` , then the context type is ` S1 ` .
294
- - Otherwise, without null safety, the context type is ` flatten(T) `
295
- where ` T ` is the imposed return type schema; with null safety, the context
296
- type is ` futureValueTypeSchema(S) ` .
300
+ value context scheme is ` S ` .
297
301
298
302
The function ** futureValueTypeSchema** is defined as follows:
299
303
@@ -306,70 +310,124 @@ The function **futureValueTypeSchema** is defined as follows:
306
310
- ** futureValueTypeSchema** (` _ ` ) = ` _ ` .
307
311
- Otherwise, for all other ` S ` , ** futureValueTypeSchema** (` S ` ) = ` Object? ` .
308
312
309
- _ Note that it is a compile-time error unless the return type of an asynchronous
310
- non-generator function is a supertype of ` Future<Never> ` , which means that
311
- the last case will only be applied when ` S ` is ` Object ` or a top type._
313
+ The function ** streamElementTypeSchema** is defined as follow:
314
+
315
+ - ** streamElementTypeSchema** (` S? ` ) = ** streamElementTypeSchema** (` S ` ),
316
+ for all ` S ` .
317
+ - ** streamElementTypeSchema** (` S* ` ) = ** streamElementTypeSchema** (` S ` ),
318
+ for all ` S ` .
319
+ - ** streamElementTypeSchema** (` FutureOr<S> ` ) = ** streamElementTypeSchema** (` S ` ),
320
+ for all ` S ` .
321
+ - ** streamElementTypeSchema** (` Stream<S> ` ) = ` S ` , for all ` S ` .
322
+ - ** streamElementTypeSchema** (` void ` ) = ` void `
323
+ - ** streamElementTypeSchema** (` dynamic ` ) = ` dynamic `
324
+ - ** streamElementTypeSchema** (` _ ` ) = ` _ `
325
+ - Otherwise, for all other ` S ` , ** streamElementTypeSchema** (` S ` ) = ` Object? ` .
326
+
327
+ The function ** iterableElementTypeSchema** is defined as follow:
328
+
329
+ - ** iterableElementTypeSchema** (` S? ` ) = ** iterableElementTypeSchema** (` S ` ),
330
+ for all ` S ` .
331
+ - ** iterableElementTypeSchema** (` S* ` ) = ** iterableElementTypeSchema** (` S ` ),
332
+ for all ` S ` .
333
+ - ** iterableElementTypeSchema** (` FutureOr<S> ` ) =
334
+ ** iterableElementTypeSchema** (` S ` ), for all ` S ` .
335
+ - ** iterableElementTypeSchema** (` Iterable<S> ` ) = ` S ` , for all ` S ` .
336
+ - ** iterableElementTypeSchema** (` void ` ) = ` void `
337
+ - ** iterableElementTypeSchema** (` dynamic ` ) = ` dynamic `
338
+ - ** iterableElementTypeSchema** (` _ ` ) = ` _ `
339
+ - Otherwise, for all other ` S ` , ** iterableElementTypeSchema** (` S ` ) = ` Object? ` .
340
+
341
+ _ Note that it is a compile-time error unless the return type of an
342
+ asynchronous non-generator function is a supertype of ` Future<Never> ` ,
343
+ which means that the last case of ** futureValueTypeScheme** will only
344
+ be applied when ` S ` is ` Object ` .
345
+ Similarly for ` async* ` and ` sync* ` functions whose return types
346
+ must be a supertypes of ` Stream<Never> ` and ` Iterable<Never> ` ._
312
347
313
348
In order to infer the return type of a function literal, we first infer the
314
- ** actual returned type** of the function literal.
315
-
316
- The actual returned type of a function literal with an expression body is the
317
- inferred type of the expression body, using the local type inference algorithm
318
- described below with a typing context as computed above.
319
-
320
- The actual returned type of a function literal with a block body is computed as
321
- follows. Let ` T ` be ` Never ` if every control path through the block exits the
322
- block without reaching the end of the block, as computed by the ** definite
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
326
- path reaches the end of the block without exiting the block, as computed by the
327
- ** definite completion** analysis specified elsewhere. Let ` K ` be the typing
328
- context for the function body as computed above from the imposed return type
329
- schema.
349
+ ** actual value type** of the function literal. _ The actual value type
350
+ represents the types of the actual values returned by non-generator functions,
351
+ and the values emitted by generator functions._
352
+
353
+ Let ` K ` be the value context schema for the function body as computed above
354
+ from the imposed return type schema.
355
+ _ When we refer to the _ inferred type_ of an expression with a typing context,
356
+ it is the type inferred using the local type inference algorithm
357
+ described below._
358
+
359
+ The actual value type of a function literal with an expression body, ` => e ` ,
360
+ _ (which cannot be a generator function)_ is computed as follows:
361
+ - If the enclosing function is marked ` async ` ,
362
+ let ` T ` be the inferred type of the returned expession with ` FutureOr<K> `
363
+ as typing context.
364
+ The actual value type is ** flatten** (` T ` ).
365
+ - If the enclosing function is not marked ` async ` , let ` T ` be the inferred
366
+ type of the returned expression with typing context ` K ` .
367
+ The actually value type is ` T ` .
368
+
369
+ The actual value type of a function literal with a block body is computed as
370
+ follows.
371
+ Let ` T ` be ` Never ` if the function is a generator function,
372
+ or if every control path through the block exits the block without
373
+ reaching the end of the block, as computed by the ** definite completion**
374
+ analysis specified elsewhere.
375
+ Otherwise _ (the function is a non-generator function and at least
376
+ one control path reaches the end of the block)_ let ` T ` be ` null ` .
377
+
378
+ Then process relevant statements of the block, one by one in source order,
379
+ to find a value type ` V ` for that statement.
380
+
330
381
- 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) ` .
340
- - For each ` yield e; ` statement in the block, let ` S ` be the inferred type of
341
- ` e ` , using the local type inference algorithm described below with typing
342
- context ` K ` , and update ` T ` to be ` UP(S, T) ` .
343
- - If the enclosing function is marked ` sync* ` , then for each ` yield* e; `
344
- statement in the block, let ` S ` be the inferred type of ` e ` , using the
345
- local type inference algorithm described below with a typing context of
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 ` ._
352
- - If the enclosing function is marked ` async* ` , then for each ` yield* e; `
353
- statement in the block, let ` S ` be the inferred type of ` e ` , using the
354
- local type inference algorithm described below with a typing context of
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 ` ._
361
-
362
- The ** actual returned type** of the function literal is the value of ` T ` after
382
+ the relevant statements are ` return; ` or ` return e; ` statements.
383
+ - For a ` return; ` statement, let ` V ` be ` Null ` .
384
+ - For a ` return e; ` statement, let ` V ` be the inferred type of ` e ` with
385
+ ` K ` as context type scheme, using the local type inference algorithm
386
+ described below.
387
+
388
+ - If the enclosing function is marked ` async ` , the relevant statements
389
+ are ` return; ` and ` return e; ` statements.
390
+ * For a ` return; ` statement, let ` V ` be ` Null ` .
391
+ * For a ` return e; ` statement, let ` S ` be the inferred type of ` e `
392
+ with typing context ` FutureOr<K> ` . Let ` V ` be ** flatten** (` S ` ).
393
+
394
+ - If the enclosing function is marked ` sync* ` , the relevant statements
395
+ are ` yield e; ` or ` yield* e; ` statement.
396
+ * For a ` yield e; ` statement, let ` V ` be the inferred type of ` e ` with
397
+ typing context ` K ` .
398
+ * For a ` yield* e; ` statement, let ` S ` be the inferred type of ` e ` with
399
+ typing context ` Iterable<K> ` .
400
+ If ` S ` implements ` Iterable<R> ` for some ` R ` , let ` V ` be ` R ` .
401
+ Otherwise let ` V ` be ` S ` .
402
+ _ It is a compile-time error if ` S ` is not a assignable to
403
+ ` Iterable<Object?> ` , so either ` S ` implements ` Iterable ` ,
404
+ or it is one of ` dynamic ` or ` Never ` ._
405
+
406
+ - If the enclosing function is marked ` async* ` , the relevant statements are
407
+ ` yield e; ` or ` yield* e; ` statements.
408
+ * For a ` yield e; ` statement, let ` V ` be the inferred type of ` e ` with
409
+ typing context ` K ` .
410
+ * For a ` yield* e; ` statement, let ` S ` be the inferred type of ` e ` with
411
+ typing context ` Stream<K> ` .
412
+ If ` S ` implements ` Stream<R> ` for some ` R ` , let ` V ` be ` R ` .
413
+ Otherwise let ` V ` be ` S ` .
414
+ _ It is a compile-time error if ` S ` is not a assignable to
415
+ ` Stream<Object?> ` , so either ` S ` implements ` Stream ` ,
416
+ or it is one of ` dynamic ` or ` Never ` ._
417
+
418
+ After processing each relevant statement, update ` T ` to be ** UP** (` T ` , ` V ` ).
419
+
420
+ The ** actual value type** of the function literal is the value of ` T ` after
363
421
all ` return ` and ` yield ` statements in the block body have been considered.
364
422
365
- Let ` T ` be the ** actual returned type** of a function literal as computed above.
423
+ Let ` T ` be the ** actual value type** of a function literal as computed above.
366
424
Let ` R ` be the greatest closure of the typing context ` K ` as computed above.
367
425
368
426
With null safety, if ` R ` is ` void ` , let ` S ` be ` void `
369
427
_ (without null-safety: no special treatment is applicable to ` void ` )_ .
370
428
371
429
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
430
+ if ` T <: R ` then let ` S ` be ` T ` , else let ` S ` be ` R ` . The
373
431
inferred return type of the function literal is then defined as follows:
374
432
375
433
- If the function literal is marked ` async ` then the inferred return type is
0 commit comments