Skip to content

Commit e0a2651

Browse files
author
Dmitry Stefantsov
committed
[cfe] Fix downcasts added during set/map disambiguation
Change-Id: I79d559c756994424eb395ecc8f12f84c1bf1e257 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98327 Commit-Queue: Dmitry Stefantsov <[email protected]> Reviewed-by: Aske Simon Christensen <[email protected]>
1 parent f21d521 commit e0a2651

File tree

5 files changed

+106
-77
lines changed

5 files changed

+106
-77
lines changed

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,8 +67,6 @@ import '../type_inference/type_promotion.dart'
6767

6868
import 'collections.dart'
6969
show
70-
ControlFlowElement,
71-
ControlFlowMapEntry,
7270
ForElement,
7371
ForInElement,
7472
ForInMapEntry,

pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart

Lines changed: 94 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
679679
Expression element,
680680
TreeNode parent,
681681
DartType inferredTypeArgument,
682+
Map<TreeNode, DartType> inferredSpreadTypes,
682683
bool inferenceNeeded,
683684
bool typeChecksNeeded) {
684685
if (element is SpreadElement) {
@@ -688,6 +689,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
688689
<DartType>[inferredTypeArgument]),
689690
inferenceNeeded || typeChecksNeeded,
690691
isVoidAllowed: true);
692+
inferredSpreadTypes[element.expression] = spreadType;
691693
if (typeChecksNeeded) {
692694
DartType spreadElementType =
693695
getSpreadElementType(spreadType, element.isNullAware);
@@ -709,9 +711,6 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
709711
element.expression.fileOffset,
710712
1)));
711713
}
712-
} else if (spreadType is DynamicType) {
713-
inferrer.ensureAssignable(inferrer.coreTypes.iterableClass.rawType,
714-
spreadType, element.expression, element.expression.fileOffset);
715714
} else if (spreadType is InterfaceType) {
716715
if (!inferrer.isAssignable(inferredTypeArgument, spreadElementType)) {
717716
parent.replaceChild(
@@ -733,12 +732,22 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
733732
inferrer.inferExpression(element.condition,
734733
inferrer.coreTypes.boolClass.rawType, typeChecksNeeded,
735734
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);
738742
DartType otherwiseType;
739743
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);
742751
}
743752
return otherwiseType == null
744753
? thenType
@@ -765,7 +774,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
765774
isVoidAllowed: true);
766775
}
767776
return inferElement(element.body, element, inferredTypeArgument,
768-
inferenceNeeded, typeChecksNeeded);
777+
inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
769778
} else if (element is ForInElement) {
770779
if (element.variable.name == null) {
771780
handleForInWithoutVariable(
@@ -782,7 +791,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
782791
isVoidAllowed: true);
783792
}
784793
return inferElement(element.body, element, inferredTypeArgument,
785-
inferenceNeeded, typeChecksNeeded);
794+
inferredSpreadTypes, inferenceNeeded, typeChecksNeeded);
786795
} else {
787796
return inferrer.inferExpression(
788797
element, inferredTypeArgument, inferenceNeeded || typeChecksNeeded,
@@ -791,9 +800,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
791800
}
792801

793802
void checkElement(Expression item, Expression parent, DartType typeArgument,
794-
DartType actualType) {
803+
DartType actualType, Map<TreeNode, DartType> inferredSpreadTypes) {
795804
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+
}
797810
} else if (item is IfElement) {
798811
if (!inferrer.isAssignable(typeArgument, actualType)) {
799812
int offset =
@@ -807,9 +820,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
807820
offset,
808821
1)));
809822
} else {
810-
checkElement(item.then, item, typeArgument, actualType);
823+
checkElement(
824+
item.then, item, typeArgument, actualType, inferredSpreadTypes);
811825
if (item.otherwise != null) {
812-
checkElement(item.otherwise, item, typeArgument, actualType);
826+
checkElement(item.otherwise, item, typeArgument, actualType,
827+
inferredSpreadTypes);
813828
}
814829
}
815830
} else if (item is ForElement) {
@@ -828,7 +843,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
828843
item.body.fileOffset,
829844
1)));
830845
} else {
831-
checkElement(item.body, item, typeArgument, actualType);
846+
checkElement(
847+
item.body, item, typeArgument, actualType, inferredSpreadTypes);
832848
}
833849
} else if (item is ForInElement) {
834850
if (!inferrer.isAssignable(typeArgument, actualType)) {
@@ -841,7 +857,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
841857
item.body.fileOffset,
842858
1)));
843859
} else {
844-
checkElement(item.body, item, typeArgument, actualType);
860+
checkElement(
861+
item.body, item, typeArgument, actualType, inferredSpreadTypes);
845862
}
846863
} else {
847864
inferrer.ensureAssignable(typeArgument, actualType, item, item.fileOffset,
@@ -859,9 +876,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
859876
List<DartType> actualTypes;
860877
bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
861878
bool typeChecksNeeded = !inferrer.isTopLevel;
879+
Map<TreeNode, DartType> inferredSpreadTypes;
862880
if (inferenceNeeded || typeChecksNeeded) {
863881
formalTypes = [];
864882
actualTypes = [];
883+
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
865884
}
866885
if (inferenceNeeded) {
867886
inferredTypes = [const UnknownType()];
@@ -874,8 +893,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
874893
}
875894
if (inferenceNeeded || typeChecksNeeded) {
876895
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);
879903
actualTypes.add(type);
880904
if (inferenceNeeded) {
881905
formalTypes.add(listType.typeArguments[0]);
@@ -900,8 +924,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
900924
}
901925
if (typeChecksNeeded) {
902926
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);
905929
}
906930
}
907931
node.inferredType = new InterfaceType(listClass, [inferredTypeArgument]);
@@ -966,12 +990,14 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
966990
DartType spreadContext,
967991
List<DartType> actualTypes,
968992
List<DartType> actualTypesForSet,
993+
Map<TreeNode, DartType> inferredSpreadTypes,
969994
bool inferenceNeeded,
970995
bool typeChecksNeeded) {
971996
if (entry is SpreadMapEntry) {
972997
DartType spreadType = inferrer.inferExpression(
973998
entry.expression, spreadContext, inferenceNeeded || typeChecksNeeded,
974999
isVoidAllowed: true);
1000+
inferredSpreadTypes[entry.expression] = spreadType;
9751001
int length = actualTypes.length;
9761002
actualTypes.add(null);
9771003
actualTypes.add(null);
@@ -1012,9 +1038,6 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
10121038
new NullLiteral())
10131039
..fileOffset = entry.fileOffset);
10141040
}
1015-
} else if (spreadType is DynamicType) {
1016-
inferrer.ensureAssignable(inferrer.coreTypes.mapClass.rawType,
1017-
spreadType, entry.expression, entry.expression.fileOffset);
10181041
} else if (spreadType is InterfaceType) {
10191042
Expression keyError;
10201043
Expression valueError;
@@ -1087,6 +1110,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
10871110
spreadContext,
10881111
actualTypes,
10891112
actualTypesForSet,
1113+
inferredSpreadTypes,
10901114
inferenceNeeded,
10911115
typeChecksNeeded);
10921116
if (entry.otherwise != null) {
@@ -1103,6 +1127,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
11031127
spreadContext,
11041128
actualTypes,
11051129
actualTypesForSet,
1130+
inferredSpreadTypes,
11061131
inferenceNeeded,
11071132
typeChecksNeeded);
11081133
int length = actualTypes.length;
@@ -1145,6 +1170,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
11451170
spreadContext,
11461171
actualTypes,
11471172
actualTypesForSet,
1173+
inferredSpreadTypes,
11481174
inferenceNeeded,
11491175
typeChecksNeeded);
11501176
} else if (entry is ForInMapEntry) {
@@ -1171,6 +1197,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
11711197
spreadContext,
11721198
actualTypes,
11731199
actualTypesForSet,
1200+
inferredSpreadTypes,
11741201
inferenceNeeded,
11751202
typeChecksNeeded);
11761203
} else {
@@ -1203,7 +1230,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
12031230
DartType keyType,
12041231
DartType valueType,
12051232
DartType actualKeyType,
1206-
DartType actualValueType) {
1233+
DartType actualValueType,
1234+
Map<TreeNode, DartType> inferredSpreadTypes) {
12071235
// It's disambiguated as a map literal.
12081236
if (iterableSpreadOffset != null) {
12091237
parent.replaceChild(
@@ -1218,7 +1246,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
12181246
new NullLiteral()));
12191247
}
12201248
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+
}
12221254
} else if (entry is IfMapEntry) {
12231255
Expression keyError;
12241256
Expression valueError;
@@ -1246,10 +1278,10 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
12461278
new MapEntry(keyError, valueError)..fileOffset = entry.fileOffset);
12471279
} else {
12481280
checkMapEntry(entry.then, entry, cachedKey, cachedValue, keyType,
1249-
valueType, actualKeyType, actualValueType);
1281+
valueType, actualKeyType, actualValueType, inferredSpreadTypes);
12501282
if (entry.otherwise != null) {
12511283
checkMapEntry(entry.otherwise, entry, cachedKey, cachedValue, keyType,
1252-
valueType, actualKeyType, actualValueType);
1284+
valueType, actualKeyType, actualValueType, inferredSpreadTypes);
12531285
}
12541286
}
12551287
} else if (entry is ForMapEntry) {
@@ -1282,7 +1314,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
12821314
new MapEntry(keyError, valueError)..fileOffset = entry.fileOffset);
12831315
} else {
12841316
checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
1285-
valueType, actualKeyType, actualValueType);
1317+
valueType, actualKeyType, actualValueType, inferredSpreadTypes);
12861318
}
12871319
} else if (entry is ForInMapEntry) {
12881320
Expression keyError;
@@ -1309,7 +1341,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
13091341
new MapEntry(keyError, valueError)..fileOffset = entry.fileOffset);
13101342
} else {
13111343
checkMapEntry(entry.body, entry, cachedKey, cachedValue, keyType,
1312-
valueType, actualKeyType, actualValueType);
1344+
valueType, actualKeyType, actualValueType, inferredSpreadTypes);
13131345
}
13141346
} else {
13151347
// Do nothing. Assignability checks are done during type inference.
@@ -1388,10 +1420,12 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
13881420
}
13891421
}
13901422
bool typeChecksNeeded = !inferrer.isTopLevel;
1423+
Map<TreeNode, DartType> inferredSpreadTypes;
13911424
if (inferenceNeeded || typeChecksNeeded) {
13921425
formalTypes = [];
13931426
actualTypes = [];
13941427
actualTypesForSet = [];
1428+
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
13951429
}
13961430
if (inferenceNeeded) {
13971431
inferredTypes = [const UnknownType(), const UnknownType()];
@@ -1439,6 +1473,7 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
14391473
spreadTypeContext,
14401474
actualTypes,
14411475
actualTypesForSet,
1476+
inferredSpreadTypes,
14421477
inferenceNeeded,
14431478
typeChecksNeeded);
14441479
if (inferenceNeeded) {
@@ -1463,6 +1498,14 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
14631498
}
14641499

