Skip to content

Commit f21d521

Browse files
author
Dmitry Stefantsov
committed
[cfe] Fix pre-inference set/map disambiguation
Closes #36377 Bug: http://dartbug.com/36377 Change-Id: I0a486f467bdc999e6188fb3206f4eed1d8ffb67a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/98341 Reviewed-by: Aske Simon Christensen <[email protected]>
1 parent 6b19aa8 commit f21d521

4 files changed

+143
-123
lines changed

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

+35-15
Original file line numberDiff line numberDiff line change
@@ -2456,7 +2456,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
24562456
if (entry is MapEntry) {
24572457
// TODO(danrubel): report the error on the colon
24582458
addProblem(fasta.templateExpectedButGot.withArguments(','),
2459-
entry.value.fileOffset - 1, 1);
2459+
entry.fileOffset, 1);
24602460
} else {
24612461
// TODO(danrubel): Revise once control flow and spread
24622462
// collection entries are supported.
@@ -2518,6 +2518,13 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
25182518
final typeArgCount = typeArguments?.length;
25192519
bool isSet = typeArgCount == 1 ? true : typeArgCount != null ? false : null;
25202520

2521+
for (int i = 0; i < setOrMapEntries.length; ++i) {
2522+
if (setOrMapEntries[i] is! MapEntry &&
2523+
!isConvertibleToMapEntry(setOrMapEntries[i])) {
2524+
hasSetEntry = true;
2525+
}
2526+
}
2527+
25212528
// TODO(danrubel): If the type arguments are not known (null) then
25222529
// defer set/map determination until after type resolution as per the
25232530
// unified collection spec: https://github.com/dart-lang/language/pull/200
@@ -2527,7 +2534,15 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
25272534
if (isSet) {
25282535
buildLiteralSet(typeArguments, constKeyword, leftBrace, setOrMapEntries);
25292536
} else {
2530-
buildLiteralMap(typeArguments, constKeyword, leftBrace, setOrMapEntries);
2537+
List<MapEntry> mapEntries = new List<MapEntry>(setOrMapEntries.length);
2538+
for (int i = 0; i < setOrMapEntries.length; ++i) {
2539+
if (setOrMapEntries[i] is MapEntry) {
2540+
mapEntries[i] = setOrMapEntries[i];
2541+
} else {
2542+
mapEntries[i] = convertToMapEntry(setOrMapEntries[i]);
2543+
}
2544+
}
2545+
buildLiteralMap(typeArguments, constKeyword, leftBrace, mapEntries);
25312546
}
25322547
}
25332548

@@ -2551,10 +2566,26 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
25512566
push(forest.literalNull(token));
25522567
}
25532568

2569+
bool isConvertibleToMapEntry(Expression element) {
2570+
if (element is SpreadElement) return true;
2571+
if (element is IfElement) {
2572+
return isConvertibleToMapEntry(element.then) &&
2573+
(element.otherwise == null ||
2574+
isConvertibleToMapEntry(element.otherwise));
2575+
}
2576+
if (element is ForElement) {
2577+
return isConvertibleToMapEntry(element.body);
2578+
}
2579+
if (element is ForInElement) {
2580+
return isConvertibleToMapEntry(element.body);
2581+
}
2582+
return false;
2583+
}
2584+
25542585
MapEntry convertToMapEntry(Expression element) {
25552586
if (element is SpreadElement) {
25562587
return new SpreadMapEntry(element.expression, element.isNullAware)
2557-
..fileOffset = element.fileOffset;
2588+
..fileOffset = element.expression.fileOffset;
25582589
}
25592590
if (element is IfElement) {
25602591
return new IfMapEntry(
@@ -2586,7 +2617,7 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
25862617
}
25872618

25882619
void buildLiteralMap(List<UnresolvedType<KernelTypeBuilder>> typeArguments,
2589-
Token constKeyword, Token leftBrace, List<dynamic> setOrMapEntries) {
2620+
Token constKeyword, Token leftBrace, List<MapEntry> entries) {
25902621
DartType keyType;
25912622
DartType valueType;
25922623
if (typeArguments != null) {
@@ -2607,17 +2638,6 @@ abstract class BodyBuilder extends ScopeListener<JumpTarget>
26072638
valueType = implicitTypeArgument;
26082639
}
26092640

2610-
List<MapEntry> entries = <MapEntry>[];
2611-
if (setOrMapEntries != null) {
2612-
for (var entry in setOrMapEntries) {
2613-
if (entry is MapEntry) {
2614-
entries.add(entry);
2615-
} else {
2616-
entries.add(convertToMapEntry(entry));
2617-
}
2618-
}
2619-
}
2620-
26212641
Expression node = forest.literalMap(
26222642
constKeyword,
26232643
constKeyword != null || constantContext == ConstantContext.inferred,

0 commit comments

Comments
 (0)