mirror of
https://github.com/dart-lang/sdk
synced 2024-09-16 01:30:32 +00:00
Issue 45672. Report constant errors when null value where non-nullable type is expected.
Original: https://dart-review.googlesource.com/c/sdk/+/196042 Reverted as: https://dart-review.googlesource.com/c/sdk/+/196281 Presubmit looks green: https://test.corp.google.com/ui#id=OCL:369788056:BASE:369887187:1619108797262:daf61e5&include_skipped=true Bug: https://github.com/dart-lang/sdk/issues/45672 Change-Id: I459b7ea3e1218d960583bf4b6ace5b2c40dc7f4a Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/196300 Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
92c4dbd4bc
commit
ac27053055
|
@ -822,9 +822,6 @@ class ConstantEvaluationEngine {
|
|||
DartObjectImpl obj,
|
||||
DartType type,
|
||||
) {
|
||||
if (obj.isNull) {
|
||||
return true;
|
||||
}
|
||||
var objType = obj.type;
|
||||
return library.typeSystem.isSubtypeOf(objType, type);
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@ class C {
|
|||
"const Center(name: 'v')",
|
||||
context: '''
|
||||
class Align {
|
||||
final double widthFactor;
|
||||
final double? widthFactor;
|
||||
const Align({String name, this.widthFactor})
|
||||
assert(widthFactor == null || widthFactor >= 0.0);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class ConstConstructorFieldTypeMismatchTest extends PubPackageResolutionTest {
|
||||
test_assignable_generic() async {
|
||||
test_generic_int_int() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class C<T> {
|
||||
|
@ -31,41 +31,7 @@ var v = const C<int>();
|
|||
);
|
||||
}
|
||||
|
||||
test_assignable_nullValue() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A(null);
|
||||
''');
|
||||
}
|
||||
|
||||
test_assignable_unresolvedFieldAndNullValue() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final Unresolved y;
|
||||
}
|
||||
var v = const A(null);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_notAssignable() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A('foo');
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 14),
|
||||
]);
|
||||
}
|
||||
|
||||
test_notAssignable_generic() async {
|
||||
test_generic_string_int() async {
|
||||
await assertErrorsInCode(
|
||||
r'''
|
||||
class C<T> {
|
||||
|
@ -83,13 +49,50 @@ var v = const C<String>();
|
|||
);
|
||||
}
|
||||
|
||||
test_notAssignable_unresolved() async {
|
||||
test_notGeneric_int_int() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A('foo');
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 14),
|
||||
]);
|
||||
}
|
||||
|
||||
test_notGeneric_int_null() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH, 57, 13),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final int y;
|
||||
}
|
||||
var v = const A(null);
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_notGeneric_unresolved_int() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final Unresolved y;
|
||||
}
|
||||
var v = const A('foo');
|
||||
var v = const A(0);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
|
||||
]);
|
||||
}
|
||||
|
||||
test_notGeneric_unresolved_null() async {
|
||||
await assertErrorsInCode(r'''
|
||||
class A {
|
||||
const A(x) : y = x;
|
||||
final Unresolved y;
|
||||
}
|
||||
var v = const A(null);
|
||||
''', [
|
||||
error(CompileTimeErrorCode.UNDEFINED_CLASS, 40, 10),
|
||||
]);
|
||||
|
|
|
@ -10,12 +10,19 @@ import '../dart/resolution/context_collection_resolution.dart';
|
|||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ListElementTypeNotAssignableTest);
|
||||
defineReflectiveTests(ListElementTypeNotAssignableWithoutNullSafetyTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ListElementTypeNotAssignableTest extends PubPackageResolutionTest
|
||||
with ListElementTypeNotAssignableTestCases {}
|
||||
with ListElementTypeNotAssignableTestCases {
|
||||
test_const_stringQuestion_null_value() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <String?>[null];
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
mixin ListElementTypeNotAssignableTestCases on PubPackageResolutionTest {
|
||||
test_const_ifElement_thenElseFalse_intInt() async {
|
||||
|
@ -67,6 +74,32 @@ var v = const <int>[if (true) a];
|
|||
]);
|
||||
}
|
||||
|
||||
test_const_intInt() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
var v1 = <int> [42];
|
||||
var v2 = const <int> [42];
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_intNull_dynamic() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 36, 1),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
const a = null;
|
||||
var v = const <int>[a];
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intNull_value() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 4),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
var v = const <int>[null];
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_spread_intInt() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <int>[...[0, 1]];
|
||||
|
@ -90,32 +123,12 @@ var v = const <String>[x];
|
|||
]);
|
||||
}
|
||||
|
||||
test_const_stringNull() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <String?>[null];
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_stringNull_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic x = null;
|
||||
var v = const <String>[x];
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_voidInt() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <void>[42];
|
||||
''');
|
||||
}
|
||||
|
||||
test_element_type_is_assignable() async {
|
||||
await assertNoErrorsInCode(r'''
|
||||
var v1 = <int> [42];
|
||||
var v2 = const <int> [42];
|
||||
''');
|
||||
}
|
||||
|
||||
test_nonConst_ifElement_thenElseFalse_intDynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic a = 'a';
|
||||
|
@ -181,3 +194,8 @@ var v = <void>[42];
|
|||
''');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ListElementTypeNotAssignableWithoutNullSafetyTest
|
||||
extends PubPackageResolutionTest
|
||||
with WithoutNullSafetyMixin, ListElementTypeNotAssignableTestCases {}
|
||||
|
|
|
@ -16,7 +16,20 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class MapKeyTypeNotAssignableTest extends PubPackageResolutionTest
|
||||
with MapKeyTypeNotAssignableTestCases {}
|
||||
with MapKeyTypeNotAssignableTestCases {
|
||||
test_const_intQuestion_null_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic a = null;
|
||||
var v = const <int?, bool>{a : true};
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_intQuestion_null_value() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <int?, bool>{null : true};
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
mixin MapKeyTypeNotAssignableTestCases on PubPackageResolutionTest {
|
||||
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
|
||||
|
@ -84,6 +97,25 @@ var v = const <int, bool>{a : true};
|
|||
''');
|
||||
}
|
||||
|
||||
test_const_intNull_dynamic() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 50, 1),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
const dynamic a = null;
|
||||
var v = const <int, bool>{a : true};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intNull_value() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE, 26, 4),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
var v = const <int, bool>{null : true};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intString_dynamic() async {
|
||||
await assertErrorsInCode('''
|
||||
const dynamic a = 'a';
|
||||
|
|
|
@ -16,7 +16,20 @@ main() {
|
|||
|
||||
@reflectiveTest
|
||||
class MapValueTypeNotAssignableTest extends PubPackageResolutionTest
|
||||
with MapValueTypeNotAssignableTestCases {}
|
||||
with MapValueTypeNotAssignableTestCases {
|
||||
test_const_intQuestion_null_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic a = null;
|
||||
var v = const <bool, int?>{true: a};
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_intQuestion_null_value() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <bool, int?>{true: null};
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
mixin MapValueTypeNotAssignableTestCases on PubPackageResolutionTest {
|
||||
test_const_ifElement_thenElseFalse_intInt_dynamic() async {
|
||||
|
@ -84,6 +97,25 @@ var v = const <bool, int>{true: a};
|
|||
''');
|
||||
}
|
||||
|
||||
test_const_intNull_dynamic() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 56, 1),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
const dynamic a = null;
|
||||
var v = const <bool, int>{true: a};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intNull_value() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE, 32, 4),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
var v = const <bool, int>{true: null};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intString_dynamic() async {
|
||||
await assertErrorsInCode('''
|
||||
const dynamic a = 'a';
|
||||
|
|
|
@ -24,6 +24,7 @@ main() {
|
|||
const A();
|
||||
}
|
||||
''', [
|
||||
error(CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH, 41, 9),
|
||||
error(CompileTimeErrorCode.NOT_ENOUGH_POSITIONAL_ARGUMENTS, 48, 2),
|
||||
]);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,26 @@ import '../dart/resolution/context_collection_resolution.dart';
|
|||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(SetElementTypeNotAssignableTest);
|
||||
defineReflectiveTests(SetElementTypeNotAssignableWithoutNullSafetyTest);
|
||||
});
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SetElementTypeNotAssignableTest extends PubPackageResolutionTest
|
||||
with SetElementTypeNotAssignableTestCases {}
|
||||
with SetElementTypeNotAssignableTestCases {
|
||||
test_const_stringQuestion_null_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const a = null;
|
||||
var v = const <String?>{a};
|
||||
''');
|
||||
}
|
||||
|
||||
test_const_stringQuestion_null_value() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <String?>{null};
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
mixin SetElementTypeNotAssignableTestCases on PubPackageResolutionTest {
|
||||
test_const_ifElement_thenElseFalse_intInt() async {
|
||||
|
@ -67,44 +81,61 @@ var v = const <int>{if (true) a};
|
|||
]);
|
||||
}
|
||||
|
||||
test_const_spread_intInt() async {
|
||||
test_const_intInt_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <int>{...[0, 1]};
|
||||
const dynamic a = 42;
|
||||
var v = const <int>{a};
|
||||
''');
|
||||
}
|
||||
|
||||
test_explicitTypeArgs_const() async {
|
||||
await assertErrorsInCode('''
|
||||
var v = const <String>{42};
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 23, 2),
|
||||
]);
|
||||
}
|
||||
|
||||
test_explicitTypeArgs_const_actualTypeMatch() async {
|
||||
test_const_intInt_value() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic x = null;
|
||||
var v = const <String>{x};
|
||||
var v = const <int>{42};
|
||||
''');
|
||||
}
|
||||
|
||||
test_explicitTypeArgs_const_actualTypeMismatch() async {
|
||||
test_const_intNull_dynamic() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 36, 1),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
const dynamic x = 42;
|
||||
var v = const <String>{x};
|
||||
const a = null;
|
||||
var v = const <int>{a};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intNull_value() async {
|
||||
var errors = expectedErrorsByNullability(nullable: [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 4),
|
||||
], legacy: []);
|
||||
await assertErrorsInCode('''
|
||||
var v = const <int>{null};
|
||||
''', errors);
|
||||
}
|
||||
|
||||
test_const_intString_dynamic() async {
|
||||
await assertErrorsInCode('''
|
||||
const dynamic x = 'abc';
|
||||
var v = const <int>{x};
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 45, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_explicitTypeArgs_notConst() async {
|
||||
test_const_intString_value() async {
|
||||
await assertErrorsInCode('''
|
||||
var v = <String>{42};
|
||||
var v = const <int>{'abc'};
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 17, 2),
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 20, 5),
|
||||
]);
|
||||
}
|
||||
|
||||
test_const_spread_intInt() async {
|
||||
await assertNoErrorsInCode('''
|
||||
var v = const <int>{...[0, 1]};
|
||||
''');
|
||||
}
|
||||
|
||||
test_nonConst_ifElement_thenElseFalse_intDynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic a = 'a';
|
||||
|
@ -148,4 +179,24 @@ var v = <int>{if (true) a};
|
|||
var v = <int>{...[0, 1]};
|
||||
''');
|
||||
}
|
||||
|
||||
test_notConst_intString_dynamic() async {
|
||||
await assertNoErrorsInCode('''
|
||||
const dynamic x = 'abc';
|
||||
var v = <int>{x};
|
||||
''');
|
||||
}
|
||||
|
||||
test_notConst_intString_value() async {
|
||||
await assertErrorsInCode('''
|
||||
var v = <int>{'abc'};
|
||||
''', [
|
||||
error(CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE, 14, 5),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class SetElementTypeNotAssignableWithoutNullSafetyTest
|
||||
extends PubPackageResolutionTest
|
||||
with WithoutNullSafetyMixin, SetElementTypeNotAssignableTestCases {}
|
||||
|
|
|
@ -18,4 +18,6 @@ class C extends Base {
|
|||
|
||||
main() {
|
||||
const C("str");
|
||||
//^^^^^^^^^^^^^^
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_EVAL_THROWS_EXCEPTION
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ class A {
|
|||
class StringInterpolation1NegativeTest {
|
||||
// Dollar not followed by "{" or identifier.
|
||||
static const DOLLAR = const A("$");
|
||||
// [error line 14, column 33, length 3]
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH
|
||||
// [error line 14, column 35, length 0]
|
||||
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
|
||||
// [cfe] A '$' has special meaning inside a string, and must be followed by an identifier or an expression in curly braces ({}).
|
||||
|
|
Loading…
Reference in a new issue