@@ -1046,22 +1046,33 @@ The elaboration process sometimes introduces new operations that are not easily
1046
1046
expressible using the syntax of Dart. To allow these operations to be specified
1047
1047
succintly, the syntax of Dart is extended to allow the following forms:
1048
1048
1049
- - ` @AWAIT_WITH_TYPE_CHECK<T> (m_1) ` , represents the following operation:
1049
+ - ` @AWAIT_WITH_TYPE_CHECK(m_1) ` represents the following operation:
1050
1050
1051
- - Evaluate ` m_1 ` , and let ` v ` denote the result .
1051
+ - Let ` T_1 ` be the static type of ` m_1 ` .
1052
1052
1053
- - If ` v ` is an instance satisfying type ` Future<T> ` , then
1054
- ` @AWAIT_WITH_TYPE_CHECK<T>(m_1) ` evaluates to ` v ` .
1053
+ - Let ` T ` be ` flatten(T_1) ` .
1055
1054
1056
- - Otherwise, let ` u ` be a future satisfying type ` Future<T> ` that will
1057
- complete to the value ` v ` at some later point. Then,
1058
- ` @AWAIT_WITH_TYPE_CHECK<T>(m_1) ` evaluates to ` u ` .
1055
+ - Evaluate ` m_1 ` , and let ` v ` denote the result. _ Note that since ` m_1 ` has
1056
+ static type ` T_1 ` , by soundness, ` v ` must be an instance satisfying
1057
+ ` T_1 ` . Since ` T_1 <: FutureOr<flatten(T_1)> ` for all ` T_1 ` , it follows that
1058
+ ` v ` must be an instance satisfying ` FutureOr<flatten(T_1)> ` , or
1059
+ equivalently, satisfying ` FutureOr<T> ` . Therefore, ` v ` must either be an
1060
+ instance satisfying either ` Future<T> ` or ` T ` . We consider the two cases
1061
+ below._
1059
1062
1060
- - _ TODO(paulberry): explain why such a future is guaranteed to (soundly)
1061
- exist, by stipulating that if ` T_1 ` is the static type of ` m_1 ` , then ` T `
1062
- must be ` flatten(T_1) ` , and then proving a lemma that `T_1 <:
1063
- FutureOr<flatten(T_1)>` ; therefore ` T_1 <: FutureOr<T >`, so in this
1064
- "otherwise" case, ` v ` must be an instance satisfying ` T ` ._
1063
+ - If ` v ` is an instance satisfying type ` Future<T> ` , then let
1064
+ ` @AWAIT_WITH_TYPE_CHECK(m_1) ` evaluate to ` v ` .
1065
+
1066
+ - Otherwise, let ` @AWAIT_WITH_TYPE_CHECK(m_1) ` evaluate to a future satisfying
1067
+ type ` Future<T> ` that will complete to the value ` v ` at some later
1068
+ point. _ Such a future could, for instance, be created by executing
1069
+ ` Future<T>.value(v) ` (this is sound because in this case ` v ` is an instance
1070
+ satisfying ` T ` ). It also could be created using a more efficient
1071
+ implementation-specific mechanism._
1072
+
1073
+ - _ Note that these two cases in the abstract correspond concretely to a type
1074
+ check in the implementation; this where the name ` @AWAIT_WITH_TYPE_CHECK `
1075
+ comes from._
1065
1076
1066
1077
- ` @CONCAT(m_1, m_2, ..., m_n) ` , where each ` m_i ` is an elaborated expression
1067
1078
whose static type is a subtype of ` String ` , represents the operation of
@@ -1389,99 +1400,17 @@ are determined as follows:
1389
1400
1390
1401
- Let ` T_2 ` be ` flatten(T_1) ` .
1391
1402
1392
- - Let ` m_2 ` be ` @AWAIT_WITH_TYPE_CHECK<T_2>(m_1) ` , with static type
1393
- ` Future<T_2> ` .
1403
+ - Let ` m_2 ` be ` @AWAIT_WITH_TYPE_CHECK(m_1) ` , with static type
1404
+ ` Future<T_2> ` . _ This is sound because ` @AWAIT_WITH_TYPE_CHECK(m_1) ` always
1405
+ evaluates to an instance satisfying type ` Future<T_2> ` ._
1394
1406
1395
1407
- _ Note that in many circumstances, it will be trivial for the compiler to
1396
1408
establish that ` m_1 ` always evaluates to an instance ` v ` that satisfies type
1397
1409
` Future<T_2> ` , in which case ` m_2 ` can be optimized to
1398
1410
` @PROMOTED_TYPE<Future<T_2>>(m_1) ` ._
1399
1411
1400
- - _ For soundness, we must prove that whenever
1401
- ` @AWAIT_WITH_TYPE_CHECK<T_2>(m_1) ` evaluates ` m_1 ` to a value ` v ` that is
1402
- __ not__ an instance satisfying type ` Future<T_2> ` , that ` v ` __ is__ an
1403
- instance satisfying type ` T_2 ` . This is necessary to ensure that the future
1404
- created by ` @AWAIT_WITH_TYPE_CHECK ` will complete to a value satisfying its
1405
- type signature. Note that ` v ` is guaranteed to be an instance satisfying
1406
- type ` T_1 ` (because ` T_1 ` is the static type of ` m_1 ` ). So we can establish
1407
- soundness by assuming that ` v ` is an instance satisfying type ` T_1 ` and not
1408
- an instance satisfying type ` Future<T_2> ` , and then considering two cases:_
1409
-
1410
- - _ TODO(paulberry): it should be possible to simplify and clarify this
1411
- section once we have proven that ` T <: FutureOr<flatten(T)> ` for all types
1412
- ` T ` ._
1413
-
1414
- - _ If the runtime value of ` v ` is ` null ` , then by soundness, ` T_1 ` must be
1415
- of the form ` Null ` , ` dynamic ` , ` S* ` , or ` S? ` . Considering each of these:_
1416
-
1417
- - _ If ` T_1 ` is of the form ` Null ` or ` dynamic ` , then by the definition of
1418
- ` flatten ` , ` T_2 ` must be the same as ` T_1 ` . Therefore, ` v ` is an
1419
- instance satisfying type ` T_2 ` , so soundness is satisfied._
1420
-
1421
- - _ If ` T_1 ` is of the form ` S* ` or ` S? ` , then by the definition of
1422
- ` flatten ` , ` T_2 ` must be of the form ` flatten(S)* ` or ` flatten(S)? ` ,
1423
- respectively. ` null ` is an instance satisfying all types ending in ` * `
1424
- and ` ? ` , so soudness is satisfied._
1425
-
1426
- - _ Otherwise, we need to show that if ` v ` is a non-null instance satisfying
1427
- type ` T_1 ` , but not an instance satisfying type ` Future<T_2> ` , then ` v ` is
1428
- an instance satisfying type ` T_2 ` ._
1429
-
1430
- - _ Substituting in the definition of ` T_2 ` , we need to show that if ` v ` is a
1431
- non-null instance satisfying type ` T_1 ` , but not an instance satisfying
1432
- type ` Future<flatten(T_1)> ` , then ` v ` is an instance satisfying type
1433
- ` flatten(T_1) ` . We can prove this by induction on ` T_1 ` :_
1434
-
1435
- - _ If ` T_1 ` is ` S? ` , then ` flatten(T_1) ` is ` flatten(S)? ` . We need to show
1436
- that if ` v ` is a non-null instance satisfying type ` S? ` , but not an
1437
- instance satisfying type ` Future<flatten(S)?> ` , then ` v ` is an instance
1438
- satisfying type ` flatten(S)? ` . Assuming ` v ` is a non-null instance
1439
- satisfying type ` S? ` , it must be a non-null instance satisfying type
1440
- ` S ` . Assuming ` v ` is not an instance satisfying type
1441
- ` Future<flatten(S)?> ` , it follows that ` v ` is not an instance satisfying
1442
- type ` Future<flatten(S)> ` . So we have satisfied the premise of the
1443
- induction hypothesis using ` T_1 = S ` , and therefore by induction, ` v ` is
1444
- an instance satisfying type ` flatten(S) ` . This in turn implies that ` v `
1445
- is an instance satisfying type ` flatten(S)? ` ._
1446
-
1447
- - _ (Same argument but with ` ? ` replaced by ` * ` ): If ` T_1 ` is ` S* ` , then
1448
- ` flatten(T_1) ` is ` flatten(S)* ` . We need to show that if ` v ` is a
1449
- non-null instance satisfying type ` S* ` , but not an instance satisfying
1450
- type ` Future<flatten(S)*> ` , then ` v ` is an instance satisfying type
1451
- ` flatten(S)* ` . Assuming ` v ` is a non-null instance satisfying type ` S* ` ,
1452
- it must be a non-null instance satisfying type ` S ` . Assuming ` v ` is not
1453
- an instance satisfying type ` Future<flatten(S)*> ` , it follows that ` v `
1454
- is not an instance satisfying type ` Future<flatten(S)> ` . So we have
1455
- satisfied the premise of the induction hypothesis using ` T_1 = S ` , and
1456
- therefore by induction, ` v ` is an instance satisfying type
1457
- ` flatten(S) ` . This in turn implies that ` v ` is an instance satisfying
1458
- type ` flatten(S)* ` ._
1459
-
1460
- - _ If ` T_1 ` is ` FutureOr<S> ` , then ` flatten(T_1) ` is ` S ` . We need to show
1461
- that if ` v ` is a non-null instance satisfying type ` FutureOr<S> ` , but
1462
- not an instance satisfying type ` Future<S> ` , then ` v ` is an instance
1463
- satisfying type ` S ` . This is trivially true, because ` FutureOr<S> ` is
1464
- the union of types ` S ` and ` Future<S> ` ._
1465
-
1466
- - _ If ` T_1 <: Future ` , then ` flatten(T_1) ` is ` S ` , where ` S ` is a type
1467
- such that ` T_1 <: Future<S> ` and for all ` R ` , if ` T_1 <: Future<R> ` then
1468
- ` S <: R ` . We need to show that if ` v ` is a non-null instance satisfying
1469
- type ` T_1 ` , but not an instance satisfying type ` Future<S> ` , then ` v ` is
1470
- an instance satisfying type ` S ` . Assuming ` v ` is a non-null instance
1471
- satisfying type ` T_1 ` , it must also be a non-null instance satisfying
1472
- type ` Future<S> ` (because ` T_1 <: Future<S> ` ). But this contradicts the
1473
- assumption that ` v ` is __ not__ an instance satisfying type ` Future<S> ` ,
1474
- so this case is impossible._
1475
-
1476
- - _ Finally, if none of the above cases are satisfied, then ` flatten(T_1) `
1477
- is ` T_1 ` . We need to show that if ` v ` is a non-null instance satisfying
1478
- type ` T_1 ` , but not an instance satisfying type ` Future<T_1> ` , then ` v `
1479
- is an instance satisfying type ` T_1 ` . This is trivially true, since if
1480
- ` v ` is a non-null instance satisfying type ` T_1 ` , it must be an instance
1481
- satisfying type ` T_1 ` ._
1482
-
1483
1412
- Let ` T ` be ` T_2 ` , and let ` m ` be ` await m_2 ` . _ Since ` m_2 ` has static type
1484
- ` Future<m_2 > ` , the value of ` await m_2 ` must necessarily be an instance
1413
+ ` Future<T_2 > ` , the value of ` await m_2 ` must necessarily be an instance
1485
1414
satisfying type ` T_2 ` , so soundness is satisfied._
1486
1415
1487
1416
<!--
0 commit comments