mirror of
https://github.com/dart-lang/sdk
synced 2024-11-02 15:17:07 +00:00
Check type parameters in const function tearoff
Fixes https://github.com/dart-lang/sdk/issues/47213 Change-Id: I6c1c7e386e64b877e1ea7d312335d924488f2306 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/214134 Commit-Queue: Samuel Rawlins <srawlins@google.com> Reviewed-by: Brian Wilkerson <brianwilkerson@google.com> Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
parent
f1e6092dd8
commit
1379c867a4
5 changed files with 97 additions and 0 deletions
|
@ -141,6 +141,7 @@ const List<ErrorCode> errorCodeValues = [
|
|||
CompileTimeErrorCode.CONST_WITH_NON_TYPE,
|
||||
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS,
|
||||
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF,
|
||||
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
|
||||
CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR,
|
||||
CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR_DEFAULT,
|
||||
CompileTimeErrorCode.CONTINUE_LABEL_ON_SWITCH,
|
||||
|
|
|
@ -128,6 +128,21 @@ class ConstantVerifier extends RecursiveAstVisitor<void> {
|
|||
_validateDefaultValues(node.parameters);
|
||||
}
|
||||
|
||||
@override
|
||||
void visitFunctionReference(FunctionReference node) {
|
||||
super.visitFunctionReference(node);
|
||||
if (node.inConstantContext) {
|
||||
var typeArguments = node.typeArguments;
|
||||
if (typeArguments == null) {
|
||||
return;
|
||||
}
|
||||
for (var typeArgument in typeArguments.arguments) {
|
||||
_checkForConstWithTypeParameters(typeArgument,
|
||||
CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void visitGenericFunctionType(GenericFunctionType node) {
|
||||
// TODO(srawlins): Also check interface types (TypeName?).
|
||||
|
|
|
@ -2898,6 +2898,18 @@ class CompileTimeErrorCode extends AnalyzerErrorCode {
|
|||
uniqueName: 'CONST_WITH_TYPE_PARAMETERS_CONSTRUCTOR_TEAROFF',
|
||||
hasPublishedDocs: true);
|
||||
|
||||
/**
|
||||
* No parameters.
|
||||
*/
|
||||
static const CompileTimeErrorCode
|
||||
CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF = CompileTimeErrorCode(
|
||||
'CONST_WITH_TYPE_PARAMETERS',
|
||||
"A constant function tearoff can't use a type parameter as a type "
|
||||
"argument.",
|
||||
correction: "Try replacing the type parameter with a different type.",
|
||||
uniqueName: 'CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF',
|
||||
hasPublishedDocs: true);
|
||||
|
||||
/**
|
||||
* 16.12.2 Const: It is a compile-time error if <i>T.id</i> is not the name of
|
||||
* a constant constructor declared by the type <i>T</i>.
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import 'package:analyzer/src/error/codes.dart';
|
||||
import 'package:test/test.dart';
|
||||
import 'package:test_reflective_loader/test_reflective_loader.dart';
|
||||
|
||||
import '../dart/resolution/context_collection_resolution.dart';
|
||||
|
@ -10,6 +11,7 @@ import '../dart/resolution/context_collection_resolution.dart';
|
|||
main() {
|
||||
defineReflectiveSuite(() {
|
||||
defineReflectiveTests(ConstWithTypeParametersConstructorTearoffTest);
|
||||
defineReflectiveTests(ConstWithTypeParametersFunctionTearoffTest);
|
||||
defineReflectiveTests(ConstWithTypeParametersTest);
|
||||
});
|
||||
}
|
||||
|
@ -83,6 +85,71 @@ class A<T> {
|
|||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ConstWithTypeParametersFunctionTearoffTest
|
||||
extends PubPackageResolutionTest {
|
||||
@FailingTest(
|
||||
reason: 'The default value of an optional parameter is not considered a '
|
||||
'"constant context". Currently only ConstantVerifier checks '
|
||||
'CONST_WITH_TYPE_PARAMETERS (and related) errors, and only for '
|
||||
'constant contexts. These checks should probably be moved to '
|
||||
'ConstantVisitor (evaluation.dart), so as to check all expressions '
|
||||
'expected to be constant expressions. Another example of a missing '
|
||||
'error is a field initializer in a class with a constant constructor.',
|
||||
)
|
||||
test_defaultValue() async {
|
||||
addTestFile('''
|
||||
void f<T>(T a) {}
|
||||
class A<U> {
|
||||
void m([void Function(U) fn = f<U>]) {}
|
||||
}
|
||||
''');
|
||||
await resolveTestFile();
|
||||
expect(result.errors, isNotEmpty);
|
||||
}
|
||||
|
||||
test_direct() async {
|
||||
await assertErrorsInCode('''
|
||||
void f<T>(T a) {}
|
||||
class A<U> {
|
||||
void m() {
|
||||
const c = f<U>;
|
||||
}
|
||||
}
|
||||
''', [
|
||||
error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
|
||||
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
|
||||
60, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_indirect() async {
|
||||
await assertErrorsInCode('''
|
||||
void f<T>(T a) {}
|
||||
class A<U> {
|
||||
void m() {
|
||||
const c = f<List<U>>;
|
||||
}
|
||||
}
|
||||
''', [
|
||||
error(HintCode.UNUSED_LOCAL_VARIABLE, 54, 1),
|
||||
error(CompileTimeErrorCode.CONST_WITH_TYPE_PARAMETERS_FUNCTION_TEAROFF,
|
||||
65, 1),
|
||||
]);
|
||||
}
|
||||
|
||||
test_nonConst() async {
|
||||
await assertNoErrorsInCode('''
|
||||
void f<T>(T a) {}
|
||||
class A<U> {
|
||||
void m() {
|
||||
f<U>;
|
||||
}
|
||||
}
|
||||
''');
|
||||
}
|
||||
}
|
||||
|
||||
@reflectiveTest
|
||||
class ConstWithTypeParametersTest extends PubPackageResolutionTest {
|
||||
test_direct() async {
|
||||
|
|
|
@ -2648,6 +2648,8 @@ _A constant constructor tearoff can't use a type parameter as a type argument._
|
|||
|
||||
_A constant creation can't use a type parameter as a type argument._
|
||||
|
||||
_A constant function tearoff can't use a type parameter as a type argument._
|
||||
|
||||
#### Description
|
||||
|
||||
The analyzer produces this diagnostic when a type parameter is used as a
|
||||
|
|
Loading…
Reference in a new issue