[analyzer] Report more specific diagnostic codes instead of INVALID_CONSTANT.

Add a more specific, but for general use, diagnostic for when the evaluator encounters a type parameter. The errors should match more closely to the CFE errors now.

This CL also tidies up some other areas like `_evaluatePropertyAccess` and produces a better error than `INVALID_CONSTANT` when you try to access something that's not String.length.

Change-Id: I4780e6e52049887a0ee44cdf046968f332527079
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/322364
Commit-Queue: Kallen Tu <kallentu@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
This commit is contained in:
Kallen Tu 2023-08-29 22:36:02 +00:00 committed by Commit Queue
parent 2ee7f1ff0c
commit af24f1d61a
18 changed files with 280 additions and 202 deletions

View file

@ -445,6 +445,8 @@ CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET:
status: noFix
CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP:
status: noFix
CompileTimeErrorCode.CONST_TYPE_PARAMETER:
status: needsEvaluation
CompileTimeErrorCode.CONST_WITH_NON_CONST:
status: hasFix
CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:

View file

@ -535,6 +535,7 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
// Should not be a type parameter.
if (type.element is TypeParameterElement) {
_errorReporter.reportErrorForNode(errorCode, type);
return;
}
// Check type arguments.
var typeArguments = type.typeArguments;
@ -603,6 +604,11 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
CompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH) ||
identical(dataErrorCode,
CompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH) ||
identical(dataErrorCode, CompileTimeErrorCode.CONST_TYPE_PARAMETER) ||
identical(
dataErrorCode,
CompileTimeErrorCode
.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF) ||
identical(
dataErrorCode, CompileTimeErrorCode.VARIABLE_TYPE_MISMATCH) ||
identical(dataErrorCode, CompileTimeErrorCode.NON_BOOL_CONDITION) ||

View file

