Skip to content

Commit

Permalink
Version 3.7.0-35.0.dev
Browse files Browse the repository at this point in the history
Merge 42364b1 into dev
  • Loading branch information
Dart CI committed Oct 17, 2024
2 parents 993d306 + 42364b1 commit 95fe32c
Show file tree
Hide file tree
Showing 6 changed files with 521 additions and 10 deletions.
57 changes: 48 additions & 9 deletions pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1155,6 +1155,26 @@ class _ConstLiteralVerifier {
return _validateMapSpread(mapConfig, element, value);
}

return true;
} else if (element is NullAwareElement) {
var value = verifier._evaluateAndReportError(element.value, errorCode);
if (value is! DartObjectImpl) return false;

var listElementType = this.listElementType;
if (listElementType != null) {
return _validateListExpression(
verifier._typeSystem.makeNullable(listElementType),
element.value,
value);
}

// If the value is `null`, skip verifying it with the set, as it won't be
// added as an element.
var setConfig = this.setConfig;
if (setConfig != null && !value.type.isDartCoreNull) {
return _validateSetExpression(setConfig, element.value, value);
}

return true;
}
throw UnsupportedError(
Expand Down Expand Up @@ -1272,6 +1292,9 @@ class _ConstLiteralVerifier {
var keyExpression = entry.key;
var valueExpression = entry.value;

var isKeyNullAware = entry.keyQuestion != null;
var isValueNullAware = entry.valueQuestion != null;

var keyValue = verifier._evaluateAndReportError(
keyExpression,
CompileTimeErrorCode.NON_CONSTANT_MAP_KEY,
Expand All @@ -1283,12 +1306,16 @@ class _ConstLiteralVerifier {

if (keyValue is DartObjectImpl) {
var keyType = keyValue.type;
var expectedKeyType = config.keyType;
if (isKeyNullAware) {
expectedKeyType = verifier._typeSystem.makeNullable(expectedKeyType);
}

if (!verifier._runtimeTypeMatch(keyValue, config.keyType)) {
if (!verifier._runtimeTypeMatch(keyValue, expectedKeyType)) {
verifier._errorReporter.atNode(
keyExpression,
CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
arguments: [keyType, config.keyType],
arguments: [keyType, expectedKeyType],
);
}

Expand All @@ -1301,20 +1328,32 @@ class _ConstLiteralVerifier {
);
}

var existingKey = config.uniqueKeys[keyValue];
if (existingKey != null) {
config.duplicateKeys[keyExpression] = existingKey;
} else {
config.uniqueKeys[keyValue] = keyExpression;
// Don't check the key for uniqueness if the key is null aware and is
// `null` or the value is null aware and is `null`, since it won't be
// added to the map in that case.
if ((!isKeyNullAware || !keyValue.type.isDartCoreNull) &&
(!isValueNullAware ||
valueValue is DartObjectImpl &&
!valueValue.type.isDartCoreNull)) {
var existingKey = config.uniqueKeys[keyValue];
if (existingKey != null) {
config.duplicateKeys[keyExpression] = existingKey;
} else {
config.uniqueKeys[keyValue] = keyExpression;
}
}
}

var expectedValueType = config.valueType;
if (isValueNullAware) {
expectedValueType = verifier._typeSystem.makeNullable(expectedValueType);
}
if (valueValue is DartObjectImpl) {
if (!verifier._runtimeTypeMatch(valueValue, config.valueType)) {
if (!verifier._runtimeTypeMatch(valueValue, expectedValueType)) {
verifier._errorReporter.atNode(
valueExpression,
CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE,
arguments: [valueValue.type, config.valueType],
arguments: [valueValue.type, expectedValueType],
);
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';

import '../dart/resolution/context_collection_resolution.dart';

main() {
defineReflectiveSuite(() {
defineReflectiveTests(NullAwareElementsConstLiteralsErrorTest);
});
}

@reflectiveTest
class NullAwareElementsConstLiteralsErrorTest extends PubPackageResolutionTest {
test_duplicated_in_key_named_null_aware_key_in_map() async {
await assertErrorsInCode('''
const intConst = 0;
const stringConst = "";
const map = {intConst: null, 0: ?intConst, null: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 73, 1,
contextMessages: [message(testFile, 57, 8)]),
]);
}

test_duplicated_int_in_set() async {
await assertErrorsInCode('''
const intConst = 0;
const stringConst = "";
const set = {0, ?intConst, stringConst};
''', [
error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 61, 8,
contextMessages: [message(testFile, 57, 1)]),
]);
}

test_duplicated_int_key_null_aware_key_in_map() async {
await assertErrorsInCode('''
const intConst = 0;
const stringConst = "";
const map = {intConst: null, ?0: intConst, null: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 74, 1,
contextMessages: [message(testFile, 57, 8)]),
]);
}

test_duplicated_null_in_set() async {
await assertErrorsInCode('''
const nullConst = null;
const intConst = 0;
const stringConst = "";
const set = {nullConst, null, intConst, stringConst};
''', [
error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 92, 4,
contextMessages: [message(testFile, 81, 9)]),
]);
}

test_duplicated_null_key_in_map() async {
await assertErrorsInCode('''
const nullConst = null;
const intConst = 0;
const stringConst = "";
const map = {null: 1, nullConst: 1, intConst: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 90, 9,
contextMessages: [message(testFile, 81, 4)]),
]);
}

test_duplicated_null_key_null_aware_value_in_map() async {
await assertErrorsInCode('''
const nullConst = null;
const intConst = 0;
const stringConst = "";
const map = {null: 1, nullConst: ?intConst, stringConst: 1};
''', [
error(CompileTimeErrorCode.EQUAL_KEYS_IN_CONST_MAP, 90, 9,
contextMessages: [message(testFile, 81, 4)]),
]);
}

test_duplicated_string_in_set() async {
await assertErrorsInCode('''
const intConst = 0;
const stringConst = "";
const set = {null, intConst, "", ?stringConst};
''', [
error(CompileTimeErrorCode.EQUAL_ELEMENTS_IN_CONST_SET, 78, 11,
contextMessages: [message(testFile, 73, 2)]),
]);
}

test_non_const_and_null_under_question_in_list() async {
await assertErrorsInCode('''
var nullVar = null;
const intConst = 0;
const stringConst = "";
const list = [?null, ?nullVar, intConst, stringConst];
''', [
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 86,
7),
error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 86, 7),
]);
}

test_non_const_in_key_under_question_in_map() async {
await assertErrorsInCode('''
const stringConst = "";
var intVar = 0;
const map = {null: 1, ?intVar: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 63, 6),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 63,
6),
]);
}

test_non_const_int_under_question_in_set() async {
await assertErrorsInCode('''
const nullConst = null;
const stringConst = "";
var intVar = 0;
const set = {nullConst, ?intVar, stringConst};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 89, 6),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 89,
6),
]);
}

test_non_const_int_value_under_question_map() async {
await assertErrorsInCode('''
const stringConst = "";
var intVar = 0;
const map = {null: 1, 0: ?intVar, stringConst: 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 66, 6),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 66,
6),
]);
}

test_non_const_null_key_under_question_in_map() async {
await assertErrorsInCode('''
var nullVar = null;
const intConst = 0;
const stringConst = "";
const map = {?nullVar: 1, intConst: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 78, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 78,
7),
]);
}

test_non_const_null_under_question_in_set() async {
await assertErrorsInCode('''
var nullVar = null;
const intConst = 0;
const stringConst = "";
const set = {?nullVar, intConst, stringConst};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 78, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 78,
7),
]);
}

test_non_const_null_value_under_question_in_map() async {
await assertErrorsInCode('''
var nullVar = null;
const intConst = 0;
const stringConst = "";
const map = {null: ?nullVar, intConst: 1, stringConst: 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 84, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 84,
7),
]);
}

test_non_const_string_key_under_question_in_map() async {
await assertErrorsInCode('''
var stringVar = "";
const map = {null: 1, 0: 1, ?stringVar: 1};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_KEY, 49, 9),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 49,
9),
]);
}

