@@ -679,6 +679,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
679
679
Expression element,
680
680
TreeNode parent,
681
681
DartType inferredTypeArgument,
682
+ Map <TreeNode , DartType > inferredSpreadTypes,
682
683
bool inferenceNeeded,
683
684
bool typeChecksNeeded) {
684
685
if (element is SpreadElement ) {
@@ -688,6 +689,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
688
689
< DartType > [inferredTypeArgument]),
689
690
inferenceNeeded || typeChecksNeeded,
690
691
isVoidAllowed: true );
692
+ inferredSpreadTypes[element.expression] = spreadType;
691
693
if (typeChecksNeeded) {
692
694
DartType spreadElementType =
693
695
getSpreadElementType (spreadType, element.isNullAware);
@@ -709,9 +711,6 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
709
711
element.expression.fileOffset,
710
712
1 )));
711
713
}
712
- } else if (spreadType is DynamicType ) {
713
- inferrer.ensureAssignable (inferrer.coreTypes.iterableClass.rawType,
714
- spreadType, element.expression, element.expression.fileOffset);
715
714
} else if (spreadType is InterfaceType ) {
716
715
if (! inferrer.isAssignable (inferredTypeArgument, spreadElementType)) {
717
716
parent.replaceChild (
@@ -733,12 +732,22 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
733
732
inferrer.inferExpression (element.condition,
734
733
inferrer.coreTypes.boolClass.rawType, typeChecksNeeded,
735
734
isVoidAllowed: false );
736
- DartType thenType = inferElement (element.then, element,
737
- inferredTypeArgument, inferenceNeeded, typeChecksNeeded);
735
+ DartType thenType = inferElement (
736
+ element.then,
737
+ element,
738
+ inferredTypeArgument,
739
+ inferredSpreadTypes,
740
+ inferenceNeeded,
741
+ typeChecksNeeded);
738
742
DartType otherwiseType;
739
743
if (element.otherwise != null ) {
740
- otherwiseType = inferElement (element.otherwise, element,
741
- inferredTypeArgument, inferenceNeeded, typeChecksNeeded);
744
+ otherwiseType = inferElement (
745
+ element.otherwise,
746
+ element,
747
+ inferredTypeArgument,
748
+ inferredSpreadTypes,
749
+ inferenceNeeded,
750
+ typeChecksNeeded);
742
751
}
743
752
return otherwiseType == null
744
753
? thenType
@@ -765,7 +774,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
765
774
isVoidAllowed: true );
766
775
}
767
776
return inferElement (element.body, element, inferredTypeArgument,
768
- inferenceNeeded, typeChecksNeeded);
777
+ inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
769
778
} else if (element is ForInElement ) {
770
779
if (element.variable.name == null ) {
771
780
handleForInWithoutVariable (
@@ -782,7 +791,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
782
791
isVoidAllowed: true );
783
792
}
784
793
return inferElement (element.body, element, inferredTypeArgument,
785
- inferenceNeeded, typeChecksNeeded);
794
+ inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
786
795
} else {
787
796
return inferrer.inferExpression (
788
797
element, inferredTypeArgument, inferenceNeeded || typeChecksNeeded,
@@ -791,9 +800,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
791
800
}
792
801
793
802
void checkElement (Expression item, Expression parent, DartType typeArgument,
794
- DartType actualType) {
803
+ DartType actualType, Map < TreeNode , DartType > inferredSpreadTypes ) {
795
804
if (item is SpreadElement ) {
796
- // Do nothing. The checks are done during inference.
805
+ DartType spreadType = inferredSpreadTypes[item.expression];
806
+ if (spreadType is DynamicType ) {
807
+ inferrer.ensureAssignable (inferrer.coreTypes.iterableClass.rawType,
808
+ spreadType, item.expression, item.expression.fileOffset);
809
+ }
797
810
} else if (item is IfElement ) {
798
811
if (! inferrer.isAssignable (typeArgument, actualType)) {
799
812
int offset =
@@ -807,9 +820,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
807
820
offset,
808
821
1 )));
809
822
} else {
810
- checkElement (item.then, item, typeArgument, actualType);
823
+ checkElement (
824
+ item.then, item, typeArgument, actualType, inferredSpreadTypes);
811
825
if (item.otherwise != null ) {
812
- checkElement (item.otherwise, item, typeArgument, actualType);
826
+ checkElement (item.otherwise, item, typeArgument, actualType,
827
+ inferredSpreadTypes);
813
828
}
814
829
}
815
830
} else if (item is ForElement ) {
@@ -828,7 +843,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
828
843
item.body.fileOffset,
829
844
1 )));
830
845
} else {
831
- checkElement (item.body, item, typeArgument, actualType);
846
+ checkElement (
847
+ item.body, item, typeArgument, actualType, inferredSpreadTypes);
832
848
}
833
849
} else if (item is ForInElement ) {
834
850
if (! inferrer.isAssignable (typeArgument, actualType)) {
@@ -841,7 +857,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
841
857
item.body.fileOffset,
842
858
1 )));
843
859
} else {
844
- checkElement (item.body, item, typeArgument, actualType);
860
+ checkElement (
861
+ item.body, item, typeArgument, actualType, inferredSpreadTypes);
845
862
}
846
863
} else {
847
864
inferrer.ensureAssignable (typeArgument, actualType, item, item.fileOffset,
@@ -859,9 +876,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
859
876
List <DartType > actualTypes;
860
877
bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument ;
861
878
bool typeChecksNeeded = ! inferrer.isTopLevel;
879
+ Map <TreeNode , DartType > inferredSpreadTypes;
862
880
if (inferenceNeeded || typeChecksNeeded) {
863
881
formalTypes = [];
864
882
actualTypes = [];
883
+ inferredSpreadTypes = new Map <TreeNode , DartType >.identity ();
865
884
}
866
885
if (inferenceNeeded) {
867
886
inferredTypes = [const UnknownType ()];
@@ -874,8 +893,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
874
893
}
875
894
if (inferenceNeeded || typeChecksNeeded) {
876
895
for (int i = 0 ; i < node.expressions.length; ++ i) {
877
- DartType type = inferElement (node.expressions[i], node,
878
- inferredTypeArgument, inferenceNeeded, typeChecksNeeded);
896
+ DartType type = inferElement (
897
+ node.expressions[i],
898
+ node,
899
+ inferredTypeArgument,
900
+ inferredSpreadTypes,
901
+ inferenceNeeded,
902
+ typeChecksNeeded);
879
903
actualTypes.add (type);
880
904
if (inferenceNeeded) {
881
905
formalTypes.add (listType.typeArguments[0 ]);
@@ -900,8 +924,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
900
924
}
901
925
if (typeChecksNeeded) {
902
926
for (int i = 0 ; i < node.expressions.length; i++ ) {
903
- checkElement (
904
- node.expressions [i], node, node.typeArgument, actualTypes[i] );
927
+ checkElement (node.expressions[i], node, node.typeArgument,
928
+ actualTypes [i], inferredSpreadTypes );
905
929
}
906
930
}
907
931
node.inferredType = new InterfaceType (listClass, [inferredTypeArgument]);
@@ -966,12 +990,14 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
966
990
DartType spreadContext,
967
991
List <DartType > actualTypes,
968
992
List <DartType > actualTypesForSet,
993
+ Map <TreeNode , DartType > inferredSpreadTypes,
969
994
bool inferenceNeeded,
970
995
bool typeChecksNeeded) {
971
996
if (entry is SpreadMapEntry ) {
972
997
DartType spreadType = inferrer.inferExpression (
973
998
entry.expression, spreadContext, inferenceNeeded || typeChecksNeeded,
974
999
isVoidAllowed: true );
1000
+ inferredSpreadTypes[entry.expression] = spreadType;
975
1001
int length = actualTypes.length;
976
1002
actualTypes.add (null );
977
1003
actualTypes.add (null );
@@ -1012,9 +1038,6 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1012
1038
new NullLiteral ())
1013
1039
..fileOffset = entry.fileOffset);
1014
1040
}
1015
- } else if (spreadType is DynamicType ) {
1016
- inferrer.ensureAssignable (inferrer.coreTypes.mapClass.rawType,
1017
- spreadType, entry.expression, entry.expression.fileOffset);
1018
1041
} else if (spreadType is InterfaceType ) {
1019
1042
Expression keyError;
1020
1043
Expression valueError;
@@ -1087,6 +1110,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1087
1110
spreadContext,
1088
1111
actualTypes,
1089
1112
actualTypesForSet,
1113
+ inferredSpreadTypes,
1090
1114
inferenceNeeded,
1091
1115
typeChecksNeeded);
1092
1116
if (entry.otherwise != null ) {
@@ -1103,6 +1127,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1103
1127
spreadContext,
1104
1128
actualTypes,
1105
1129
actualTypesForSet,
1130
+ inferredSpreadTypes,
1106
1131
inferenceNeeded,
1107
1132
typeChecksNeeded);
1108
1133
int length = actualTypes.length;
@@ -1145,6 +1170,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1145
1170
spreadContext,
1146
1171
actualTypes,
1147
1172
actualTypesForSet,
1173
+ inferredSpreadTypes,
1148
1174
inferenceNeeded,
1149
1175
typeChecksNeeded);
1150
1176
} else if (entry is ForInMapEntry ) {
@@ -1171,6 +1197,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1171
1197
spreadContext,
1172
1198
actualTypes,
1173
1199
actualTypesForSet,
1200
+ inferredSpreadTypes,
1174
1201
inferenceNeeded,
1175
1202
typeChecksNeeded);
1176
1203
} else {
@@ -1203,7 +1230,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1203
1230
DartType keyType,
1204
1231
DartType valueType,
1205
1232
DartType actualKeyType,
1206
- DartType actualValueType) {
1233
+ DartType actualValueType,
1234
+ Map <TreeNode , DartType > inferredSpreadTypes) {
1207
1235
// It's disambiguated as a map literal.
1208
1236
if (iterableSpreadOffset != null ) {
1209
1237
parent.replaceChild (
@@ -1218,7 +1246,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1218
1246
new NullLiteral ()));
1219
1247
}
1220
1248
if (entry is SpreadMapEntry ) {
1221
- // Do nothing. The type checks are done during type inference.
1249
+ DartType spreadType = inferredSpreadTypes[entry.expression];
1250
+ if (spreadType is DynamicType ) {
1251
+ inferrer.ensureAssignable (inferrer.coreTypes.mapClass.rawType,
1252
+ spreadType, entry.expression, entry.expression.fileOffset);
1253
+ }
1222
1254
} else if (entry is IfMapEntry ) {
1223
1255
Expression keyError;
1224
1256
Expression valueError;
@@ -1246,10 +1278,10 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1246
1278
new MapEntry (keyError, valueError)..fileOffset = entry.fileOffset);
1247
1279
} else {
1248
1280
checkMapEntry (entry.then, entry, cachedKey, cachedValue, keyType,
1249
- valueType, actualKeyType, actualValueType);
1281
+ valueType, actualKeyType, actualValueType, inferredSpreadTypes );
1250
1282
if (entry.otherwise != null ) {
1251
1283
checkMapEntry (entry.otherwise, entry, cachedKey, cachedValue, keyType,
1252
- valueType, actualKeyType, actualValueType);
1284
+ valueType, actualKeyType, actualValueType, inferredSpreadTypes );
1253
1285
}
1254
1286
}
1255
1287
} else if (entry is ForMapEntry ) {
@@ -1282,7 +1314,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1282
1314
new MapEntry (keyError, valueError)..fileOffset = entry.fileOffset);
1283
1315
} else {
1284
1316
checkMapEntry (entry.body, entry, cachedKey, cachedValue, keyType,
1285
- valueType, actualKeyType, actualValueType);
1317
+ valueType, actualKeyType, actualValueType, inferredSpreadTypes );
1286
1318
}
1287
1319
} else if (entry is ForInMapEntry ) {
1288
1320
Expression keyError;
@@ -1309,7 +1341,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1309
1341
new MapEntry (keyError, valueError)..fileOffset = entry.fileOffset);
1310
1342
} else {
1311
1343
checkMapEntry (entry.body, entry, cachedKey, cachedValue, keyType,
1312
- valueType, actualKeyType, actualValueType);
1344
+ valueType, actualKeyType, actualValueType, inferredSpreadTypes );
1313
1345
}
1314
1346
} else {
1315
1347
// Do nothing. Assignability checks are done during type inference.
@@ -1388,10 +1420,12 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1388
1420
}
1389
1421
}
1390
1422
bool typeChecksNeeded = ! inferrer.isTopLevel;
1423
+ Map <TreeNode , DartType > inferredSpreadTypes;
1391
1424
if (inferenceNeeded || typeChecksNeeded) {
1392
1425
formalTypes = [];
1393
1426
actualTypes = [];
1394
1427
actualTypesForSet = [];
1428
+ inferredSpreadTypes = new Map <TreeNode , DartType >.identity ();
1395
1429
}
1396
1430
if (inferenceNeeded) {
1397
1431
inferredTypes = [const UnknownType (), const UnknownType ()];
@@ -1439,6 +1473,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1439
1473
spreadTypeContext,
1440
1474
actualTypes,
1441
1475
actualTypesForSet,
1476
+ inferredSpreadTypes,
1442
1477
inferenceNeeded,
1443
1478
typeChecksNeeded);
1444
1479
if (inferenceNeeded) {
@@ -1463,6 +1498,14 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1463
1498
}
1464
1499
1465
1500
List <DartType > inferredTypesForSet = < DartType > [const UnknownType ()];
1501
+ inferrer.typeSchemaEnvironment.inferGenericFunctionOrType (
1502
+ setType,
1503
+ inferrer.coreTypes.setClass.typeParameters,
1504
+ null ,
1505
+ null ,
1506
+ typeContext,
1507
+ inferredTypesForSet,
1508
+ isConst: node.isConst);
1466
1509
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType (
1467
1510
inferrer.coreTypes.setClass.thisType,
1468
1511
inferrer.coreTypes.setClass.typeParameters,
@@ -1481,6 +1524,16 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1481
1524
typeArgument: inferredTypeArgument, isConst: node.isConst)
1482
1525
..fileOffset = node.fileOffset;
1483
1526
node.parent.replaceChild (node, setLiteral);
1527
+ if (typeChecksNeeded) {
1528
+ for (int i = 0 ; i < setLiteral.expressions.length; i++ ) {
1529
+ checkElement (
1530
+ setLiteral.expressions[i],
1531
+ setLiteral,
1532
+ setLiteral.typeArgument,
1533
+ actualTypesForSet[i],
1534
+ inferredSpreadTypes);
1535
+ }
1536
+ }
1484
1537
1485
1538
node.inferredType = setLiteral.inferredType =
1486
1539
new InterfaceType (inferrer.coreTypes.setClass, inferredTypesForSet);
@@ -1534,7 +1587,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1534
1587
node.keyType,
1535
1588
node.valueType,
1536
1589
actualTypes[2 * i],
1537
- actualTypes[2 * i + 1 ]);
1590
+ actualTypes[2 * i + 1 ],
1591
+ inferredSpreadTypes);
1538
1592
}
1539
1593
}
1540
1594
node.inferredType =
@@ -1773,9 +1827,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1773
1827
List <DartType > actualTypes;
1774
1828
bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument ;
1775
1829
bool typeChecksNeeded = ! inferrer.isTopLevel;
1830
+ Map <TreeNode , DartType > inferredSpreadTypes;
1776
1831
if (inferenceNeeded || typeChecksNeeded) {
1777
1832
formalTypes = [];
1778
1833
actualTypes = [];
1834
+ inferredSpreadTypes = new Map <TreeNode , DartType >.identity ();
1779
1835
}
1780
1836
if (inferenceNeeded) {
1781
1837
inferredTypes = [const UnknownType ()];
@@ -1788,8 +1844,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1788
1844
}
1789
1845
if (inferenceNeeded || typeChecksNeeded) {
1790
1846
for (int i = 0 ; i < node.expressions.length; ++ i) {
1791
- DartType type = inferElement (node.expressions[i], node,
1792
- inferredTypeArgument, inferenceNeeded, typeChecksNeeded);
1847
+ DartType type = inferElement (
1848
+ node.expressions[i],
1849
+ node,
1850
+ inferredTypeArgument,
1851
+ inferredSpreadTypes,
1852
+ inferenceNeeded,
1853
+ typeChecksNeeded);
1793
1854
actualTypes.add (type);
1794
1855
if (inferenceNeeded) {
1795
1856
formalTypes.add (setType.typeArguments[0 ]);
@@ -1814,8 +1875,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
1814
1875
}
1815
1876
if (typeChecksNeeded) {
1816
1877
for (int i = 0 ; i < node.expressions.length; i++ ) {
1817
- checkElement (
1818
- node.expressions [i], node, node.typeArgument, actualTypes[i] );
1878
+ checkElement (node.expressions[i], node, node.typeArgument,
1879
+ actualTypes [i], inferredSpreadTypes );
1819
1880
}
1820
1881
}
1821
1882
node.inferredType = new InterfaceType (setClass, [inferredTypeArgument]);
0 commit comments