Skip to content

Commit f1ac695

Browse files
johnniwinthercommit-bot@chromium.org
authored andcommitted
[cfe] Handle mixed if map entries
Closes #38874 Change-Id: I0122ccb9bc91d349c030955332da338830a137c3 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/121987 Reviewed-by: Aske Simon Christensen <askesc@google.com> Commit-Queue: Johnni Winther <johnniwinther@google.com>
1 parent 8b3d76d commit f1ac695

File tree

8 files changed

+564
-18
lines changed

8 files changed

+564
-18
lines changed

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

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -107,12 +107,7 @@ import '../type_inference/type_inferrer.dart' show TypeInferrer;
107107
import '../type_inference/type_promotion.dart'
108108
show TypePromoter, TypePromotionFact, TypePromotionScope;
109109

110-
import 'collections.dart'
111-
show
112-
SpreadElement,
113-
SpreadMapEntry,
114-
convertToMapEntry,
115-
isConvertibleToMapEntry;
110+
import 'collections.dart';
116111

117112
import 'constness.dart' show Constness;
118113

@@ -3961,12 +3956,21 @@ class BodyBuilder extends ScopeListener<JumpTarget>
39613956
if (elseEntry is MapEntry) {
39623957
push(forest.createIfMapEntry(
39633958
offsetForToken(ifToken), toValue(condition), thenEntry, elseEntry));
3964-
} else if (elseEntry is SpreadElement) {
3965-
push(forest.createIfMapEntry(
3966-
offsetForToken(ifToken),
3967-
toValue(condition),
3968-
thenEntry,
3969-
new SpreadMapEntry(elseEntry.expression, elseEntry.isNullAware)));
3959+
} else if (elseEntry is ControlFlowElement) {
3960+
MapEntry elseMapEntry = elseEntry.toMapEntry();
3961+
if (elseMapEntry != null) {
3962+
push(forest.createIfMapEntry(offsetForToken(ifToken),
3963+
toValue(condition), thenEntry, elseMapEntry));
3964+
} else {
3965+
int offset = elseEntry is Expression
3966+
? elseEntry.fileOffset
3967+
: offsetForToken(ifToken);
3968+
push(new MapEntry(
3969+
buildProblem(
3970+
fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
3971+
new NullLiteral())
3972+
..fileOffset = offsetForToken(ifToken));
3973+
}
39703974
} else {
39713975
int offset = elseEntry is Expression
39723976
? elseEntry.fileOffset
@@ -3978,12 +3982,21 @@ class BodyBuilder extends ScopeListener<JumpTarget>
39783982
..fileOffset = offsetForToken(ifToken));
39793983
}
39803984
} else if (elseEntry is MapEntry) {
3981-
if (thenEntry is SpreadElement) {
3982-
push(forest.createIfMapEntry(
3983-
offsetForToken(ifToken),
3984-
toValue(condition),
3985-
new SpreadMapEntry(thenEntry.expression, thenEntry.isNullAware),
3986-
elseEntry));
3985+
if (thenEntry is ControlFlowElement) {
3986+
MapEntry thenMapEntry = thenEntry.toMapEntry();
3987+
if (thenMapEntry != null) {
3988+
push(forest.createIfMapEntry(offsetForToken(ifToken),
3989+
toValue(condition), thenMapEntry, elseEntry));
3990+
} else {
3991+
int offset = thenEntry is Expression
3992+
? thenEntry.fileOffset
3993+
: offsetForToken(ifToken);
3994+
push(new MapEntry(
3995+
buildProblem(
3996+
fasta.messageCantDisambiguateAmbiguousInformation, offset, 1),
3997+
new NullLiteral())
3998+
..fileOffset = offsetForToken(ifToken));
3999+
}
39874000
} else {
39884001
int offset = thenEntry is Expression
39894002
? thenEntry.fileOffset

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,11 @@ mixin ControlFlowElement on Expression {
5555
@override
5656
R accept1<R, A>(ExpressionVisitor1<R, A> v, A arg) =>
5757
v.defaultExpression(this, arg);
58+
59+
/// Returns this control flow element as a [MapEntry], or `null` if this
60+
/// control flow element cannot be converted into a [MapEntry].
61+
// TODO(johnniwinther): Merge this with [convertToMapEntry].
62+
MapEntry toMapEntry();
5863
}
5964

6065
/// A spread element in a list or set literal.
@@ -84,6 +89,11 @@ class SpreadElement extends Expression with ControlFlowElement {
8489
expression?.parent = this;
8590
}
8691
}
92+
93+
@override
94+
SpreadMapEntry toMapEntry() {
95+
return new SpreadMapEntry(expression, isNullAware)..fileOffset = fileOffset;
96+
}
8797
}
8898

8999
/// An 'if' element in a list or set literal.
@@ -120,6 +130,26 @@ class IfElement extends Expression with ControlFlowElement {
120130
otherwise?.parent = this;
121131
}
122132
}
133+
134+
@override
135+
MapEntry toMapEntry() {
136+
MapEntry thenEntry;
137+
if (then is ControlFlowElement) {
138+
ControlFlowElement thenElement = then;
139+
thenEntry = thenElement.toMapEntry();
140+
}
141+
if (thenEntry == null) return null;
142+
MapEntry otherwiseEntry;
143+
if (otherwise != null) {
144+
if (otherwise is ControlFlowElement) {
145+
ControlFlowElement otherwiseElement = otherwise;
146+
otherwiseEntry = otherwiseElement.toMapEntry();
147+
}
148+
if (otherwiseEntry == null) return null;
149+
}
150+
return new IfMapEntry(condition, thenEntry, otherwiseEntry)
151+
..fileOffset = fileOffset;
152+
}
123153
}
124154

