Version 2.16.0-2.0.dev
Merge commit 'ac78f998830e08e82f47095ae3c5c9b30e7444db' into 'dev'
diff --git a/.dart_tool/package_config.json b/.dart_tool/package_config.json
index 4281850..a988d58 100644
--- a/.dart_tool/package_config.json
+++ b/.dart_tool/package_config.json
@@ -11,7 +11,7 @@
"constraint, update this by running tools/generate_package_config.dart."
],
"configVersion": 2,
- "generated": "2021-10-26T10:20:01.277340",
+ "generated": "2021-11-10T09:58:01.876670",
"generator": "tools/generate_package_config.dart",
"packages": [
{
@@ -124,7 +124,7 @@
"name": "bazel_worker",
"rootUri": "../third_party/pkg/bazel_worker",
"packageUri": "lib/",
- "languageVersion": "2.12"
+ "languageVersion": "2.14"
},
{
"name": "benchmark_harness",
diff --git a/DEPS b/DEPS
index 8c0e608..e93a12b 100644
--- a/DEPS
+++ b/DEPS
@@ -76,7 +76,7 @@
# Revisions of /third_party/* dependencies.
"args_rev": "3b3f55766af13d895d2020ec001a28e8dc147f91",
"async_rev": "80886150a5e6c58006c8ae5a6c2aa7108638e2a9",
- "bazel_worker_rev": "0885637b037979afbf5bcd05fd748b309fd669c0",
+ "bazel_worker_rev": "ceeba0982d4ff40d32371c9d35f3d2dc1868de20",
"benchmark_harness_rev": "c546dbd9f639f75cd2f75de8df2eb9f8ea15e8e7",
"boolean_selector_rev": "665e6921ab246569420376f827bff4585dff0b14",
"boringssl_gen_rev": "7322fc15cc065d8d2957fccce6b62a509dc4d641",
@@ -141,7 +141,7 @@
"process_rev": "56ece43b53b64c63ae51ec184b76bd5360c28d0b",
"protobuf_rev": "c1eb6cb51af39ccbaa1a8e19349546586a5c8e31",
"pub_rev": "96404e0749864c9fbf8b12e1d424e8078809e00a",
- "pub_semver_rev": "a43ad72fb6b7869607581b5fedcb186d1e74276a",
+ "pub_semver_rev": "cee044a3dc867c1c8464408ed435bd21949510c0",
"root_certificates_rev": "692f6d6488af68e0121317a9c2c9eb393eb0ee50",
"rust_revision": "b7856f695d65a8ebc846754f97d15814bcb1c244",
"shelf_static_rev": "202ec1a53c9a830c17cf3b718d089cf7eba568ad",
diff --git a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
index 96389a0..56442ae 100644
--- a/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
+++ b/pkg/analysis_server/lib/src/services/correction/dart/abstract_producer.dart
@@ -239,10 +239,6 @@
final AstNode node;
- /// A map keyed by lock names whose value is a list of the ranges for which a
- /// lock has already been acquired.
- final Map<String, List<SourceRange>> _lockRanges = {};
-
CorrectionProducerContext._({
required this.resolvedResult,
required this.workspace,
@@ -458,26 +454,6 @@
CorrectionUtils get utils => _context.utils;
- /// Return `true` if this is the first request to lock the given [range] for
- /// the lock with the given [lockName], or false if a lock for that range has
- /// already been acquired.
- ///
- /// This method is used to allow correction producers to guard against
- /// repeating changes that have already been made. For example, if multiple
- /// arguments in an argument list have diagnostics reported against them and
- /// the fix will fix all of the arguments, then the fix should be applied for
- /// the first diagnostic and not for the others. A correction producer can
- /// ensure this behavior by attempting to acquire a lock prior to creating any
- /// edits, and only create the edits if a lock could be acquired.
- bool acquireLockOnRange(String lockName, SourceRange range) {
- var ranges = _context._lockRanges.putIfAbsent(lockName, () => []);
- if (ranges.contains(range)) {
- return false;
- }
- ranges.add(range);
- return true;
- }
-
/// Configure this producer based on the [context].
void configure(CorrectionProducerContext context) {
_context = context;
diff --git a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
index 6ea735c..c71ea13 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix/data_driven/modify_parameters.dart
@@ -59,9 +59,6 @@
// This should only happen if `validate` didn't check this case.
return;
}
- if (!fix.acquireLockOnRange('ModifyParameters', range.node(argumentList))) {
- return;
- }
var arguments = argumentList.arguments;
var argumentCount = arguments.length;
var templateContext = TemplateContext(invocation, fix.utils);
diff --git a/pkg/analyzer/lib/src/dart/analysis/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 319ddc6..6376bc1 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -221,11 +221,13 @@
_typeSystemLegacy?.updateOptions(
implicitCasts: analysisOptions.implicitCasts,
+ strictCasts: analysisOptions.strictCasts,
strictInference: analysisOptions.strictInference,
);
_typeSystemNonNullableByDefault?.updateOptions(
implicitCasts: analysisOptions.implicitCasts,
+ strictCasts: analysisOptions.strictCasts,
strictInference: analysisOptions.strictInference,
);
}
@@ -268,6 +270,7 @@
_typeSystemLegacy = TypeSystemImpl(
implicitCasts: _analysisOptions.implicitCasts,
isNonNullableByDefault: false,
+ strictCasts: _analysisOptions.strictCasts,
strictInference: _analysisOptions.strictInference,
typeProvider: legacy,
);
@@ -275,6 +278,7 @@
_typeSystemNonNullableByDefault = TypeSystemImpl(
implicitCasts: _analysisOptions.implicitCasts,
isNonNullableByDefault: true,
+ strictCasts: _analysisOptions.strictCasts,
strictInference: _analysisOptions.strictInference,
typeProvider: nonNullableByDefault,
);
diff --git a/pkg/analyzer/lib/src/dart/constant/value.dart b/pkg/analyzer/lib/src/dart/constant/value.dart
index 094b8b6..313caf6 100644
--- a/pkg/analyzer/lib/src/dart/constant/value.dart
+++ b/pkg/analyzer/lib/src/dart/constant/value.dart
@@ -518,6 +518,7 @@
var typeSystem = TypeSystemImpl(
implicitCasts: false,
isNonNullableByDefault: false,
+ strictCasts: false,
strictInference: false,
typeProvider: typeProvider,
);
diff --git a/pkg/analyzer/lib/src/dart/element/type_system.dart b/pkg/analyzer/lib/src/dart/element/type_system.dart
index ef329f4..b38a654 100644
--- a/pkg/analyzer/lib/src/dart/element/type_system.dart
+++ b/pkg/analyzer/lib/src/dart/element/type_system.dart
@@ -45,6 +45,11 @@
/// This affects the behavior of [isAssignableTo].
bool implicitCasts;
+ /// True if "strict casts" should be enforced.
+ ///
+ /// This affects the behavior of [isAssignableTo].
+ bool strictCasts;
+
/// A flag indicating whether inference failures are allowed, off by default.
///
/// This option is experimental and subject to change.
@@ -71,6 +76,7 @@
TypeSystemImpl({
required this.implicitCasts,
required this.isNonNullableByDefault,
+ required this.strictCasts,
required this.strictInference,
required TypeProvider typeProvider,
}) : typeProvider = typeProvider as TypeProviderImpl {
@@ -699,9 +705,10 @@
}
}
- // First make sure --no-implicit-casts disables all downcasts, including
- // dynamic casts.
- if (!implicitCasts) {
+ // First make sure that the static analysis options, `implicit-casts: false`
+ // and `strict-casts: true` disable all downcasts, including casts from
+ // `dynamic`.
+ if (!implicitCasts || strictCasts) {
return false;
}
@@ -1537,9 +1544,11 @@
void updateOptions({
required bool implicitCasts,
+ required bool strictCasts,
required bool strictInference,
}) {
this.implicitCasts = implicitCasts;
+ this.strictCasts = strictCasts;
this.strictInference = strictInference;
}
diff --git a/pkg/analyzer/lib/src/error/literal_element_verifier.dart b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
index a6962f4..05ee001 100644
--- a/pkg/analyzer/lib/src/error/literal_element_verifier.dart
+++ b/pkg/analyzer/lib/src/error/literal_element_verifier.dart
@@ -138,7 +138,15 @@
/// assigned to the [elementType] of the enclosing collection.
void _verifySpreadForListOrSet(bool isNullAware, Expression expression) {
var expressionType = expression.typeOrThrow;
- if (expressionType.isDynamic) return;
+ if (expressionType.isDynamic) {
+ if (typeSystem.strictCasts) {
+ return errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_ITERABLE_SPREAD,
+ expression,
+ );
+ }
+ return;
+ }
if (typeSystem.isNonNullableByDefault) {
if (typeSystem.isSubtypeOf(expressionType, NeverTypeImpl.instance)) {
@@ -224,7 +232,15 @@
/// its key and values are assignable to [mapKeyType] and [mapValueType].
void _verifySpreadForMap(bool isNullAware, Expression expression) {
var expressionType = expression.typeOrThrow;
- if (expressionType.isDynamic) return;
+ if (expressionType.isDynamic) {
+ if (typeSystem.strictCasts) {
+ return errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.NOT_MAP_SPREAD,
+ expression,
+ );
+ }
+ return;
+ }
if (typeSystem.isNonNullableByDefault) {
if (typeSystem.isSubtypeOf(expressionType, NeverTypeImpl.instance)) {
diff --git a/pkg/analyzer/lib/src/generated/engine.dart b/pkg/analyzer/lib/src/generated/engine.dart
index c678842..86b03d0 100644
--- a/pkg/analyzer/lib/src/generated/engine.dart
+++ b/pkg/analyzer/lib/src/generated/engine.dart
@@ -285,6 +285,9 @@
/// re-throwing them)
bool propagateLinterExceptions = false;
+ /// Whether implicit casts should be reported as potential problems.
+ bool strictCasts = false;
+
/// A flag indicating whether inference failures are allowed, off by default.
///
/// This option is experimental and subject to change.
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 85bde05..3dea90e 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -2259,6 +2259,26 @@
DartType iterableType = node.iterable.typeOrThrow;
+ Token? awaitKeyword;
+ var parent = node.parent;
+ if (parent is ForStatement) {
+ awaitKeyword = parent.awaitKeyword;
+ } else if (parent is ForElement) {
+ awaitKeyword = parent.awaitKeyword;
+ }
+
+ // Use an explicit string instead of [loopType] to remove the "<E>".
+ String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';
+
+ if (iterableType.isDynamic && typeSystem.strictCasts) {
+ errorReporter.reportErrorForNode(
+ CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
+ node.iterable,
+ [iterableType, loopNamedType],
+ );
+ return false;
+ }
+
// TODO(scheglov) use NullableDereferenceVerifier
if (_isNonNullableByDefault) {
if (typeSystem.isNullable(iterableType)) {
@@ -2275,14 +2295,6 @@
return false;
}
- Token? awaitKeyword;
- var parent = node.parent;
- if (parent is ForStatement) {
- awaitKeyword = parent.awaitKeyword;
- } else if (parent is ForElement) {
- awaitKeyword = parent.awaitKeyword;
- }
-
// The object being iterated has to implement Iterable<T> for some T that
// is assignable to the variable's type.
// TODO(rnystrom): Move this into mostSpecificTypeArgument()?
@@ -2297,8 +2309,6 @@
}
if (!typeSystem.isAssignableTo(iterableType, requiredSequenceType)) {
- // Use an explicit string instead of [loopType] to remove the "<E>".
- String loopNamedType = awaitKeyword != null ? 'Stream' : 'Iterable';
errorReporter.reportErrorForNode(
CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE,
node.iterable,
diff --git a/pkg/analyzer/lib/src/task/options.dart b/pkg/analyzer/lib/src/task/options.dart
index 6a393dc..73b4a73 100644
--- a/pkg/analyzer/lib/src/task/options.dart
+++ b/pkg/analyzer/lib/src/task/options.dart
@@ -139,6 +139,7 @@
static const String implicitDynamic = 'implicit-dynamic';
// Language options (see AnalysisOptionsImpl for documentation).
+ static const String strictCasts = 'strict-casts';
static const String strictInference = 'strict-inference';
static const String strictRawTypes = 'strict-raw-types';
@@ -177,7 +178,11 @@
];
/// Supported `analyzer` language options.
- static const List<String> languageOptions = [strictInference, strictRawTypes];
+ static const List<String> languageOptions = [
+ strictCasts,
+ strictInference,
+ strictRawTypes,
+ ];
/// Supported 'analyzer' optional checks options.
static const List<String> optionalChecksOptions = [
@@ -750,6 +755,9 @@
AnalysisOptionsImpl options, Object? feature, Object value) {
var boolValue = toBool(value);
if (boolValue != null) {
+ if (feature == AnalyzerOptions.strictCasts) {
+ options.strictCasts = boolValue;
+ }
if (feature == AnalyzerOptions.strictInference) {
options.strictInference = boolValue;
}
diff --git a/pkg/analyzer/test/generated/test_analysis_context.dart b/pkg/analyzer/test/generated/test_analysis_context.dart
index 840d225..bdfa64f 100644
--- a/pkg/analyzer/test/generated/test_analysis_context.dart
+++ b/pkg/analyzer/test/generated/test_analysis_context.dart
@@ -43,6 +43,7 @@
_typeSystemLegacy = TypeSystemImpl(
implicitCasts: _analysisOptions.implicitCasts,
isNonNullableByDefault: false,
+ strictCasts: _analysisOptions.strictCasts,
strictInference: _analysisOptions.strictInference,
typeProvider: _typeProviderLegacy,
);
@@ -50,6 +51,7 @@
_typeSystemNonNullableByDefault = TypeSystemImpl(
implicitCasts: _analysisOptions.implicitCasts,
isNonNullableByDefault: true,
+ strictCasts: _analysisOptions.strictCasts,
strictInference: _analysisOptions.strictInference,
typeProvider: _typeProviderNonNullableByDefault,
);
diff --git a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
index 148433e..1b491ac 100644
--- a/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/context_collection_resolution.dart
@@ -36,6 +36,7 @@
final bool implicitCasts;
final bool implicitDynamic;
final List<String> lints;
+ final bool strictCasts;
final bool strictInference;
final bool strictRawTypes;
final List<String> unignorableNames;
@@ -45,6 +46,7 @@
this.implicitCasts = true,
this.implicitDynamic = true,
this.lints = const [],
+ this.strictCasts = false,
this.strictInference = false,
this.strictRawTypes = false,
this.unignorableNames = const [],
@@ -59,8 +61,9 @@
buffer.writeln(' - $experiment');
}
buffer.writeln(' language:');
- buffer.writeln(' strict-raw-types: $strictRawTypes');
+ buffer.writeln(' strict-casts: $strictCasts');
buffer.writeln(' strict-inference: $strictInference');
+ buffer.writeln(' strict-raw-types: $strictRawTypes');
buffer.writeln(' strong-mode:');
buffer.writeln(' implicit-casts: $implicitCasts');
buffer.writeln(' implicit-dynamic: $implicitDynamic');
@@ -393,13 +396,14 @@
}
mixin WithNoImplicitCastsMixin on PubPackageResolutionTest {
+ /// Asserts that no errors are reported in [code] when implicit casts are
+ /// allowed, and that [expectedErrors] are reported for the same [code] when
+ /// implicit casts are not allowed.
Future<void> assertErrorsWithNoImplicitCasts(
String code,
- List<ExpectedError> expectedErrorsWhenImplicitCastsDisabled,
+ List<ExpectedError> expectedErrors,
) async {
- newFile(testFilePath, content: code);
-
- await resolveTestFile();
+ await resolveTestCode(code);
assertNoErrorsInResult();
disposeAnalysisContextCollection();
@@ -411,8 +415,13 @@
);
await resolveTestFile();
- assertErrorsInResult(expectedErrorsWhenImplicitCastsDisabled);
+ assertErrorsInResult(expectedErrors);
}
+
+ /// Asserts that no errors are reported in [code], both when implicit casts
+ /// are allowed and when implicit casts are not allowed.
+ Future<void> assertNoErrorsWithNoImplicitCasts(String code) async =>
+ assertErrorsWithNoImplicitCasts(code, []);
}
mixin WithoutConstructorTearoffsMixin on PubPackageResolutionTest {
@@ -427,3 +436,32 @@
@override
bool get typeToStringWithNullability => false;
}
+
+mixin WithStrictCastsMixin on PubPackageResolutionTest {
+ /// Asserts that no errors are reported in [code] when implicit casts are
+ /// allowed, and that [expectedErrors] are reported for the same [code] when
+ /// implicit casts are not allowed.
+ Future<void> assertErrorsWithStrictCasts(
+ String code,
+ List<ExpectedError> expectedErrors,
+ ) async {
+ await resolveTestCode(code);
+ assertNoErrorsInResult();
+
+ disposeAnalysisContextCollection();
+
+ writeTestPackageAnalysisOptionsFile(
+ AnalysisOptionsFileConfig(
+ strictCasts: true,
+ ),
+ );
+
+ await resolveTestFile();
+ assertErrorsInResult(expectedErrors);
+ }
+
+ /// Asserts that no errors are reported in [code], both when implicit casts
+ /// are allowed and when implicit casts are not allowed.
+ Future<void> assertNoErrorsWithStrictCasts(String code) async =>
+ assertErrorsWithStrictCasts(code, []);
+}
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 60ca6a0..226eafa 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -11,8 +11,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ArgumentTypeNotAssignableTest);
- defineReflectiveTests(ArgumentTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ ArgumentTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(ArgumentTypeNotAssignableWithoutNullSafetyTest);
+ defineReflectiveTests(ArgumentTypeNotAssignableWithStrictCastsTest);
});
}
@@ -656,7 +658,7 @@
}
@reflectiveTest
-class ArgumentTypeNotAssignableWithNoImplicitCastsTest
+class ArgumentTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_functionCall() async {
@@ -708,3 +710,28 @@
]);
}
}
+
+@reflectiveTest
+class ArgumentTypeNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_functionCall() async {
+ await assertErrorsWithStrictCasts('''
+void f(int i) {}
+void foo(dynamic a) {
+ f(a);
+}
+''', [
+ error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 43, 1),
+ ]);
+ }
+
+ test_operator() async {
+ await assertErrorsWithStrictCasts('''
+void foo(int i, dynamic a) {
+ i + a;
+}
+''', [
+ error(CompileTimeErrorCode.ARGUMENT_TYPE_NOT_ASSIGNABLE, 35, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
index 07abbcd..767bfa9 100644
--- a/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/field_initializer_not_assignable_test.dart
@@ -10,7 +10,9 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(FieldInitializerNotAssignableTest);
- defineReflectiveTests(FieldInitializerNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ FieldInitializerNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
+ defineReflectiveTests(FieldInitializerNotAssignableWithStrictCastsTest);
});
}
@@ -53,14 +55,34 @@
}
@reflectiveTest
-class FieldInitializerNotAssignableWithNoImplicitCastsTest
+class FieldInitializerNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_constructorInitializer() async {
- await assertErrorsWithNoImplicitCasts(
- 'class A { int i; A(num n) : i = n; }',
+ await assertErrorsWithNoImplicitCasts('''
+class A {
+ int i;
+ A(num n) : i = n;
+}
+''', [
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 36, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
+class FieldInitializerNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_constructorInitializer() async {
+ await assertErrorsWithStrictCasts(
+ '''
+class A {
+ int i;
+ A(dynamic a) : i = a;
+}
+''',
[
- error(CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 32, 1),
+ error(CompileTimeErrorCode.FIELD_INITIALIZER_NOT_ASSIGNABLE, 40, 1),
],
);
}
diff --git a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
index c75dd89..31ecd85 100644
--- a/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/for_in_of_invalid_type_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(ForInOfInvalidTypeTest);
defineReflectiveTests(ForInOfInvalidTypeWithoutNullSafetyTest);
+ defineReflectiveTests(ForInOfInvalidTypeWithStrictCastsTest);
});
}
@@ -183,3 +184,19 @@
''');
}
}
+
+@reflectiveTest
+class ForInOfInvalidTypeWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_forIn() async {
+ await assertErrorsWithStrictCasts('''
+f(dynamic e) {
+ for (var id in e) {
+ id;
+ }
+}
+''', [
+ error(CompileTimeErrorCode.FOR_IN_OF_INVALID_TYPE, 32, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index a303efd..726f456 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -11,8 +11,10 @@
defineReflectiveSuite(() {
defineReflectiveTests(InvalidAssignment_ImplicitCallReferenceTest);
defineReflectiveTests(InvalidAssignmentTest);
- defineReflectiveTests(InvalidAssignmentWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ InvalidAssignmentWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(InvalidAssignmentWithoutNullSafetyTest);
+ defineReflectiveTests(InvalidAssignmentWithStrictCastsTest);
});
}
@@ -962,24 +964,27 @@
}
@reflectiveTest
-class InvalidAssignmentWithNoImplicitCastsTest extends PubPackageResolutionTest
+class InvalidAssignmentWithoutNullSafetyAndNoImplicitCastsTest
+ extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_assignment() async {
- await assertErrorsWithNoImplicitCasts(
- 'void f(num n, int i) { i = n;}',
- [
- error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 27, 1),
- ],
- );
+ await assertErrorsWithNoImplicitCasts('''
+void f(num n, int i) {
+ i = n;
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 29, 1),
+ ]);
}
test_compoundAssignment() async {
- await assertErrorsWithNoImplicitCasts(
- 'void f(num n, int i) { i += n; }',
- [
- error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 28, 1),
- ],
- );
+ await assertErrorsWithNoImplicitCasts('''
+void f(num n, int i) {
+ i += n;
+}
+''', [
+ error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 30, 1),
+ ]);
}
@failingTest
@@ -1008,11 +1013,11 @@
test_numericOps() async {
// Regression test for https://github.com/dart-lang/sdk/issues/26912
- await assertErrorsWithNoImplicitCasts(r'''
+ await assertNoErrorsWithNoImplicitCasts('''
void f(int x, int y) {
x += y;
}
-''', []);
+''');
}
@failingTest
@@ -1088,3 +1093,16 @@
]);
}
}
+
+@reflectiveTest
+class InvalidAssignmentWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_assignment() async {
+ await assertErrorsWithStrictCasts('''
+dynamic a;
+int b = a;
+''', [
+ error(CompileTimeErrorCode.INVALID_ASSIGNMENT, 19, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
index 8d45f28..6a85dc3 100644
--- a/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/list_element_type_not_assignable_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ListElementTypeNotAssignableTest);
- defineReflectiveTests(ListElementTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ ListElementTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(ListElementTypeNotAssignableWithoutNullSafetyTest);
+ defineReflectiveTests(ListElementTypeNotAssignableWithStrictCastsTest);
});
}
@@ -233,7 +235,7 @@
}
@reflectiveTest
-class ListElementTypeNotAssignableWithNoImplicitCastsTest
+class ListElementTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_ifElement_falseBranch_dynamic() async {
@@ -291,3 +293,37 @@
class ListElementTypeNotAssignableWithoutNullSafetyTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, ListElementTypeNotAssignableTestCases {}
+
+@reflectiveTest
+class ListElementTypeNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_ifElement_falseBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int>[if (c) 0 else a];
+}
+''', [
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 50, 1),
+ ]);
+ }
+
+ test_ifElement_trueBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int>[if (c) a];
+}
+''', [
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 43, 1),
+ ]);
+ }
+
+ test_spread() async {
+ await assertErrorsWithStrictCasts('''
+void f(Iterable<dynamic> a) {
+ <int>[...a];
+}
+''', [
+ error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 41, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
index 1216de7..ca3c915 100644
--- a/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_key_type_not_assignable_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MapKeyTypeNotAssignableTest);
- defineReflectiveTests(MapKeyTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ MapKeyTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(MapKeyTypeNotAssignableWithoutNullSafetyTest);
+ defineReflectiveTests(MapKeyTypeNotAssignableWithStrictCastsTest);
});
}
@@ -238,7 +240,7 @@
}
@reflectiveTest
-class MapKeyTypeNotAssignableWithNoImplicitCastsTest
+class MapKeyTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_ifElement_falseBranch_key_dynamic() async {
@@ -302,3 +304,37 @@
''');
}
}
+
+@reflectiveTest
+class MapKeyTypeNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_ifElement_falseBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int, int>{if (c) 0: 0 else a: 0};
+}
+''', [
+ error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 58, 1),
+ ]);
+ }
+
+ test_ifElement_trueBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int, int>{if (c) a: 0 };
+}
+''', [
+ error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 48, 1),
+ ]);
+ }
+
+ test_spread() async {
+ await assertErrorsWithStrictCasts('''
+void f(Map<dynamic, int> a) {
+ <int, int>{...a};
+}
+''', [
+ error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 46, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
index 212b70b..4cebc25 100644
--- a/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/map_value_type_not_assignable_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(MapValueTypeNotAssignableTest);
- defineReflectiveTests(MapValueTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ MapValueTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(MapValueTypeNotAssignableWithoutNullSafetyTest);
+ defineReflectiveTests(MapValueTypeNotAssignableWithStrictCastsTest);
});
}
@@ -232,7 +234,7 @@
}
@reflectiveTest
-class MapValueTypeNotAssignableWithNoImplicitCastsTest
+class MapValueTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_ifElement_falseBranch_value_dynamic() async {
@@ -296,3 +298,37 @@
''');
}
}
+
+@reflectiveTest
+class MapValueTypeNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_ifElement_falseBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int, int>{if (c) 0: 0 else 0: a};
+}
+''', [
+ error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 61, 1),
+ ]);
+ }
+
+ test_ifElement_trueBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int, int>{if (c) 0: a};
+}
+''', [
+ error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 51, 1),
+ ]);
+ }
+
+ test_spread() async {
+ await assertErrorsWithStrictCasts('''
+void f(Map<int, dynamic> a) {
+ <int, int>{...a};
+}
+''', [
+ error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 46, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
index d96e7f3..3f99747 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NonBoolConditionTest);
- defineReflectiveTests(NonBoolConditionWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ NonBoolConditionWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(NonBoolConditionWithNullSafetyTest);
+ defineReflectiveTests(NonBoolConditionWithStrictCastsTest);
});
}
@@ -214,7 +216,31 @@
}
@reflectiveTest
-class NonBoolConditionWithNoImplicitCastsTest extends PubPackageResolutionTest
+class NonBoolConditionWithNullSafetyTest extends PubPackageResolutionTest {
+ test_if_null() async {
+ await assertErrorsInCode(r'''
+void f(Null a) {
+ if (a) {}
+}
+''', [
+ error(CompileTimeErrorCode.NON_BOOL_CONDITION, 23, 1),
+ ]);
+ }
+
+ test_ternary_condition_null() async {
+ await assertErrorsInCode(r'''
+void f(Null a) {
+ a ? 0 : 1;
+}
+''', [
+ error(CompileTimeErrorCode.NON_BOOL_CONDITION, 19, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
+class NonBoolConditionWithoutNullSafetyAndNoImplicitCastsTest
+ extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_map_ifElement_condition_dynamic() async {
await assertErrorsWithNoImplicitCasts(r'''
@@ -258,26 +284,25 @@
}
@reflectiveTest
-class NonBoolConditionWithNullSafetyTest extends PubPackageResolutionTest {
- test_if_null() async {
- await assertErrorsInCode(r'''
-m() {
- Null x;
- if (x) {}
+class NonBoolConditionWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_map_ifElement_condition() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic c) {
+ <int, int>{if (c) 0: 0};
}
''', [
- error(CompileTimeErrorCode.NON_BOOL_CONDITION, 22, 1),
+ error(CompileTimeErrorCode.NON_BOOL_CONDITION, 37, 1),
]);
}
- test_ternary_condition_null() async {
- await assertErrorsInCode(r'''
-m() {
- Null x;
- x ? 0 : 1;
+ test_set_ifElement_condition() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic c) {
+ <int>{if (c) 0};
}
''', [
- error(CompileTimeErrorCode.NON_BOOL_CONDITION, 18, 1),
+ error(CompileTimeErrorCode.NON_BOOL_CONDITION, 32, 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_expression_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_expression_test.dart
index 0a12cfb..1305b0d 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_expression_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_expression_test.dart
@@ -10,6 +10,7 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(NonBoolExpressionTest);
+ defineReflectiveTests(NonBoolExpressionWithStrictCastsTest);
});
}
@@ -47,3 +48,17 @@
]);
}
}
+
+@reflectiveTest
+class NonBoolExpressionWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_assert() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic a) {
+ assert(a);
+}
+''', [
+ error(CompileTimeErrorCode.NON_BOOL_EXPRESSION, 29, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_negation_expression_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_negation_expression_test.dart
index 6fb1e92..f0578ad 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_negation_expression_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_negation_expression_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(NonBoolNegationExpressionTest);
defineReflectiveTests(NonBoolNegationExpressionWithNullSafetyTest);
+ defineReflectiveTests(NonBoolNegationExpressionWithStrictCastsTest);
});
}
@@ -50,14 +51,26 @@
class NonBoolNegationExpressionWithNullSafetyTest
extends PubPackageResolutionTest {
test_null() async {
- await assertErrorsInCode(r'''
-m() {
- Null x;
+ await assertErrorsInCode('''
+void m(Null x) {
!x;
}
''', [
- error(HintCode.UNUSED_LOCAL_VARIABLE, 13, 1),
- error(CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION, 19, 1),
+ error(CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION, 20, 1),
+ ]);
+ }
+}
+
+@reflectiveTest
+class NonBoolNegationExpressionWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_negation() async {
+ await assertErrorsWithStrictCasts(r'''
+void f(dynamic a) {
+ !a;
+}
+''', [
+ error(CompileTimeErrorCode.NON_BOOL_NEGATION_EXPRESSION, 23, 1),
]);
}
}
diff --git a/pkg/analyzer/test/src/diagnostics/non_bool_operand_test.dart b/pkg/analyzer/test/src/diagnostics/non_bool_operand_test.dart
index ea06d2a..1b25120 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_operand_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_operand_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(NonBoolOperandTest);
defineReflectiveTests(NonBoolOperandWithNullSafetyTest);
+ defineReflectiveTests(NonBoolOperandWithStrictCastsTest);
});
}
@@ -110,3 +111,17 @@
]);
}
}
+
+@reflectiveTest
+class NonBoolOperandWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_and() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic a) {
+ if(a && true) {}
+}
+''', [
+ error(CompileTimeErrorCode.NON_BOOL_OPERAND, 25, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
index d81a21a..d968410 100644
--- a/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_iterable_spread_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(NotIterableSpreadTest);
defineReflectiveTests(NotIterableSpreadWithoutNullSafetyTest);
+ defineReflectiveTests(NotIterableSpreadWithStrictCastsTest);
});
}
@@ -112,3 +113,27 @@
@reflectiveTest
class NotIterableSpreadWithoutNullSafetyTest extends PubPackageResolutionTest
with WithoutNullSafetyMixin, NotIterableSpreadTestCases {}
+
+@reflectiveTest
+class NotIterableSpreadWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_list() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic a) {
+ [...a];
+}
+''', [
+ error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 26, 1),
+ ]);
+ }
+
+ test_set() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic a) {
+ <int>{...a};
+}
+''', [
+ error(CompileTimeErrorCode.NOT_ITERABLE_SPREAD, 31, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
index 3c008f9..aa8cf06 100644
--- a/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/not_map_spread_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(NotMapSpreadTest);
defineReflectiveTests(NotMapSpreadWithoutNullSafetyTest);
+ defineReflectiveTests(NotMapSpreadWithStrictCastsTest);
});
}
@@ -102,3 +103,17 @@
@reflectiveTest
class NotMapSpreadWithoutNullSafetyTest extends PubPackageResolutionTest
with NotMapSpreadTestCases, WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class NotMapSpreadWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_map() async {
+ await assertErrorsWithStrictCasts('''
+void f(dynamic a) {
+ <int, String>{...a};
+}
+''', [
+ error(CompileTimeErrorCode.NOT_MAP_SPREAD, 39, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
index ef2237d..1a11708 100644
--- a/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/return_of_invalid_type_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(ReturnOfInvalidTypeTest);
- defineReflectiveTests(ReturnOfInvalidTypeWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ ReturnOfInvalidTypeWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(ReturnOfInvalidTypeWithoutNullSafetyTest);
+ defineReflectiveTests(ReturnOfInvalidTypeWithStrictCastsTest);
});
}
@@ -547,7 +549,7 @@
}
@reflectiveTest
-class ReturnOfInvalidTypeWithNoImplicitCastsTest
+class ReturnOfInvalidTypeWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_return() async {
@@ -571,3 +573,25 @@
@reflectiveTest
class ReturnOfInvalidTypeWithoutNullSafetyTest extends PubPackageResolutionTest
with ReturnOfInvalidTypeTestCases, WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class ReturnOfInvalidTypeWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_return() async {
+ await assertErrorsWithStrictCasts('''
+int f(dynamic a) => a;
+''', [
+ error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 20, 1),
+ ]);
+ }
+
+ test_return_async() async {
+ await assertErrorsWithStrictCasts('''
+Future<int> f(dynamic a) async {
+ return a;
+}
+''', [
+ error(CompileTimeErrorCode.RETURN_OF_INVALID_TYPE_FROM_FUNCTION, 42, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
index a74f2cc..d5cb62b 100644
--- a/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/set_element_type_not_assignable_test.dart
@@ -10,8 +10,10 @@
main() {
defineReflectiveSuite(() {
defineReflectiveTests(SetElementTypeNotAssignableTest);
- defineReflectiveTests(SetElementTypeNotAssignableWithNoImplicitCastsTest);
+ defineReflectiveTests(
+ SetElementTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest);
defineReflectiveTests(SetElementTypeNotAssignableWithoutNullSafetyTest);
+ defineReflectiveTests(SetElementTypeNotAssignableWithStrictCastsTest);
});
}
@@ -198,7 +200,7 @@
}
@reflectiveTest
-class SetElementTypeNotAssignableWithNoImplicitCastsTest
+class SetElementTypeNotAssignableWithoutNullSafetyAndNoImplicitCastsTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, WithNoImplicitCastsMixin {
test_ifElement_falseBranch_dynamic() async {
@@ -256,3 +258,37 @@
class SetElementTypeNotAssignableWithoutNullSafetyTest
extends PubPackageResolutionTest
with WithoutNullSafetyMixin, SetElementTypeNotAssignableTestCases {}
+
+@reflectiveTest
+class SetElementTypeNotAssignableWithStrictCastsTest
+ extends PubPackageResolutionTest with WithStrictCastsMixin {
+ test_ifElement_falseBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int>{if (c) 0 else a};
+}
+''', [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 50, 1),
+ ]);
+ }
+
+ test_ifElement_trueBranch() async {
+ await assertErrorsWithStrictCasts('''
+void f(bool c, dynamic a) {
+ <int>{if (c) a};
+}
+''', [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 43, 1),
+ ]);
+ }
+
+ test_spread() async {
+ await assertErrorsWithStrictCasts('''
+void f(Iterable<dynamic> a) {
+ <int>{...a};
+}
+''', [
+ error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 41, 1),
+ ]);
+ }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
index 6eda8bd..e064365 100644
--- a/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/yield_of_invalid_type_test.dart
@@ -11,6 +11,7 @@
defineReflectiveSuite(() {
defineReflectiveTests(YieldOfInvalidTypeTest);
defineReflectiveTests(YieldOfInvalidTypeWithoutNullSafetyTest);
+ defineReflectiveTests(YieldOfInvalidTypeWithStrictCastsTest);
});
}
@@ -448,3 +449,27 @@
@reflectiveTest
class YieldOfInvalidTypeWithoutNullSafetyTest extends PubPackageResolutionTest
with YieldOfInvalidTypeTestCases, WithoutNullSafetyMixin {}
+
+@reflectiveTest
+class YieldOfInvalidTypeWithStrictCastsTest extends PubPackageResolutionTest
+ with WithStrictCastsMixin {
+ test_yieldEach_asyncStar() async {
+ await assertErrorsWithStrictCasts('''
+f(dynamic a) async* {
+ yield* a;
+}
+''', [
+ error(CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE, 31, 1),
+ ]);
+ }
+
+ test_yieldEach_syncStar() async {
+ await assertErrorsWithStrictCasts('''
+f(dynamic a) sync* {
+ yield* a;
+}
+''', [
+ error(CompileTimeErrorCode.YIELD_EACH_OF_INVALID_TYPE, 30, 1),
+ ]);
+ }
+}
diff --git a/pkg/nnbd_migration/lib/src/fix_builder.dart b/pkg/nnbd_migration/lib/src/fix_builder.dart
index 5e57c8b..afb6393 100644
--- a/pkg/nnbd_migration/lib/src/fix_builder.dart
+++ b/pkg/nnbd_migration/lib/src/fix_builder.dart
@@ -292,6 +292,7 @@
return TypeSystemImpl(
implicitCasts: typeSystem.implicitCasts,
isNonNullableByDefault: true,
+ strictCasts: typeSystem.strictCasts,
strictInference: typeSystem.strictInference,
typeProvider: nnbdTypeProvider);
}
diff --git a/pkg/nnbd_migration/test/edge_builder_test.dart b/pkg/nnbd_migration/test/edge_builder_test.dart
index fcec048..2be4a72 100644
--- a/pkg/nnbd_migration/test/edge_builder_test.dart
+++ b/pkg/nnbd_migration/test/edge_builder_test.dart
@@ -70,6 +70,7 @@
TypeSystemImpl(
implicitCasts: true,
isNonNullableByDefault: false,
+ strictCasts: false,
strictInference: false,
typeProvider: typeProvider,
),
@@ -500,6 +501,7 @@
var typeSystem = TypeSystemImpl(
isNonNullableByDefault: false,
implicitCasts: true,
+ strictCasts: false,
strictInference: false,
typeProvider: typeProvider,
);
diff --git a/sdk/lib/collection/hash_map.dart b/sdk/lib/collection/hash_map.dart
index 5aa9504..2d4f42c 100644
--- a/sdk/lib/collection/hash_map.dart
+++ b/sdk/lib/collection/hash_map.dart
@@ -37,40 +37,13 @@
/// values, the iteration order is unspecified except that it will stay the
/// same as long as the map isn't changed.
///
- /// If [equals] is provided, it is used to compare the keys in the table with
+ /// If [equals] is provided, it is used to compare the keys in the map with
/// new keys. If [equals] is omitted, the key's own [Object.==] is used
/// instead.
///
/// Similar, if [hashCode] is provided, it is used to produce a hash value
- /// for keys in order to place them in the hash table. If it is omitted, the
- /// key's own [Object.hashCode] is used.
- ///
- /// If using methods like [operator []], [remove] and [containsKey] together
- /// with a custom equality and hashcode, an extra `isValidKey` function
- /// can be supplied. This function is called before calling [equals] or
- /// [hashCode] with an argument that may not be a [K] instance, and if the
- /// call returns false, the key is assumed to not be in the set.
- /// The [isValidKey] function defaults to just testing if the object is a
- /// [K] instance.
- ///
- /// Example:
- /// ```dart template:expression
- /// HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
- /// hashCode: (int e) => e % 5)
- /// ```
- /// This example map does not need an `isValidKey` function to be passed.
- /// The default function accepts only `int` values, which can safely be
- /// passed to both the `equals` and `hashCode` functions.
- ///
- /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
- /// the default `isValidKey` instead accepts all keys.
- /// The default equality and hashcode operations are assumed to work on all
- /// objects.
- ///
- /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
- /// and `isValidKey` is omitted, the resulting map is identity based,
- /// and the `isValidKey` defaults to accepting all keys.
- /// Such a map can be created directly using [HashMap.identity].
+ /// for keys in order to place them in the map. If [hashCode] is omitted,
+ /// the key's own [Object.hashCode] is used.
///
/// The used `equals` and `hashCode` method should always be consistent,
/// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
@@ -79,7 +52,36 @@
/// unpredictable.
///
/// If you supply one of [equals] and [hashCode],
- /// you should generally also to supply the other.
+ /// you should generally also supply the other.
+ ///
+ /// Some [equals] or [hashCode] functions might not work for all objects.
+ /// If [isValidKey] is supplied, it's used to check a potential key
+ /// which is not necessarily an instance of [K], like the arguments to
+ /// [operator []], [remove] and [containsKey], which are typed as `Object?`.
+ /// If [isValidKey] returns `false`, for an object, the [equals] and
+ /// [hashCode] functions are not called, and no key equal to that object
+ /// is assumed to be in the map.
+ /// The [isValidKey] function defaults to just testing if the object is an
+ /// instance of [K].
+ ///
+ /// Example:
+ /// ```dart template:expression
+ /// HashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
+ /// ```
+ /// This example map does not need an `isValidKey` function to be passed.
+ /// The default function accepts precisely `int` values, which can safely be
+ /// passed to both the `equals` and `hashCode` functions.
+ ///
+ /// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
+ /// the default `isValidKey` instead accepts all keys.
+ /// The default equality and hashcode operations are known to work on all
+ /// objects.
+ ///
+ /// Likewise, if `equals` is [identical], `hashCode` is [identityHashCode]
+ /// and `isValidKey` is omitted, the resulting map is identity based,
+ /// and the `isValidKey` defaults to accepting all keys.
+ /// Such a map can be created directly using [HashMap.identity].
external factory HashMap(
{bool Function(K, K)? equals,
int Function(K)? hashCode,
@@ -87,6 +89,9 @@
/// Creates an unordered identity-based map.
///
+ /// Keys of this map are considered equal only to the same object,
+ /// and does not use [Object.==] at all.
+ ///
/// Effectively a shorthand for:
/// ```dart
/// HashMap<K, V>(equals: identical, hashCode: identityHashCode)
diff --git a/sdk/lib/collection/hash_set.dart b/sdk/lib/collection/hash_set.dart
index ee8fed0..1f94ffb 100644
--- a/sdk/lib/collection/hash_set.dart
+++ b/sdk/lib/collection/hash_set.dart
@@ -25,12 +25,7 @@
/// Create a hash set using the provided [equals] as equality.
///
/// The provided [equals] must define a stable equivalence relation, and
- /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
- /// methods won't work on all objects, but only on some instances of E, the
- /// [isValidKey] predicate can be used to restrict the keys that the functions
- /// are applied to.
- /// Any key for which [isValidKey] returns false is automatically assumed
- /// to not be in the set when asking `contains`.
+ /// [hashCode] must be consistent with [equals].
///
/// If [equals] or [hashCode] are omitted, the set uses
/// the elements' intrinsic [Object.==] and [Object.hashCode].
@@ -38,18 +33,20 @@
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
///
- /// If the supplied `equals` or `hashCode` functions won't work on all [E]
- /// objects, and the map will be used in a setting where a non-`E` object
- /// is passed to, e.g., `contains`, then the [isValidKey] function should
- /// also be supplied.
- ///
- /// If [isValidKey] is omitted, it defaults to testing if the object is an
- /// [E] instance. That means that:
+ /// Some [equals] or [hashCode] functions might not work for all objects.
+ /// If [isValidKey] is supplied, it's used to check a potential element
+ /// which is not necessarily an instance of [E], like the argument to
+ /// [contains] which is typed as `Object?`.
+ /// If [isValidKey] returns `false`, for an object, the [equals] and
+ /// [hashCode] functions are not called, and no key equal to that object
+ /// is assumed to be in the map.
+ /// The [isValidKey] function defaults to just testing if the object is an
+ /// instance of [E], which means that:
/// ```dart template:expression
/// HashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
/// hashCode: (int e) => e % 5)
/// ```
- /// does not need an `isValidKey` argument, because it defaults to only
+ /// does not need an `isValidKey` argument because it defaults to only
/// accepting `int` values which are accepted by both `equals` and `hashCode`.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
diff --git a/sdk/lib/collection/linked_hash_map.dart b/sdk/lib/collection/linked_hash_map.dart
index cfab8f3..646b581 100644
--- a/sdk/lib/collection/linked_hash_map.dart
+++ b/sdk/lib/collection/linked_hash_map.dart
@@ -8,7 +8,7 @@
///
/// The insertion order of keys is remembered,
/// and keys are iterated in the order they were inserted into the map.
-/// Values are iterated in their corresponding key's order.
+/// Values and entries are iterated in their corresponding key's order.
/// Changing a key's value, when the key is already in the map,
/// does not change the iteration order,
/// but removing the key and adding it again
@@ -30,21 +30,31 @@
/// for keys in order to place them in the hash table. If it is omitted, the
/// key's own [Object.hashCode] is used.
///
- /// If using methods like [operator []], [remove] and [containsKey] together
- /// with a custom equality and hashcode, an extra `isValidKey` function
- /// can be supplied. This function is called before calling [equals] or
- /// [hashCode] with an argument that may not be a [K] instance, and if the
- /// call returns false, the key is assumed to not be in the set.
- /// The [isValidKey] function defaults to just testing if the object is a
- /// [K] instance.
+ /// The used `equals` and `hashCode` method should always be consistent,
+ /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
+ /// of an object, or what it compares equal to, should not change while the
+ /// object is in the table. If it does change, the result is unpredictable.
+ ///
+ /// If you supply one of [equals] and [hashCode],
+ /// you should generally also supply the other.
+ ///
+ /// Some [equals] or [hashCode] functions might not work for all objects.
+ /// If [isValidKey] is supplied, it's used to check a potential key
+ /// which is not necessarily an instance of [K], like the arguments to
+ /// [operator []], [remove] and [containsKey], which are typed as `Object?`.
+ /// If [isValidKey] returns `false`, for an object, the [equals] and
+ /// [hashCode] functions are not called, and no key equal to that object
+ /// is assumed to be in the map.
+ /// The [isValidKey] function defaults to just testing if the object is an
+ /// instance of [K].
///
/// Example:
/// ```dart template:expression
- /// LinkedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
- /// hashCode: (int e) => e % 5)
+ /// LikedHashMap<int,int>(equals: (int a, int b) => (b - a) % 5 == 0,
+ /// hashCode: (int e) => e % 5)
/// ```
/// This example map does not need an `isValidKey` function to be passed.
- /// The default function accepts only `int` values, which can safely be
+ /// The default function accepts precisely `int` values, which can safely be
/// passed to both the `equals` and `hashCode` functions.
///
/// If neither `equals`, `hashCode`, nor `isValidKey` is provided,
@@ -56,14 +66,6 @@
/// and `isValidKey` is omitted, the resulting map is identity based,
/// and the `isValidKey` defaults to accepting all keys.
/// Such a map can be created directly using [LinkedHashMap.identity].
- ///
- /// The used `equals` and `hashCode` method should always be consistent,
- /// so that if `equals(a, b)` then `hashCode(a) == hashCode(b)`. The hash
- /// of an object, or what it compares equal to, should not change while the
- /// object is in the table. If it does change, the result is unpredictable.
- ///
- /// If you supply one of [equals] and [hashCode],
- /// you should generally also to supply the other.
external factory LinkedHashMap(
{bool Function(K, K)? equals,
int Function(K)? hashCode,
diff --git a/sdk/lib/collection/linked_hash_set.dart b/sdk/lib/collection/linked_hash_set.dart
index 43d9a52..66be66c 100644
--- a/sdk/lib/collection/linked_hash_set.dart
+++ b/sdk/lib/collection/linked_hash_set.dart
@@ -30,28 +30,20 @@
/// [equals] and [hashCode].
///
/// The provided [equals] must define a stable equivalence relation, and
- /// [hashCode] must be consistent with [equals]. If the [equals] or [hashCode]
- /// methods won't work on all objects, but only on some instances of E, the
- /// [isValidKey] predicate can be used to restrict the keys that the functions
- /// are applied to.
- /// Any key for which [isValidKey] returns false is automatically assumed
- /// to not be in the set when asking `contains`.
- ///
- /// If [equals] or [hashCode] are omitted, the set uses
- /// the elements' intrinsic [Object.==] and [Object.hashCode],
- /// and [isValidKey] is ignored since these operations are assumed
- /// to work on all objects.
+ /// [hashCode] must be consistent with [equals].
///
/// If you supply one of [equals] and [hashCode],
/// you should generally also to supply the other.
///
- /// If the supplied `equals` or `hashCode` functions won't work on all [E]
- /// objects, and the map will be used in a setting where a non-`E` object
- /// is passed to, e.g., `contains`, then the [isValidKey] function should
- /// also be supplied.
- ///
- /// If [isValidKey] is omitted, it defaults to testing if the object is an
- /// [E] instance. That means that:
+ /// Some [equals] or [hashCode] functions might not work for all objects.
+ /// If [isValidKey] is supplied, it's used to check a potential element
+ /// which is not necessarily an instance of [E], like the argument to
+ /// [contains] which is typed as `Object?`.
+ /// If [isValidKey] returns `false`, for an object, the [equals] and
+ /// [hashCode] functions are not called, and no key equal to that object
+ /// is assumed to be in the map.
+ /// The [isValidKey] function defaults to just testing if the object is an
+ /// instance of [E], which means that:
/// ```dart template:expression
/// LinkedHashSet<int>(equals: (int e1, int e2) => (e1 - e2) % 5 == 0,
/// hashCode: (int e) => e % 5)
diff --git a/tools/VERSION b/tools/VERSION
index 3fdef2c..b0b82aa 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -27,5 +27,5 @@
MAJOR 2
MINOR 16
PATCH 0
-PRERELEASE 1
+PRERELEASE 2
PRERELEASE_PATCH 0
\ No newline at end of file