Skip to content

Commit fffd0d0

Browse files
committed
[cfe] Handle Null/Never-ish spread element types
Closes #42758 Change-Id: I0b25a5a1abc0896300f61fc98f514f1ed1a63e31 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155447 Reviewed-by: Dmitry Stefantsov <[email protected]>
1 parent 77fcb33 commit fffd0d0

23 files changed

+1573
-140
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6379,14 +6379,6 @@ const MessageCode messageNonInstanceTypeVariableUse = const MessageCode(
63796379
analyzerCodes: <String>["TYPE_PARAMETER_REFERENCED_BY_STATIC"],
63806380
message: r"""Can only use type variables in instance methods.""");
63816381

6382-
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6383-
const Code<Null> codeNonNullAwareSpreadIsNull = messageNonNullAwareSpreadIsNull;
6384-
6385-
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
6386-
const MessageCode messageNonNullAwareSpreadIsNull = const MessageCode(
6387-
"NonNullAwareSpreadIsNull",
6388-
message: r"""Can't spread a value with static type Null.""");
6389-
63906382
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
63916383
const Template<Message Function(String name)>
63926384
templateNonNullableLateDefinitelyAssignedError =

pkg/front_end/lib/src/fasta/fasta_codes_cfe_generated.dart

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2196,6 +2196,33 @@ Message _withArgumentsMixinInferenceNoMatchingClass(
21962196
arguments: {'name': name, 'name2': name2, 'type': _type});
21972197
}
21982198

2199+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2200+
const Template<Message Function(DartType _type, bool isNonNullableByDefault)>
2201+
templateNonNullAwareSpreadIsNull = const Template<
2202+
Message Function(DartType _type, bool isNonNullableByDefault)>(
2203+
messageTemplate: r"""Can't spread a value with static type '#type'.""",
2204+
withArguments: _withArgumentsNonNullAwareSpreadIsNull);
2205+
2206+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2207+
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>
2208+
codeNonNullAwareSpreadIsNull =
2209+
const Code<Message Function(DartType _type, bool isNonNullableByDefault)>(
2210+
"NonNullAwareSpreadIsNull",
2211+
templateNonNullAwareSpreadIsNull,
2212+
);
2213+
2214+
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
2215+
Message _withArgumentsNonNullAwareSpreadIsNull(
2216+
DartType _type, bool isNonNullableByDefault) {
2217+
TypeLabeler labeler = new TypeLabeler(isNonNullableByDefault);
2218+
List<Object> typeParts = labeler.labelType(_type);
2219+
String type = typeParts.join();
2220+
return new Message(codeNonNullAwareSpreadIsNull,
2221+
message: """Can't spread a value with static type '${type}'.""" +
2222+
labeler.originMessages,
2223+
arguments: {'type': _type});
2224+
}
2225+
21992226
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
22002227
const Template<
22012228
Message Function(

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

Lines changed: 46 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1328,21 +1328,27 @@ class InferenceVisitor
13281328
}
13291329