14651500
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);
14661509
inferrer.typeSchemaEnvironment.inferGenericFunctionOrType(
14671510
inferrer.coreTypes.setClass.thisType,
14681511
inferrer.coreTypes.setClass.typeParameters,
@@ -1481,6 +1524,16 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
14811524
typeArgument: inferredTypeArgument, isConst: node.isConst)
14821525
..fileOffset = node.fileOffset;
14831526
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+
}
14841537

14851538
node.inferredType = setLiteral.inferredType =
14861539
new InterfaceType(inferrer.coreTypes.setClass, inferredTypesForSet);
@@ -1534,7 +1587,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
15341587
node.keyType,
15351588
node.valueType,
15361589
actualTypes[2 * i],
1537-
actualTypes[2 * i + 1]);
1590+
actualTypes[2 * i + 1],
1591+
inferredSpreadTypes);
15381592
}
15391593
}
15401594
node.inferredType =
@@ -1773,9 +1827,11 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
17731827
List<DartType> actualTypes;
17741828
bool inferenceNeeded = node.typeArgument is ImplicitTypeArgument;
17751829
bool typeChecksNeeded = !inferrer.isTopLevel;
1830+
Map<TreeNode, DartType> inferredSpreadTypes;
17761831
if (inferenceNeeded || typeChecksNeeded) {
17771832
formalTypes = [];
17781833
actualTypes = [];
1834+
inferredSpreadTypes = new Map<TreeNode, DartType>.identity();
17791835
}
17801836
if (inferenceNeeded) {
17811837
inferredTypes = [const UnknownType()];
@@ -1788,8 +1844,13 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
17881844
}
17891845
if (inferenceNeeded || typeChecksNeeded) {
17901846
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);
17931854
actualTypes.add(type);
17941855
if (inferenceNeeded) {
17951856
formalTypes.add(setType.typeArguments[0]);
@@ -1814,8 +1875,8 @@ class InferenceVisitor extends BodyVisitor1<void, DartType> {
18141875
}
18151876
if (typeChecksNeeded) {
18161877
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);
18191880
}
18201881
}
18211882
node.inferredType = new InterfaceType(setClass, [inferredTypeArgument]);

pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@ import '../../base/instrumentation.dart'
3535

3636
import '../fasta_codes.dart'
3737
show
38-
LocatedMessage,
3938
messageCantDisambiguateAmbiguousInformation,
4039
messageCantDisambiguateNotEnoughInformation,
4140
messageNonNullAwareSpreadIsNull,
42-
messageSpreadElement,
43-
messageSpreadMapElement,
4441
messageSwitchExpressionNotAssignableCause,
4542
messageVoidExpression,
4643
noLength,

0 commit comments

Comments
 (0)