@ -836,7 +836,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
@override
Constant visitFunctionReference(FunctionReference node) {
var functionResult = _getConstant(node.function);
final functionResult = _getConstant(node.function);
if (functionResult is! DartObjectImpl) {
return functionResult;
}
@ -846,9 +846,9 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
// any type parameters contained therein are reported as non-constant in
// [ConstantVerifier].
if (node.typeArguments == null) {
var typeArgumentTypes = node.typeArgumentTypes;
final typeArgumentTypes = node.typeArgumentTypes;
if (typeArgumentTypes != null) {
var instantiatedTypeArgumentTypes = typeArgumentTypes.map((type) {
final instantiatedTypeArgumentTypes = typeArgumentTypes.map((type) {
if (type is TypeParameterType) {
return _lexicalTypeEnvironment?[type.element] ?? type;
} else {
@ -866,26 +866,39 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
}
}
var typeArgumentList = node.typeArguments;
final typeArgumentList = node.typeArguments;
if (typeArgumentList == null) {
return _instantiateFunctionType(node, functionResult);
}
var typeArguments = <DartType>[];
final typeArguments = <DartType>[];
for (var typeArgument in typeArgumentList.arguments) {
var object = _getConstant(typeArgument);
if (object is! DartObjectImpl) {
return object;
final typeArgumentConstant = _getConstant(typeArgument);
switch (typeArgumentConstant) {
case InvalidConstant(
errorCode: CompileTimeErrorCode.CONST_TYPE_PARAMETER
):
// If there's a type parameter error in the evaluated constant, we
// convert the message to a more specific function reference error.
// TODO(kallentu): Don't report error here.
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
typeArgument);
return InvalidConstant(typeArgument,
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF);
case InvalidConstant():
return typeArgumentConstant;
case DartObjectImpl():
final typeArgumentType = typeArgumentConstant.toTypeValue();
if (typeArgumentType == null) {
return InvalidConstant(
typeArgument, CompileTimeErrorCode.INVALID_CONSTANT);
}
// TODO(srawlins): Test type alias types (`typedef i = int`) used as
// type arguments. Possibly change implementation based on
// canonicalization rules.
typeArguments.add(typeArgumentType);
}
var typeArgumentType = object.toTypeValue();
if (typeArgumentType == null) {
return InvalidConstant(
typeArgument, CompileTimeErrorCode.INVALID_CONSTANT);
}
// TODO(srawlins): Test type alias types (`typedef i = int`) used as
// type arguments. Possibly change implementation based on
// canonicalization rules.
typeArguments.add(typeArgumentType);
}
return _dartObjectComputer.typeInstantiate(
functionResult, typeArguments, node.function);
@ -954,7 +967,8 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
if (!result.isBoolNumStringOrNull) {
// TODO(kallentu): Don't report error here.
_error(node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING, node);
return InvalidConstant(
node, CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_NUM_STRING);
}
@ -1070,11 +1084,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
if ((!_isNonNullableByDefault || node.isTypeLiteralInConstantPattern) &&
hasTypeParameterReference(type)) {
// TODO(kallentu): Don't report error here and report a more specific
// diagnostic
// TODO(kallentu): Don't report error here
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.INVALID_CONSTANT, node);
return InvalidConstant(node, CompileTimeErrorCode.INVALID_CONSTANT);
CompileTimeErrorCode.CONST_TYPE_PARAMETER, node);
return InvalidConstant(node, CompileTimeErrorCode.CONST_TYPE_PARAMETER);
} else if (node.isDeferred) {
return _getDeferredLibraryError(node, node.name2) ??
InvalidConstant(node, CompileTimeErrorCode.INVALID_CONSTANT);
@ -1129,10 +1142,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
// String.length
if (prefixElement is! InterfaceElement) {
final stringLengthResult =
_evaluateStringLength(prefixResult, node.identifier, node);
if (stringLengthResult != null) {
return stringLengthResult;
final propertyAccessResult =
_evaluatePropertyAccess(prefixResult, node.identifier, node);
if (propertyAccessResult != null) {
return propertyAccessResult;
}
}
}
@ -1182,10 +1195,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
return prefixResult;
}
final stringLengthResult =
_evaluateStringLength(prefixResult, node.propertyName, node);
if (stringLengthResult != null) {
return stringLengthResult;
final propertyAccessResult =
_evaluatePropertyAccess(prefixResult, node.propertyName, node);
if (propertyAccessResult != null) {
return propertyAccessResult;
}
}
return _getConstantValue(
@ -1380,7 +1393,8 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
return null;
}
case MapLiteralEntry():
return InvalidConstant(element, CompileTimeErrorCode.INVALID_CONSTANT);
return InvalidConstant(
element, CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP);
case SpreadElement():
var spread = _getConstant(element.expression);
switch (spread) {
@ -1405,7 +1419,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
switch (element) {
case Expression():
return InvalidConstant(element, CompileTimeErrorCode.INVALID_CONSTANT);
return InvalidConstant(element, CompileTimeErrorCode.EXPRESSION_IN_MAP);
case ForElement():
// TODO(kallentu): Don't report error here.
_errorReporter.reportErrorForNode(
@ -1508,7 +1522,8 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
return null;
}
case MapLiteralEntry():
return InvalidConstant(element, CompileTimeErrorCode.INVALID_CONSTANT);
return InvalidConstant(
element, CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP);
case SpreadElement():
var spread = _getConstant(element.expression);
switch (spread) {
@ -1578,12 +1593,12 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
_errorReporter.reportErrorForNode(code, node);
}
/// Attempt to evaluate a constant that reads the length of a `String`.
/// Attempt to evaluate a constant property access.
///
/// Return a valid [DartObjectImpl] if the given [targetResult] represents a
/// `String` and the [identifier] is `length`, an [InvalidConstant] if there's
/// an error, and `null` otherwise.
Constant? _evaluateStringLength(DartObjectImpl targetResult,
Constant? _evaluatePropertyAccess(DartObjectImpl targetResult,
SimpleIdentifier identifier, AstNode errorNode) {
if (identifier.staticElement?.enclosingElement is ExtensionElement) {
_errorReporter.reportErrorForNode(
@ -1592,23 +1607,33 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
errorNode, CompileTimeErrorCode.CONST_EVAL_EXTENSION_METHOD);
}
if (identifier.name == 'length') {
final targetType = targetResult.type;
if (!(targetType is InterfaceType && targetType.isDartCoreString)) {
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS,
errorNode,
[identifier.name, targetType]);
return InvalidConstant(
errorNode, CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS,
arguments: [identifier.name, targetType]);
}
final targetType = targetResult.type;
// Evaluate a constant that reads the length of a `String`.
if (identifier.name == 'length' &&
targetType is InterfaceType &&
targetType.isDartCoreString) {
return _dartObjectComputer.stringLength(errorNode, targetResult);
}
// TODO(kallentu): Make a more specific error here if we aren't accessing
// the '.length' property.
return null;
final element = identifier.staticElement;
if (element != null && element is ExecutableElement && element.isStatic) {
return null;
}
// No other property access is allowed except for `.length` of a `String`.
// TODO(kallentu): Don't report error here.
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS, errorNode, [
identifier.name,
targetType.getDisplayString(withNullability: _isNonNullableByDefault)
]);
return InvalidConstant(
errorNode, CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS,
arguments: [
identifier.name,
targetType.getDisplayString(withNullability: _isNonNullableByDefault)
]);
}
/// Return a [Constant], evaluated by the [ConstantVisitor].
@ -1650,8 +1675,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
(expression.tearOffTypeArgumentTypes?.any(hasTypeParameterReference) ??
false)) {
// TODO(kallentu): Don't report error here.
_error(expression, null);
return InvalidConstant.genericError(expression);
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_TYPE_PARAMETER, expression);
return InvalidConstant(
expression, CompileTimeErrorCode.CONST_TYPE_PARAMETER);
}
if (variableElement is VariableElementImpl) {
@ -1748,7 +1775,7 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
// Constants may refer to type parameters only if the constructor-tearoffs
// feature is enabled.
if (_library.featureSet.isEnabled(Feature.constructor_tearoffs)) {
var typeArgument = _lexicalTypeEnvironment?[variableElement];
final typeArgument = _lexicalTypeEnvironment?[variableElement];
if (typeArgument != null) {
return DartObjectImpl(
typeSystem,
@ -1756,6 +1783,10 @@ class ConstantVisitor extends UnifyingAstVisitor<Constant> {
TypeState(typeArgument),
);
}
_errorReporter.reportErrorForNode(
CompileTimeErrorCode.CONST_TYPE_PARAMETER, errorNode2);
return InvalidConstant(
errorNode2, CompileTimeErrorCode.CONST_TYPE_PARAMETER);
}
}

View file

@ -1027,6 +1027,14 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
hasPublishedDocs: true,
);
/// No parameters.
static const CompileTimeErrorCode CONST_TYPE_PARAMETER = CompileTimeErrorCode(
'CONST_TYPE_PARAMETER',
"Type parameters can't be used in a constant expression.",
correctionMessage:
"Try replacing the type parameter with a different type.",
);
/// No parameters.
static const CompileTimeErrorCode CONST_WITH_NON_CONST = CompileTimeErrorCode(
'CONST_WITH_NON_CONST',

View file

@ -138,6 +138,7 @@ const List<ErrorCode> errorCodeValues = [
CompileTimeErrorCode.CONST_SET_ELEMENT_NOT_PRIMITIVE_EQUALITY,
CompileTimeErrorCode.CONST_SPREAD_EXPECTED_LIST_OR_SET,
CompileTimeErrorCode.CONST_SPREAD_EXPECTED_MAP,
CompileTimeErrorCode.CONST_TYPE_PARAMETER,
CompileTimeErrorCode.CONST_WITH_NON_CONST,
CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT,
CompileTimeErrorCode.CONST_WITH_NON_TYPE,

View file

@ -986,6 +986,7 @@ class _ConstantAnalysisErrorListener extends AnalysisErrorListener {
case CompileTimeErrorCode.CONST_EVAL_FOR_ELEMENT:
case CompileTimeErrorCode.CONST_MAP_KEY_NOT_PRIMITIVE_EQUALITY:
case CompileTimeErrorCode.CONST_SET_ELEMENT_NOT_PRIMITIVE_EQUALITY:
case CompileTimeErrorCode.CONST_TYPE_PARAMETER:
case CompileTimeErrorCode.CONST_WITH_NON_CONST:
case CompileTimeErrorCode.CONST_WITH_NON_CONSTANT_ARGUMENT:
case CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS:

View file

@ -3034,6 +3034,10 @@ CompileTimeErrorCode:
const Map<String, int> map1 = {};
const Map<String, int> map2 = {...map1};
```
CONST_TYPE_PARAMETER:
problemMessage: "Type parameters can't be used in a constant expression."
correctionMessage: Try replacing the type parameter with a different type.
comment: No parameters.
CONST_WITH_NON_CONST:
problemMessage: "The constructor being called isn't a const constructor."
correctionMessage: "Try removing 'const' from the constructor invocation."

View file

@ -542,6 +542,22 @@ void f(Object? x) {
''');
}
test_typeParameter() async {
await assertErrorsInCode('''
class A<X> {
const A();
void m() {
const x = X;
}
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 49, 1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 53, 1),
]);
final result = _localVar('x');
_assertNull(result);
}
test_visitBinaryExpression_extensionMethod() async {
await assertErrorsInCode('''
extension on Object {
@ -1102,7 +1118,8 @@ class C<T> {
const C({this.p = f});
}
''', [
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 83, 1),
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
83, 1),
]);
}
@ -1223,8 +1240,7 @@ class C<U> {
error(WarningCode.UNUSED_LOCAL_VARIABLE, 55, 1),
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
61, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 61,
1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 61, 1),
]);
}
@ -1668,8 +1684,7 @@ void f<T>(Object? x) {
if (x case const (T)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 43, 1),
]);
}
@ -1679,8 +1694,7 @@ void f<T>(Object? x) {
if (x case const (List<T>)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 7),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 43, 7),
]);
}
@ -2265,23 +2279,6 @@ const c = {1, ...{2, 3}, 4};
expect(result.toSetValue()!.map((e) => e.toIntValue()), [1, 2, 3, 4]);
}
test_typeParameter() async {
await assertErrorsInCode('''
class A<X> {
const A();
void m() {
const x = X;
}
}
''', [
error(WarningCode.UNUSED_LOCAL_VARIABLE, 49, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 53,
1),
]);
final result = _localVar('x');
_assertNull(result);
}
test_visitAsExpression_instanceOfSameClass() async {
await resolveTestCode('''
const a = const A();

View file

@ -16,6 +16,33 @@ main() {
@reflectiveTest
class ConstEvalPropertyAccessTest extends PubPackageResolutionTest {
test_constructorFieldInitializer_fromSeparateLibrary() async {
newFile('$testPackageLibPath/lib.dart', r'''
class A<T> {
final int f;
const A() : f = T.foo;
}
''');
await assertErrorsInCode(r'''
import 'lib.dart';
const a = const A();
''', [
error(
CompileTimeErrorCode.CONST_EVAL_PROPERTY_ACCESS,
29,
9,
contextMessages: [
ExpectedContextMessage(
convertPath('$testPackageLibPath/lib.dart'), 46, 5,
text:
"The error is in the field initializer of 'A', and occurs here."),
],
),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 29,
9),
]);
}
test_length_invalidTarget() async {
await assertErrorsInCode('''
void main() {

View file

@ -0,0 +1,47 @@
// Copyright (c) 2023, 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(ConstTypeParameterTest);
});
}
@reflectiveTest
class ConstTypeParameterTest extends PubPackageResolutionTest {
test_constantPattern_typeParameter() async {
await assertErrorsInCode(r'''
void f<T>(x) {
if (x case T) {}
}
''', [
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 28, 1),
]);
}
test_constantPattern_typeParameter_nested() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (T)) {}
}
''', [
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 43, 1),
]);
}
test_constantPattern_typeParameter_nested2() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (List<T>)) {}
}
''', [
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 43, 7),
]);
}
}

View file

@ -135,6 +135,66 @@ class A<T> {
@reflectiveTest
class ConstWithTypeParametersFunctionTearoffTest
extends PubPackageResolutionTest {
test_appliedTypeParameter_defaultConstructorValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
class C<T> {
final void Function(T) p;
const C({this.p = f});
}
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
83, 1),
]);
}
test_appliedTypeParameter_defaultFunctionValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(T) p = f]) {}
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
56, 1),
]);
}
test_appliedTypeParameter_defaultMethodValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
class C<T> {
void foo([void Function(T) p = f]) {}
}
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
68, 1),
]);
}
test_appliedTypeParameter_nested() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(List<T>) p = f]) {}
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
62, 1),
]);
}
test_appliedTypeParameter_nestedFunction() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(T Function()) p = f]) {}
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
67, 1)
]);
}
test_defaultValue() async {
await assertErrorsInCode('''
void f<T>(T a) {}
@ -144,7 +204,7 @@ class A<U> {
''', [
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
65, 1),
error(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 65, 1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 65, 1),
]);
}
@ -160,8 +220,7 @@ class A<U> {
error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
60, 1),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 60,
1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 60, 1),
]);
}
@ -180,6 +239,7 @@ class A<U> {
5),
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
58, 1),
error(CompileTimeErrorCode.CONST_TYPE_PARAMETER, 58, 1),
]);
}

View file

@ -557,39 +557,6 @@ GuardedPattern
''');
}
test_typeLiteral_typeParameter() async {
await assertErrorsInCode(r'''
void f<T>(x) {
if (x case T) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
28, 1),
]);
}
test_typeLiteral_typeParameter_nested() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (T)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 1),
]);
}
test_typeLiteral_typeParameter_nested2() async {
await assertErrorsInCode(r'''
void f<T>(Object? x) {
if (x case const (List<T>)) {}
}
''', [
error(CompileTimeErrorCode.CONSTANT_PATTERN_WITH_NON_CONSTANT_EXPRESSION,
43, 7),
]);
}
test_unresolvedIdentifier() async {
await assertErrorsInCode(r'''
void f(Object? x) {

View file

@ -49,33 +49,6 @@ class A {
]);
}
test_constructorFieldInitializer_fromSeparateLibrary() async {
newFile('$testPackageLibPath/lib.dart', r'''
class A<T> {
final int f;
const A() : f = T.foo;
}
''');
await assertErrorsInCode(r'''
import 'lib.dart';
const a = const A();
''', [
error(
CompileTimeErrorCode.INVALID_CONSTANT,
29,
9,
contextMessages: [
ExpectedContextMessage(
convertPath('$testPackageLibPath/lib.dart'), 46, 5,
text:
"The error is in the field initializer of 'A', and occurs here."),
],
),
error(CompileTimeErrorCode.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE, 29,
9),
]);
}
test_in_initializer_field_as() async {
await assertNoErrorsInCode('''
class C<T> {

View file

@ -5,7 +5,6 @@
import 'package:analyzer/src/error/codes.dart';
import 'package:test_reflective_loader/test_reflective_loader.dart';
import '../../generated/test_support.dart';
import '../dart/resolution/context_collection_resolution.dart';
main() {
@ -16,51 +15,6 @@ main() {
@reflectiveTest
class NonConstantDefaultValueTest extends PubPackageResolutionTest {
test_appliedTypeParameter_defaultConstructorValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
class C<T> {
final void Function(T) p;
const C({this.p = f});
}
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 83, 1)]);
}
test_appliedTypeParameter_defaultFunctionValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(T) p = f]) {}
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 56, 1)]);
}
test_appliedTypeParameter_defaultMethodValue() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
class C<T> {
void foo([void Function(T) p = f]) {}
}
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 68, 1)]);
}
test_appliedTypeParameter_nested() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(List<T>) p = f]) {}
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 62, 1)]);
}
test_appliedTypeParameter_nestedFunction() async {
await assertErrorsInCode(r'''
void f<T>(T t) => t;
void bar<T>([void Function(T Function()) p = f]) {}
''', [ExpectedError(CompileTimeErrorCode.NON_CONSTANT_DEFAULT_VALUE, 67, 1)]);
}
test_constructor_named() async {
await assertErrorsInCode(r'''
class A {

View file

@ -132,6 +132,7 @@ import 'const_set_element_not_primitive_equality_test.dart'
import 'const_spread_expected_list_or_set_test.dart'
as const_spread_expected_list_or_set;
import 'const_spread_expected_map_test.dart' as const_spread_expected_map;
import 'const_type_parameter_test.dart' as const_type_parameter;
import 'const_with_non_const_test.dart' as const_with_non_const;
import 'const_with_non_constant_argument_test.dart'
as const_with_non_constant_argument;
@ -986,6 +987,7 @@ main() {
const_set_element_not_primitive_equality.main();
const_spread_expected_list_or_set.main();
const_spread_expected_map.main();
const_type_parameter.main();
const_with_non_const.main();
const_with_non_constant_argument.main();
const_with_non_type.main();

View file

@ -15,37 +15,37 @@ class Annotation {
class Class<T, @Annotation(T) U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
void function<T, @Annotation(T) U>() {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
extension Extension<T, @Annotation(T) U> on Map<T, U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
class C {
void method<T, @Annotation(T) U>() {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
}
mixin Mixin<T, @Annotation(T) U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
typedef void Typedef1<T, @Annotation(T) U>(T t, U u);
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
typedef Typedef2<T, @Annotation(T) U> = void Function(T t, U u);
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.

View file

@ -9,10 +9,8 @@ class C<T> {
const List lst = const [
T
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_INITIALIZED_WITH_NON_CONSTANT_VALUE
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
// ^
// [analyzer] COMPILE_TIME_ERROR.NON_CONSTANT_LIST_ELEMENT
];
}
}

View file

@ -15,37 +15,37 @@ class Annotation {
class Class<T, @Annotation(T) U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
void function<T, @Annotation(T) U>() {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
extension Extension<T, @Annotation(T) U> on Map<T, U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
class C {
void method<T, @Annotation(T) U>() {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
}
mixin Mixin<T, @Annotation(T) U> {}
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
typedef void Typedef1<T, @Annotation(T) U>(T t, U u);
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.
typedef Typedef2<T, @Annotation(T) U> = void Function(T t, U u);
// ^
// [analyzer] COMPILE_TIME_ERROR.CONST_WITH_NON_CONSTANT_ARGUMENT
// [analyzer] COMPILE_TIME_ERROR.CONST_TYPE_PARAMETER
// [cfe] Type variables can't be used as constants.