Tests for implicit cast properties; add cast for `<T>[...dynamic]`.
Change-Id: Ia04c75d304dc6673c9f637c9007a8eb60062078c
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/97461
Auto-Submit: Mike Fairhurst <mfairhurst@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Nicholas Shahan <nshahan@google.com>
Commit-Queue: Mike Fairhurst <mfairhurst@google.com>
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index 68d8bd2..ccc800d 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -189,13 +189,12 @@
var asIterableType = exprType is InterfaceTypeImpl
? exprType.asInstanceOf(typeProvider.iterableType.element)
: null;
- if (asIterableType != null) {
- var elementType = asIterableType.typeArguments[0];
- // Items in the spread will then potentially be downcast to the expected
- // type.
- _checkImplicitCast(element.expression, expectedType,
- from: elementType, forSpread: true);
- }
+ var elementType =
+ asIterableType == null ? null : asIterableType.typeArguments[0];
+ // Items in the spread will then potentially be downcast to the expected
+ // type.
+ _checkImplicitCast(element.expression, expectedType,
+ from: elementType, forSpread: true);
}
}
@@ -229,16 +228,16 @@
? exprType.asInstanceOf(typeProvider.mapType.element)
: null;
- if (asMapType != null) {
- var elementKeyType = asMapType.typeArguments[0];
- var elementValueType = asMapType.typeArguments[1];
- // Keys and values in the spread will then potentially be downcast to
- // the expected types.
- _checkImplicitCast(element.expression, expectedKeyType,
- from: elementKeyType, forSpreadKey: true);
- _checkImplicitCast(element.expression, expectedValueType,
- from: elementValueType, forSpreadValue: true);
- }
+ var elementKeyType =
+ asMapType == null ? null : asMapType.typeArguments[0];
+ var elementValueType =
+ asMapType == null ? null : asMapType.typeArguments[1];
+ // Keys and values in the spread will then potentially be downcast to
+ // the expected types.
+ _checkImplicitCast(element.expression, expectedKeyType,
+ from: elementKeyType, forSpreadKey: true);
+ _checkImplicitCast(element.expression, expectedValueType,
+ from: elementValueType, forSpreadValue: true);
}
}
diff --git a/pkg/analyzer/test/generated/strong_mode_test.dart b/pkg/analyzer/test/generated/strong_mode_test.dart
index 4b8c461..15570bb 100644
--- a/pkg/analyzer/test/generated/strong_mode_test.dart
+++ b/pkg/analyzer/test/generated/strong_mode_test.dart
@@ -8,6 +8,7 @@
import 'package:analyzer/dart/ast/standard_resolution_map.dart';
import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/dart/element/element.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/engine.dart';
@@ -26,6 +27,7 @@
defineReflectiveTests(StrongModeLocalInferenceTest);
defineReflectiveTests(StrongModeStaticTypeAnalyzer2Test);
defineReflectiveTests(StrongModeTypePropagationTest);
+ defineReflectiveTests(StrongModeSpreadCastsTest);
});
}
@@ -2823,6 +2825,622 @@
}
@reflectiveTest
+class StrongModeSpreadCastsTest extends ResolverTestCase {
+ @override
+ List<String> get enabledExperiments => [EnableString.spread_collections];
+
+ @override
+ bool get enableNewAnalysisDriver => true;
+
+ test_implicitCastMetadata_spread_list_elements() async {
+ var source = addSource(r'''
+class C {
+ dynamic dyn;
+ Iterable<int> iInt;
+ Iterable<Object> iObject;
+ Iterable<dynamic> iDynamic;
+ Iterable<Null> iNull;
+ List<int> lInt;
+ List<Object> lObject;
+ List<dynamic> lDynamic;
+ List<Null> lNull;
+
+ void casts() {
+ <int>[...dyn];
+ <num>[...dyn];
+ <int>[...iObject];
+ <int>[...iDynamic];
+ <int>[...lObject];
+ <int>[...lDynamic];
+ <Null>[...dyn];
+ <Null>[...iObject];
+ <Null>[...iDynamic];
+ <Null>[...iInt];
+ <Null>[...lObject];
+ <Null>[...lDynamic];
+ <Null>[...lInt];
+ }
+
+ void noCasts() {
+ [...dyn];
+ <dynamic>[...dyn];
+ <Object>[...dyn];
+ <dynamic>[...iInt];
+ <Object>[...iInt];
+ <Object>[...iNull];
+ <dynamic>[...lInt];
+ <Object>[...lInt];
+ <Object>[...lNull];
+ <dynamic>[...iObject];
+ <Object>[...iObject];
+ <Object>[...iNull];
+ <dynamic>[...lObject];
+ <Object>[...lObject];
+ <Object>[...lNull];
+ <dynamic>[...iDynamic];
+ <Object>[...iDynamic];
+ <Object>[...iNull];
+ <dynamic>[...lDynamic];
+ <Object>[...lDynamic];
+ <Object>[...lNull];
+ <num>[...iInt];
+ <num>[...lInt];
+ <num>[...iNull];
+ <num>[...lNull];
+ <int>[...iInt];
+ <int>[...lInt];
+ <int>[...iNull];
+ <int>[...lNull];
+ <Null>[...iNull];
+ <Null>[...lNull];
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(ExpressionStatement s) {
+ ListLiteral literal = s.expression;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ DartType getListElementType(ExpressionStatement s) {
+ ListLiteral literal = s.expression;
+ return literal.typeArguments.arguments[0].type;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType, equals(getListElementType(s)));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_list_iterable() async {
+ var source = addSource(r'''
+class C {
+ dynamic dyn;
+ Iterable<int> iInt;
+ Iterable<Object> iObject;
+ Iterable<dynamic> iDynamic;
+ Iterable<Null> iNull;
+ List<int> lInt;
+ List<Object> lObject;
+ List<dynamic> lDynamic;
+ List<Null> lNull;
+
+ void casts() {
+ [...dyn];
+ <int>[...dyn];
+ <num>[...dyn];
+ }
+
+ void noCasts() {
+ [...iInt];
+ [...iObject];
+ [...iDynamic];
+ [...iNull];
+ <Null>[...iInt];
+ <Null>[...iObject];
+ <Null>[...iDynamic];
+ <Null>[...iNull];
+ <int>[...iInt];
+ <int>[...iObject];
+ <int>[...iDynamic];
+ <int>[...iNull];
+ [...lInt];
+ [...lObject];
+ [...lDynamic];
+ [...lNull];
+ <Null>[...lInt];
+ <Null>[...lObject];
+ <Null>[...lDynamic];
+ <Null>[...lNull];
+ <int>[...lInt];
+ <int>[...lObject];
+ <int>[...lDynamic];
+ <int>[...lNull];
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(ExpressionStatement e) {
+ ListLiteral expression = e.expression;
+ SpreadElement spread = expression.elements[0];
+ return spread.expression;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType.toString(), equals('Iterable<dynamic>'));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_map_keys() async {
+ var source = addSource(r'''
+abstract class HashMap<K, V> implements Map<K, V> {}
+class C {
+ dynamic dyn;
+ Map<int, dynamic> mIntDynamic;
+ Map<Object, dynamic> mObjectDynamic;
+ Map<dynamic, dynamic> mDynamicDynamic;
+ Map<Null, dynamic> mNullDynamic;
+ HashMap<int, dynamic> hIntDynamic;
+ HashMap<Object, dynamic> hObjectDynamic;
+ HashMap<dynamic, dynamic> hDynamicDynamic;
+ HashMap<Null, dynamic> hNullDynamic;
+
+ void casts() {
+ Map m0 = <int, dynamic>{...dyn};
+ Map m1 = <num, dynamic>{...dyn};
+ Map m2 = <int, dynamic>{...mObjectDynamic};
+ Map m3 = <int, dynamic>{...mDynamicDynamic};
+ Map m4 = <int, dynamic>{...hObjectDynamic};
+ Map m5 = <int, dynamic>{...hDynamicDynamic};
+ Map m6 = <Null, dynamic>{...dyn};
+ Map m7 = <Null, dynamic>{...mObjectDynamic};
+ Map m8 = <Null, dynamic>{...mDynamicDynamic};
+ Map m9 = <Null, dynamic>{...mIntDynamic};
+ Map m10 = <Null, dynamic>{...hObjectDynamic};
+ Map m11 = <Null, dynamic>{...hDynamicDynamic};
+ Map m12 = <Null, dynamic>{...hIntDynamic};
+ }
+
+ void noCasts() {
+ Map m0 = {...dyn};
+ Map m1 = <dynamic, dynamic>{...dyn};
+ Map m2 = <Object, dynamic>{...dyn};
+ Map m3 = <dynamic, dynamic>{...mIntDynamic};
+ Map m4 = <Object, dynamic>{...mIntDynamic};
+ Map m5 = <Object, dynamic>{...mNullDynamic};
+ Map m6 = <dynamic, dynamic>{...hIntDynamic};
+ Map m7 = <Object, dynamic>{...hIntDynamic};
+ Map m8 = <Object, dynamic>{...hNullDynamic};
+ Map m9 = <dynamic, dynamic>{...mObjectDynamic};
+ Map m10 = <Object, dynamic>{...mObjectDynamic};
+ Map m11 = <Object, dynamic>{...mNullDynamic};
+ Map m12 = <dynamic, dynamic>{...hObjectDynamic};
+ Map m13 = <Object, dynamic>{...hObjectDynamic};
+ Map m14 = <Object, dynamic>{...hNullDynamic};
+ Map m15 = <dynamic, dynamic>{...mDynamicDynamic};
+ Map m16 = <Object, dynamic>{...mDynamicDynamic};
+ Map m17 = <Object, dynamic>{...mNullDynamic};
+ Map m18 = <dynamic, dynamic>{...hDynamicDynamic};
+ Map m19 = <Object, dynamic>{...hDynamicDynamic};
+ Map m20 = <Object, dynamic>{...hNullDynamic};
+ Map m21 = <num, dynamic>{...mIntDynamic};
+ Map m22 = <num, dynamic>{...hIntDynamic};
+ Map m23 = <num, dynamic>{...mNullDynamic};
+ Map m24 = <num, dynamic>{...hNullDynamic};
+ Map m25 = <int, dynamic>{...hIntDynamic};
+ Map m26 = <int, dynamic>{...mIntDynamic};
+ Map m27 = <int, dynamic>{...mNullDynamic};
+ Map m28 = <int, dynamic>{...hNullDynamic};
+ Map m29 = <Null, dynamic>{...mNullDynamic};
+ Map m30 = <Null, dynamic>{...hNullDynamic};
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ DartType getSetElementType(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ return literal.typeArguments.arguments[0].type;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadKeyCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType, equals(getSetElementType(s)));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadKeyCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_map_map() async {
+ var source = addSource(r'''
+abstract class HashMap<K, V> implements Map<K, V> {}
+class C {
+ dynamic dyn;
+ Map<int, int> mIntInt;
+ Map<int, Object> mIntObject;
+ Map<Object, int> mObjectInt;
+ Map<Object, Object> mObjectObject;
+ Map<dynamic, dynamic> mDynamicDynamic;
+ Map<Null, Null> mNullNull;
+ Map<Object, Null> mObjectNull;
+ Map<Null, Object> mNullObject;
+ HashMap<int, int> hIntInt;
+ HashMap<int, Object> hIntObject;
+ HashMap<Object, int> hObjectInt;
+ HashMap<Object, Object> hObjectObject;
+ HashMap<dynamic, dynamic> hDynamicDynamic;
+ HashMap<Null, Null> hNullNull;
+
+ void casts() {
+ Map m0 = {...dyn};
+ Map m1 = <int, int>{...dyn};
+ Map m2 = <num, int>{...dyn};
+ Map m3 = <int, num>{...dyn};
+ Map m4 = <num, num>{...dyn};
+ }
+
+ void noCasts() {
+ Map m0 = {...mIntInt};
+ Map m1 = {...mIntObject};
+ Map m2 = {...mObjectInt};
+ Map m3 = {...mObjectObject};
+ Map m4 = {...mDynamicDynamic};
+ Map m5 = {...mNullObject};
+ Map m6 = {...mObjectNull};
+ Map m7 = {...mNullNull};
+ Map m8 = <Null, Null>{...mIntInt};
+ Map m9 = <Null, Null>{...mObjectObject};
+ Map m10 = <Null, Null>{...mDynamicDynamic};
+ Map m11 = <Null, Null>{...mNullNull};
+ Map m12 = <int, int>{...mIntInt};
+ Map m13 = <int, int>{...mObjectObject};
+ Map m14 = <int, int>{...mDynamicDynamic};
+ Map m15 = <int, int>{...mNullNull};
+ Map m16 = {...hIntInt};
+ Map m17 = {...hObjectObject};
+ Map m18 = {...hDynamicDynamic};
+ Map m19 = {...hNullNull};
+ Map m20 = <Null, Null>{...hIntInt};
+ Map m21 = <Null, Null>{...hObjectObject};
+ Map m22 = <Null, Null>{...hDynamicDynamic};
+ Map m23 = <Null, Null>{...hNullNull};
+ Map m24 = <int, int>{...hIntInt};
+ Map m25 = <int, int>{...hObjectObject};
+ Map m26 = <int, int>{...hDynamicDynamic};
+ Map m27 = <int, int>{...hNullNull};
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType.toString(), equals('Map<dynamic, dynamic>'));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_map_values() async {
+ var source = addSource(r'''
+abstract class HashMap<K, V> implements Map<K, V> {}
+class C {
+ dynamic dyn;
+ Map<dynamic, int> mDynamicInt;
+ Map<dynamic, Object> mDynamicObject;
+ Map<dynamic, dynamic> mDynamicDynamic;
+ Map<dynamic, Null> mDynamicNull;
+ HashMap<dynamic, int> hDynamicInt;
+ HashMap<dynamic, Object> hDynamicObject;
+ HashMap<dynamic, dynamic> hDynamicDynamic;
+ HashMap<dynamic, Null> hDynamicNull;
+
+ void casts() {
+ Map m0 = <dynamic, int>{...dyn};
+ Map m1 = <dynamic, num>{...dyn};
+ Map m2 = <dynamic, int>{...mDynamicObject};
+ Map m3 = <dynamic, int>{...mDynamicDynamic};
+ Map m4 = <dynamic, int>{...hDynamicObject};
+ Map m5 = <dynamic, int>{...hDynamicDynamic};
+ Map m6 = <dynamic, Null>{...dyn};
+ Map m7 = <dynamic, Null>{...mDynamicObject};
+ Map m8 = <dynamic, Null>{...mDynamicDynamic};
+ Map m9 = <dynamic, Null>{...mDynamicInt};
+ Map m10 = <dynamic, Null>{...hDynamicObject};
+ Map m11 = <dynamic, Null>{...hDynamicDynamic};
+ Map m12 = <dynamic, Null>{...hDynamicInt};
+ }
+
+ void noCasts() {
+ Map m0 = {...dyn};
+ Map m1 = <dynamic, dynamic>{...dyn};
+ Map m2 = <dynamic, Object>{...dyn};
+ Map m3 = <dynamic, dynamic>{...mDynamicInt};
+ Map m4 = <dynamic, Object>{...mDynamicInt};
+ Map m5 = <dynamic, Object>{...mDynamicNull};
+ Map m6 = <dynamic, dynamic>{...hDynamicInt};
+ Map m7 = <dynamic, Object>{...hDynamicInt};
+ Map m8 = <dynamic, Object>{...hDynamicNull};
+ Map m9 = <dynamic, dynamic>{...mDynamicObject};
+ Map m10 = <dynamic, Object>{...mDynamicObject};
+ Map m11 = <dynamic, Object>{...mDynamicNull};
+ Map m12 = <dynamic, dynamic>{...hDynamicObject};
+ Map m13 = <dynamic, Object>{...hDynamicObject};
+ Map m14 = <dynamic, Object>{...hDynamicNull};
+ Map m15 = <dynamic, dynamic>{...mDynamicDynamic};
+ Map m16 = <dynamic, Object>{...mDynamicDynamic};
+ Map m17 = <dynamic, Object>{...mDynamicNull};
+ Map m18 = <dynamic, dynamic>{...hDynamicDynamic};
+ Map m19 = <dynamic, Object>{...hDynamicDynamic};
+ Map m20 = <dynamic, Object>{...hDynamicNull};
+ Map m21 = <dynamic, num>{...mDynamicInt};
+ Map m22 = <dynamic, num>{...hDynamicInt};
+ Map m23 = <dynamic, num>{...mDynamicNull};
+ Map m24 = <dynamic, num>{...hDynamicNull};
+ Map m25 = <dynamic, int>{...hDynamicInt};
+ Map m26 = <dynamic, int>{...mDynamicInt};
+ Map m27 = <dynamic, int>{...mDynamicNull};
+ Map m28 = <dynamic, int>{...hDynamicNull};
+ Map m29 = <dynamic, Null>{...mDynamicNull};
+ Map m30 = <dynamic, Null>{...hDynamicNull};
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ DartType getValueType(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ return literal.typeArguments.arguments[1].type;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadValueCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType, equals(getValueType(s)));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadValueCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_set_elements() async {
+ var source = addSource(r'''
+class C {
+ dynamic dyn;
+ Iterable<int> iInt;
+ Iterable<Object> iObject;
+ Iterable<dynamic> iDynamic;
+ Iterable<Null> iNull;
+ List<int> lInt;
+ List<Object> lObject;
+ List<dynamic> lDynamic;
+ List<Null> lNull;
+
+ void casts() {
+ Set s0 = <int>{...dyn};
+ Set s1 = <num>{...dyn};
+ Set s2 = <int>{...iObject};
+ Set s3 = <int>{...iDynamic};
+ Set s4 = <int>{...lObject};
+ Set s5 = <int>{...lDynamic};
+ Set s6 = <Null>{...dyn};
+ Set s7 = <Null>{...iObject};
+ Set s8 = <Null>{...iDynamic};
+ Set s9 = <Null>{...iInt};
+ Set s10 = <Null>{...lObject};
+ Set s11 = <Null>{...lDynamic};
+ Set s12 = <Null>{...lInt};
+ }
+
+ void noCasts() {
+ Set s0 = {...dyn};
+ Set s1 = <dynamic>{...dyn};
+ Set s2 = <Object>{...dyn};
+ Set s3 = <dynamic>{...iInt};
+ Set s4 = <Object>{...iInt};
+ Set s5 = <Object>{...iNull};
+ Set s6 = <dynamic>{...lInt};
+ Set s7 = <Object>{...lInt};
+ Set s8 = <Object>{...lNull};
+ Set s9 = <dynamic>{...iObject};
+ Set s10 = <Object>{...iObject};
+ Set s11 = <Object>{...iNull};
+ Set s12 = <dynamic>{...lObject};
+ Set s13 = <Object>{...lObject};
+ Set s14 = <Object>{...lNull};
+ Set s15 = <dynamic>{...iDynamic};
+ Set s16 = <Object>{...iDynamic};
+ Set s17 = <Object>{...iNull};
+ Set s18 = <dynamic>{...lDynamic};
+ Set s19 = <Object>{...lDynamic};
+ Set s20 = <Object>{...lNull};
+ Set s21 = <num>{...iInt};
+ Set s22 = <num>{...lInt};
+ Set s23 = <num>{...iNull};
+ Set s24 = <num>{...lNull};
+ Set s25 = <int>{...iInt};
+ Set s26 = <int>{...lInt};
+ Set s27 = <int>{...iNull};
+ Set s28 = <int>{...lNull};
+ Set s29 = <Null>{...iNull};
+ Set s30 = <Null>{...lNull};
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ DartType getKeyType(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ return literal.typeArguments.arguments[0].type;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType, equals(getKeyType(s)));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitSpreadCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+
+ test_implicitCastMetadata_spread_set_iterable() async {
+ var source = addSource(r'''
+class C {
+ dynamic dyn;
+ Iterable<int> iInt;
+ Iterable<Object> iObject;
+ Iterable<dynamic> iDynamic;
+ Iterable<Null> iNull;
+ List<int> lInt;
+ List<Object> lObject;
+ List<dynamic> lDynamic;
+ List<Null> lNull;
+
+ void casts() {
+ Set s0 = {...dyn};
+ Set s1 = <int>{...dyn};
+ Set s2 = <num>{...dyn};
+ }
+
+ void noCasts() {
+ Set s0 = {...iInt};
+ Set s1 = {...iObject};
+ Set s2 = {...iDynamic};
+ Set s3 = {...iNull};
+ Set s4 = <Null>{...iInt};
+ Set s5 = <Null>{...iObject};
+ Set s6 = <Null>{...iDynamic};
+ Set s7 = <Null>{...iNull};
+ Set s8 = <int>{...iInt};
+ Set s9 = <int>{...iObject};
+ Set s10 = <int>{...iDynamic};
+ Set s11 = <int>{...iNull};
+ Set s12 = {...lInt};
+ Set s13 = {...lObject};
+ Set s14 = {...lDynamic};
+ Set s15 = {...lNull};
+ Set s16 = <Null>{...lInt};
+ Set s17 = <Null>{...lObject};
+ Set s18 = <Null>{...lDynamic};
+ Set s19 = <Null>{...lNull};
+ Set s20 = <int>{...lInt};
+ Set s21 = <int>{...lObject};
+ Set s22 = <int>{...lDynamic};
+ }
+}
+''');
+ var unit = (await computeAnalysisResult(source)).unit;
+ assertNoErrors(source);
+
+ Expression getSpreadExpression(VariableDeclarationStatement s) {
+ VariableDeclaration declaration = s.variables.variables[0];
+ SetOrMapLiteral literal = declaration.initializer;
+ SpreadElement spread = literal.elements[0];
+ return spread.expression;
+ }
+
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'casts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNotNull,
+ reason: 'Expression $expression does not have implicit cast');
+ expect(spreadCastType.toString(), equals('Iterable<dynamic>'));
+ }
+ for (var s in AstFinder.getStatementsInMethod(unit, 'C', 'noCasts')) {
+ var expression = getSpreadExpression(s);
+ var spreadCastType = getImplicitCast(expression);
+ expect(spreadCastType, isNull,
+ reason: 'Expression $expression should not have implicit cast');
+ }
+ }
+}
+
+@reflectiveTest
class StrongModeStaticTypeAnalyzer2Test extends StaticTypeAnalyzer2TestShared
with StrongModeStaticTypeAnalyzer2TestCases {
@override