13301330
DartType getSpreadElementType(DartType spreadType, bool isNullAware) {
1331-
if (spreadType is InterfaceType) {
1332-
if (spreadType.classNode == inferrer.coreTypes.nullClass) {
1333-
if (inferrer.isNonNullableByDefault) {
1334-
return isNullAware ? const NeverType(Nullability.nonNullable) : null;
1335-
} else {
1336-
return isNullAware ? spreadType : null;
1337-
}
1331+
DartType typeBound = inferrer.resolveTypeParameter(spreadType);
1332+
if (inferrer.coreTypes.isNull(typeBound)) {
1333+
if (inferrer.isNonNullableByDefault) {
1334+
return isNullAware ? const NeverType(Nullability.nonNullable) : null;
1335+
} else {
1336+
return isNullAware ? inferrer.coreTypes.nullType : null;
13381337
}
1338+
}
1339+
if (typeBound is InterfaceType) {
13391340
List<DartType> supertypeArguments = inferrer.typeSchemaEnvironment
13401341
.getTypeArgumentsAsInstanceOf(
1341-
spreadType, inferrer.coreTypes.iterableClass);
1342-
if (supertypeArguments == null) return null;
1342+
typeBound, inferrer.coreTypes.iterableClass);
1343+
if (supertypeArguments == null) {
1344+
return null;
1345+
}
13431346
return supertypeArguments.single;
1347+
} else if (spreadType is DynamicType) {
1348+
return const DynamicType();
1349+
} else if (inferrer.coreTypes.isBottom(spreadType)) {
1350+
return const NeverType(Nullability.nonNullable);
13441351
}
1345-
if (spreadType is DynamicType) return const DynamicType();
13461352
return null;
13471353
}
13481354

@@ -1374,11 +1380,12 @@ class InferenceVisitor
13741380
DartType spreadElementType =
13751381
getSpreadElementType(spreadType, element.isNullAware);
13761382
if (spreadElementType == null) {
1377-
if (spreadType is InterfaceType &&
1378-
spreadType.classNode == inferrer.coreTypes.nullClass &&
1383+
if (inferrer.coreTypes
1384+
.isNull(inferrer.resolveTypeParameter(spreadType)) &&
13791385
!element.isNullAware) {
13801386
replacement = inferrer.helper.buildProblem(
1381-
messageNonNullAwareSpreadIsNull,
1387+
templateNonNullAwareSpreadIsNull.withArguments(
1388+
spreadType, inferrer.isNonNullableByDefault),
13821389
element.expression.fileOffset,
13831390
1);
13841391
} else {
@@ -1734,28 +1741,28 @@ class InferenceVisitor
17341741
// is a function type, the original values in output are preserved.
17351742
void storeSpreadMapEntryElementTypes(DartType spreadMapEntryType,
17361743
bool isNullAware, List<DartType> output, int offset) {
1737-
if (spreadMapEntryType is InterfaceType) {
1738-
if (spreadMapEntryType.classNode == inferrer.coreTypes.nullClass) {
1739-
if (isNullAware) {
1740-
if (inferrer.isNonNullableByDefault) {
1741-
output[offset] =
1742-
output[offset + 1] = const NeverType(Nullability.nonNullable);
1743-
} else {
1744-
output[offset] = output[offset + 1] = spreadMapEntryType;
1745-
}
1746-
}
1747-
} else {
1748-
List<DartType> supertypeArguments = inferrer.typeSchemaEnvironment
1749-
.getTypeArgumentsAsInstanceOf(
1750-
spreadMapEntryType, inferrer.coreTypes.mapClass);
1751-
if (supertypeArguments != null) {
1752-
output[offset] = supertypeArguments[0];
1753-
output[offset + 1] = supertypeArguments[1];
1744+
DartType typeBound = inferrer.resolveTypeParameter(spreadMapEntryType);
1745+
if (inferrer.coreTypes.isNull(typeBound)) {
1746+
if (isNullAware) {
1747+
if (inferrer.isNonNullableByDefault) {
1748+
output[offset] =
1749+
output[offset + 1] = const NeverType(Nullability.nonNullable);
1750+
} else {
1751+
output[offset] = output[offset + 1] = inferrer.coreTypes.nullType;
17541752
}
17551753
}
1756-
}
1757-
if (spreadMapEntryType is DynamicType) {
1754+
} else if (typeBound is InterfaceType) {
1755+
List<DartType> supertypeArguments = inferrer.typeSchemaEnvironment
1756+
.getTypeArgumentsAsInstanceOf(typeBound, inferrer.coreTypes.mapClass);
1757+
if (supertypeArguments != null) {
1758+
output[offset] = supertypeArguments[0];
1759+
output[offset + 1] = supertypeArguments[1];
1760+
}
1761+
} else if (spreadMapEntryType is DynamicType) {
17581762
output[offset] = output[offset + 1] = const DynamicType();
1763+
} else if (inferrer.coreTypes.isBottom(spreadMapEntryType)) {
1764+
output[offset] =
1765+
output[offset + 1] = const NeverType(Nullability.nonNullable);
17591766
}
17601767
}
17611768

@@ -1800,12 +1807,15 @@ class InferenceVisitor
18001807
MapEntry replacement = entry;
18011808
if (typeChecksNeeded) {
18021809
if (actualKeyType == null) {
1803-
if (spreadType is InterfaceType &&
1804-
spreadType.classNode == inferrer.coreTypes.nullClass &&
1810+
if (inferrer.coreTypes
1811+
.isNull(inferrer.resolveTypeParameter(spreadType)) &&
18051812
!entry.isNullAware) {
18061813
replacement = new MapEntry(
1807-
inferrer.helper.buildProblem(messageNonNullAwareSpreadIsNull,
1808-
entry.expression.fileOffset, 1),
1814+
inferrer.helper.buildProblem(
1815+
templateNonNullAwareSpreadIsNull.withArguments(
1816+
spreadType, inferrer.isNonNullableByDefault),
1817+
entry.expression.fileOffset,
1818+
1),
18091819
new NullLiteral())
18101820
..fileOffset = entry.fileOffset;
18111821
} else if (actualElementType != null) {

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,9 +154,8 @@ class TypeLabeler implements DartTypeVisitor<void>, ConstantVisitor<void> {
154154
}
155155

156156
void visitNeverType(NeverType node) {
157-
// TODO(askesc): Consider throwing internal error if NeverType appears in
158-
// diagnostics.
159157
result.add("Never");
158+
addNullability(node.declaredNullability);
160159
}
161160

162161
void visitDynamicType(DynamicType node) {

pkg/front_end/messages.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3914,7 +3914,7 @@ SpreadMapElement:
39143914
severity: CONTEXT
39153915

39163916
NonNullAwareSpreadIsNull:
3917-
template: "Can't spread a value with static type Null."
3917+
template: "Can't spread a value with static type '#type'."
39183918
script: >
39193919
main() {
39203920
<int>[...null];

pkg/front_end/testcases/general/spread_collection_inference.dart.strong.expect

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,23 @@ library;
7676
// Map<String, String> map61 = <String, String>{...mapSpread};
7777
// ^
7878
//
79-
// pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type Null.
79+
// pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
8080
// List<int> lhs70 = <int>[...null];
8181
// ^
8282
//
83-
// pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type Null.
83+
// pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type 'Null'.
8484
// Set<int> set70 = <int>{...null};
8585
// ^
8686
//
87-
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Can't spread a value with static type Null.
87+
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Can't spread a value with static type 'Null'.
8888
// ...null,
8989
// ^
9090
//
9191
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Expected ',' before this.
9292
// ...null,
9393
// ^
9494
//
95-
// pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type Null.
95+
// pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type 'Null'.
9696
// Map<String, int> map70 = <String, int>{...null};
9797
// ^
9898
//
@@ -302,10 +302,10 @@ Try providing type arguments for the literal explicitly to disambiguate it.
302302
core::Map<core::String*, core::String*>* map61 = <core::String*, core::String*>{null: invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:129:51: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
303303
Map<String, String> map61 = <String, String>{...mapSpread};
304304
^"};
305-
core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type Null.
305+
core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
306306
List<int> lhs70 = <int>[...null];
307307
^"];
308-
core::Set<core::int*>* set70 = let final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t67 = #t66.{core::Set::add}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type Null.
308+
core::Set<core::int*>* set70 = let final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>() in let final dynamic #t67 = #t66.{core::Set::add}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type 'Null'.
309309
Set<int> set70 = <int>{...null};
310310
^") in #t66;
311311
core::Set<dynamic>* set71ambiguous = block {
@@ -318,7 +318,7 @@ Try providing type arguments for the literal explicitly to disambiguate it.
318318
#t68.{core::Set::add}(#t70);
319319
}
320320
} =>#t68;
321-
core::Map<core::String*, core::int*>* map70 = <core::String*, core::int*>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type Null.
321+
core::Map<core::String*, core::int*>* map70 = <core::String*, core::int*>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type 'Null'.
322322
Map<String, int> map70 = <String, int>{...null};
323323
^": null};
324324
core::List<core::int*>* lhs80 = block {

pkg/front_end/testcases/general/spread_collection_inference.dart.strong.transformed.expect

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -76,23 +76,23 @@ library;
7676
// Map<String, String> map61 = <String, String>{...mapSpread};
7777
// ^
7878
//
79-
// pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type Null.
79+
// pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
8080
// List<int> lhs70 = <int>[...null];
8181
// ^
8282
//
83-
// pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type Null.
83+
// pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type 'Null'.
8484
// Set<int> set70 = <int>{...null};
8585
// ^
8686
//
87-
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Can't spread a value with static type Null.
87+
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Can't spread a value with static type 'Null'.
8888
// ...null,
8989
// ^
9090
//
9191
// pkg/front_end/testcases/general/spread_collection_inference.dart:137:8: Error: Expected ',' before this.
9292
// ...null,
9393
// ^
9494
//
95-
// pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type Null.
95+
// pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type 'Null'.
9696
// Map<String, int> map70 = <String, int>{...null};
9797
// ^
9898
//
@@ -431,10 +431,10 @@ Try providing type arguments for the literal explicitly to disambiguate it.
431431
core::Map<core::String*, core::String*>* map61 = <core::String*, core::String*>{null: invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:129:51: Error: Can't assign spread entry values of type 'int' to map entry values of type 'String'.
432432
Map<String, String> map61 = <String, String>{...mapSpread};
433433
^"};
434-
core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type Null.
434+
core::List<core::int*>* lhs70 = <core::int*>[invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:131:30: Error: Can't spread a value with static type 'Null'.
435435
List<int> lhs70 = <int>[...null];
436436
^"];
437-
core::Set<core::int*>* set70 = let final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>() in let final core::bool #t67 = #t66.{core::Set::add}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type Null.
437+
core::Set<core::int*>* set70 = let final core::Set<core::int*>* #t66 = col::LinkedHashSet::•<core::int*>() in let final core::bool #t67 = #t66.{core::Set::add}(invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:133:29: Error: Can't spread a value with static type 'Null'.
438438
Set<int> set70 = <int>{...null};
439439
^") in #t66;
440440
core::Set<dynamic>* set71ambiguous = block {
@@ -453,7 +453,7 @@ Try providing type arguments for the literal explicitly to disambiguate it.
453453
}
454454
}
455455
} =>#t68;
456-
core::Map<core::String*, core::int*>* map70 = <core::String*, core::int*>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type Null.
456+
core::Map<core::String*, core::int*>* map70 = <core::String*, core::int*>{invalid-expression "pkg/front_end/testcases/general/spread_collection_inference.dart:142:45: Error: Can't spread a value with static type 'Null'.
457457
Map<String, int> map70 = <String, int>{...null};
458458
^": null};
459459
core::List<core::int*>* lhs80 = block {

0 commit comments

Comments
 (0)