test_non_const_string_under_question_in_set() async {
await assertErrorsInCode('''
const nullConst = null;
const intConst = 0;
var stringVar = "";
const set = {nullConst, intConst, ?stringVar};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT, 99, 9),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 99,
9),
]);
}

test_non_const_string_value_under_question_in_map() async {
await assertErrorsInCode('''
var stringVar = "";
const map = {null: 1, 0: 1, "": ?stringVar};
''', [
error(CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE, 53, 9),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 53,
9),
]);
}

test_non_const_under_question_in_list() async {
await assertErrorsInCode('''
var nullVar = null;
const intConst = 0;
const stringConst = "";
const list = [?nullVar, intConst, stringConst];
''', [
error(CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT, 79, 7),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 79,
7),
]);
}
}
3 changes: 3 additions & 0 deletions pkg/analyzer/test/src/diagnostics/test_all.dart
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,8 @@ import 'not_map_spread_test.dart' as not_map_spread;
import 'not_null_aware_null_spread_test.dart' as not_null_aware_null_spread;
import 'null_argument_to_non_null_type_test.dart'
as null_argument_to_non_null_type;
import 'null_aware_elements_const_literals_error_test.dart'
as null_aware_elements_const_literals_error;
import 'null_check_always_fails_test.dart' as null_check_always_fails;
import 'null_safety_read_write_test.dart' as null_safety_read_write;
import 'nullable_type_in_catch_clause_test.dart'
Expand Down Expand Up @@ -1351,6 +1353,7 @@ main() {
not_map_spread.main();
not_null_aware_null_spread.main();
null_argument_to_non_null_type.main();
null_aware_elements_const_literals_error.main();
null_check_always_fails.main();
null_safety_read_write.main();
nullable_type_in_catch_clause.main();
Expand Down
Loading

0 comments on commit 95fe32c

Please sign in to comment.