125155
/// A 'for' element in a list or set literal.
@@ -157,6 +187,18 @@ class ForElement extends Expression with ControlFlowElement {
157187
body?.parent = this;
158188
}
159189
}
190+
191+
@override
192+
MapEntry toMapEntry() {
193+
MapEntry bodyEntry;
194+
if (body is ControlFlowElement) {
195+
ControlFlowElement bodyElement = body;
196+
bodyEntry = bodyElement.toMapEntry();
197+
}
198+
if (bodyEntry == null) return null;
199+
return new ForMapEntry(variables, condition, updates, bodyEntry)
200+
..fileOffset = fileOffset;
201+
}
160202
}
161203

162204
/// A 'for-in' element in a list or set literal.
@@ -208,6 +250,18 @@ class ForInElement extends Expression with ControlFlowElement {
208250
problem?.parent = this;
209251
}
210252
}
253+
254+
@override
255+
MapEntry toMapEntry() {
256+
MapEntry bodyEntry;
257+
if (body is ControlFlowElement) {
258+
ControlFlowElement bodyElement = body;
259+
bodyEntry = bodyElement.toMapEntry();
260+
}
261+
if (bodyEntry == null) return null;
262+
return new ForInMapEntry(variable, iterable, prologue, bodyEntry, problem)
263+
..fileOffset = fileOffset;
264+
}
211265
}
212266

213267
mixin ControlFlowMapEntry implements MapEntry {

pkg/front_end/testcases/text_serialization.status

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,5 +1147,6 @@ runtime_checks_new/stub_from_interface_covariant_from_interface: TextSerializati
11471147
runtime_checks_new/stub_from_interface_covariant_from_super: TextSerializationFailure # Was: Pass
11481148
set_literals/disambiguation_rule: TextSerializationFailure # Was: RuntimeError
11491149
top_level_variance_test: TextSerializationFailure
1150+
unified_collections/mixed_entries: TextSerializationFailure
11501151
variance/class_type_parameter_modifier: TextSerializationFailure
11511152
variance/mixin_type_parameter_modifier: TextSerializationFailure
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
2+
// for details. All rights reserved. Use of this source code is governed by a
3+
// BSD-style license that can be found in the LICENSE file.
4+
5+
bool b = false;
6+
7+
var list = [];
8+
9+
var map0 = {};
10+
var map1 = {if (b) 0: 1 else ...map0};
11+
var map2 = {if (b) ...map0 else 0: 1};
12+
var map3 = {if (b) ...map0 else ...map0};
13+
var map4 = {if (b) 0: 1 else for (var a in list) a: 1};
14+
var map5 = {if (b) for (var a in list) a: 1 else 0: 1};
15+
var map6 = {
16+
if (b) 0: 1 else for (var a in list) ...{a: 1}
17+
};
18+
var map7 = {
19+
if (b) for (var a in list) ...{a: 1} else 0: 1
20+
};
21+
var map8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]: 1};
22+
var map9 = {if (b) for (var i = 0; i < list.length; i++) list[i]: 1 else 0: 1};
23+
var map10 = {
24+
if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]: 1}
25+
};
26+
var map11 = {
27+
if (b) for (var i = 0; i < list.length; i++) ...{list[i]: 1} else 0: 1
28+
};
29+
var map12 = {
30+
if (b) 0: 1 else if (b) ...{0: 1}
31+
};
32+
33+
var error4 = {if (b) 0: 1 else for (var a in list) a};
34+
var error5 = {if (b) for (var a in list) a else 0: 1};
35+
var error6 = {
36+
if (b) 0: 1 else for (var a in list) ...{a}
37+
};
38+
var error7 = {
39+
if (b) for (var a in list) ...{a} else 0: 1
40+
};
41+
var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
42+
var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
43+
var error10 = {
44+
if (b) 0: 1 else for (var i = 0; i < list.length; i++) ...{list[i]}
45+
};
46+
var error11 = {
47+
if (b) for (var i = 0; i < list.length; i++) ...{list[i]} else 0: 1
48+
};
49+
var error12 = {
50+
if (b) 0: 1 else if (b) ...{0}
51+
};
52+
53+
main() {}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
library;
2+
//
3+
// Problems in library:
4+
//
5+
// pkg/front_end/testcases/unified_collections/mixed_entries.dart:33:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
6+
// var error4 = {if (b) 0: 1 else for (var a in list) a};
7+
// ^
8+
//
9+
// pkg/front_end/testcases/unified_collections/mixed_entries.dart:34:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
10+
// var error5 = {if (b) for (var a in list) a else 0: 1};
11+
// ^
12+
//
13+
// pkg/front_end/testcases/unified_collections/mixed_entries.dart:41:32: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
14+
// var error8 = {if (b) 0: 1 else for (var i = 0; i < list.length; i++) list[i]};
15+
// ^
16+
//
17+
// pkg/front_end/testcases/unified_collections/mixed_entries.dart:42:22: Error: Both Iterable and Map spread elements encountered in ambiguous literal.
18+
// var error9 = {if (b) for (var i = 0; i < list.length; i++) list[i] else 0: 1};
19+
// ^
20+
//
21+
import self as self;
22+
import "dart:core" as core;
23+
24+
static field core::bool* b;
25+
static field core::List<dynamic>* list;
26+
static field core::Map<dynamic, dynamic>* map0;
27+
static field core::Map<dynamic, dynamic>* map1;
28+
static field core::Map<dynamic, dynamic>* map2;
29+
static field core::Map<dynamic, dynamic>* map3;
30+
static field core::Map<dynamic, core::int*>* map4;
31+
static field core::Map<dynamic, core::int*>* map5;
32+
static field core::Map<dynamic, core::int*>* map6;
33+
static field core::Map<dynamic, core::int*>* map7;
34+
static field core::Map<dynamic, core::int*>* map8;
35+
static field core::Map<dynamic, core::int*>* map9;
36+
static field core::Map<dynamic, core::int*>* map10;
37+
static field core::Map<dynamic, core::int*>* map11;
38+
static field core::Map<core::int*, core::int*>* map12;
39+
static field core::Map<dynamic, core::Null?>* error4;
40+
static field core::Map<dynamic, core::Null?>* error5;
41+
static field dynamic error6;
42+
static field dynamic error7;
43+
static field core::Map<dynamic, core::Null?>* error8;
44+
static field core::Map<dynamic, core::Null?>* error9;
45+
static field dynamic error10;
46+
static field dynamic error11;
47+
static field dynamic error12;
48+
static method main() → dynamic
49+
;

0 commit comments

Comments
 (0)