diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart index 316443aadbd6..1557389fb24c 100644 --- a/pkg/analyzer/lib/error/error.dart +++ b/pkg/analyzer/lib/error/error.dart @@ -130,6 +130,7 @@ const List errorCodeValues = const [ CompileTimeErrorCode.FINAL_INITIALIZED_MULTIPLE_TIMES, CompileTimeErrorCode.GENERIC_FUNCTION_TYPED_PARAM_UNSUPPORTED, CompileTimeErrorCode.GENERIC_FUNCTION_TYPE_CANNOT_BE_BOUND, + CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, CompileTimeErrorCode.GETTER_AND_METHOD_WITH_SAME_NAME, CompileTimeErrorCode.IMPLEMENTS_DEFERRED_CLASS, CompileTimeErrorCode.IMPLEMENTS_DISALLOWED_CLASS, diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart index e071c482e5c6..5d1badaeaa40 100644 --- a/pkg/analyzer/lib/src/error/codes.dart +++ b/pkg/analyzer/lib/src/error/codes.dart @@ -2409,6 +2409,18 @@ class CompileTimeErrorCode extends ErrorCode { correction: 'Try making the free variable in the function type part' ' of the larger declaration signature'); + /** + * It is a compile-time error if a generic function type is used as an actual + * type argument. + */ + static const CompileTimeErrorCode GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT = + const CompileTimeErrorCode( + 'GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT', + "Generic function has type parameters '<{0}>', so it may not be used" + ' as a type argument', + correction: "Try removing the type parameters '<{0}>', or using" + " 'dynamic' as the type argument here instead of a function."); + /** * 15.3.1 Typedef: Any self reference, either directly, or recursively via * another typedef, is a compile time error. diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart index 7cf79c09cf0f..b470ac2bbd3c 100644 --- a/pkg/analyzer/lib/src/generated/error_verifier.dart +++ b/pkg/analyzer/lib/src/generated/error_verifier.dart @@ -5947,11 +5947,19 @@ class ErrorVerifier extends RecursiveAstVisitor { for (int i = 0; i < loopThroughIndex; i++) { TypeAnnotation argumentNode = argumentNodes[i]; DartType argType = argumentNode.type; + if (argType is FunctionType && argType.typeFormals.isNotEmpty) { + _errorReporter.reportTypeErrorForNode( + CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, + argumentNode, + [argType.typeFormals.join(', ')]); + continue; + } DartType boundType = parameterElements[i].bound; if (argType != null && boundType != null) { if (shouldSubstitute) { boundType = boundType.substitute2(arguments, parameterTypes); } + if (!_typeSystem.isSubtypeOf(argType, boundType)) { ErrorCode errorCode; if (_isInConstInstanceCreation) { @@ -6471,6 +6479,15 @@ class ErrorVerifier extends RecursiveAstVisitor { // > // DartType argType = typeArgs[i]; + + if (argType is FunctionType && argType.typeFormals.isNotEmpty) { + _errorReporter.reportTypeErrorForNode( + CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT, + typeArgumentList[i], + [argType.typeFormals.join(', ')]); + continue; + } + DartType bound = fnTypeParams[i].bound.substitute2(typeArgs, fnTypeParams); if (!_typeSystem.isSubtypeOf(argType, bound)) { diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart index e54318adca83..a50097524bb6 100644 --- a/pkg/analyzer/lib/src/generated/type_system.dart +++ b/pkg/analyzer/lib/src/generated/type_system.dart @@ -15,7 +15,8 @@ import 'package:analyzer/error/listener.dart' show ErrorReporter; import 'package:analyzer/src/dart/element/element.dart'; import 'package:analyzer/src/dart/element/member.dart' show TypeParameterMember; import 'package:analyzer/src/dart/element/type.dart'; -import 'package:analyzer/src/error/codes.dart' show StrongModeCode; +import 'package:analyzer/src/error/codes.dart' + show StrongModeCode, CompileTimeErrorCode; import 'package:analyzer/src/generated/engine.dart' show AnalysisContext, AnalysisOptionsImpl; import 'package:analyzer/src/generated/resolver.dart' show TypeProvider; diff --git a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart index 8232bc7da183..97fa300c82a9 100644 --- a/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart +++ b/pkg/analyzer/test/generated/compile_time_error_code_kernel_test.dart @@ -3133,6 +3133,34 @@ class CompileTimeErrorCodeTest_Kernel extends CompileTimeErrorCodeTest_Driver { test_genericFunctionTypeAsBound_typedef() async { await super.test_genericFunctionTypeAsBound_typedef(); } + + @override + @failingTest + @potentialAnalyzerProblem + test_genericFunctionTypeArgument_class() async { + await super.test_genericFunctionTypeArgument_class(); + } + + @override + @failingTest + @potentialAnalyzerProblem + test_genericFunctionTypeArgument_functionType() async { + await super.test_genericFunctionTypeArgument_functionType(); + } + + @override + @failingTest + @potentialAnalyzerProblem + test_genericFunctionTypeArgument_function() async { + await super.test_genericFunctionTypeArgument_function(); + } + + @override + @failingTest + @potentialAnalyzerProblem + test_genericFunctionTypeArgument_method() async { + await super.test_genericFunctionTypeArgument_method(); + } } /// Tests marked with this annotation fail because of a Fasta problem. diff --git a/pkg/analyzer/test/generated/compile_time_error_code_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_test.dart index 8b911026b7fc..6f250b257f5f 100644 --- a/pkg/analyzer/test/generated/compile_time_error_code_test.dart +++ b/pkg/analyzer/test/generated/compile_time_error_code_test.dart @@ -7063,6 +7063,98 @@ f() { return const G(); }'''); verify([source]); } + test_genericFunctionTypeArgument_class() async { + Source source = addSource(r''' +class C {} +C(T)> c;'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + test_genericFunctionTypeArgument_functionType() async { + Source source = addSource(r''' +T Function(T) f; +main() { f(S)>(null); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + test_genericFunctionTypeArgument_function() async { + Source source = addSource(r''' +T f(T) => null; +main() { f(S)>(null); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + test_genericFunctionTypeArgument_method() async { + Source source = addSource(r''' +class C { + T f(T) => null; +} +main() { new C().f(S)>(null); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + @failingTest + test_genericFunctionTypeArgument_inference_functionType() async { + // TODO(mfairhurst) how should these inference errors be reported? + Source source = addSource(r''' +T Function(T) f; +main() { f((S s) => s); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + @failingTest + test_genericFunctionTypeArgument_inference_function() async { + // TODO(mfairhurst) how should these inference errors be reported? + Source source = addSource(r''' +T f(T) => null; +main() { f((S s) => s); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + @failingTest + test_genericFunctionTypeArgument_inference_method() async { + // TODO(mfairhurst) how should these inference errors be reported? + Source source = addSource(r''' +class C { + T f(T) => null; +} +main() { new C().f((S s) => s); }'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + + @failingTest + test_genericFunctionTypeArgument_typedef() async { + // TODO(mfairhurst) diagnose these parse errors to give the correct error + Source source = addSource(r''' +typedef T f(T t); +final T(int)> x = null;'''); + await computeAnalysisResult(source); + assertErrors(source, + [CompileTimeErrorCode.GENERIC_FUNCTION_CANNOT_BE_TYPE_ARGUMENT]); + verify([source]); + } + test_undefinedAnnotation_unresolved_identifier() async { Source source = addSource(r''' @unresolved diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status index 79bacbd99fb1..705f19039379 100644 --- a/tests/language_2/language_2_analyzer.status +++ b/tests/language_2/language_2_analyzer.status @@ -33,7 +33,6 @@ final_syntax_test/03: Fail # Issue 11124 final_syntax_test/04: Fail # Issue 11124 function_type_parameter2_negative_test: CompileTimeError function_type_parameter_negative_test: CompileTimeError -generic_function_type_as_type_argument_test/01: MissingCompileTimeError # Issue 30929 generic_function_type_as_type_argument_test/02: MissingCompileTimeError # Issue 30929 generic_local_functions_test: CompileTimeError # Issue 28515 generic_methods_generic_function_parameter_test: CompileTimeError # Issue 28515 @@ -1354,7 +1353,6 @@ generic_constructor_mixin3_test/01: MissingCompileTimeError generic_constructor_mixin_test/01: MissingCompileTimeError generic_field_mixin6_test/01: MissingCompileTimeError generic_function_typedef2_test/04: MissingCompileTimeError -generic_methods_generic_function_result_test/01: MissingCompileTimeError # Issue #30207 generic_methods_overriding_test/01: MissingCompileTimeError generic_test/01: MissingCompileTimeError identical_const_test/01: MissingCompileTimeError diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status index d93e1c849372..a643e677babd 100644 --- a/tests/language_2/language_2_dartdevc.status +++ b/tests/language_2/language_2_dartdevc.status @@ -384,6 +384,7 @@ function_propagation_test: RuntimeError function_type_parameter2_negative_test: Fail function_type_parameter_negative_test: Fail generic_function_bounds_test: RuntimeError +generic_function_type_as_type_argument_test/01: MissingCompileTimeError # Issue 29920 generic_methods_generic_function_result_test/01: MissingCompileTimeError generic_methods_overriding_test/01: MissingCompileTimeError # Issue 29920 generic_methods_recursive_bound_test/02: MissingCompileTimeError @@ -666,7 +667,6 @@ flatten_test/09: MissingRuntimeError # Issue 29920 flatten_test/12: MissingRuntimeError # Issue 29920 for_variable_capture_test: RuntimeError # Issue 29920; Expect.equals(expected: <1>, actual: <0>) fails. function_subtype_inline2_test: RuntimeError # Expect.fail('Missing type error: 'new C.c1(m2)'.') -generic_function_type_as_type_argument_test/01: MissingCompileTimeError # Issue 29920 generic_function_type_as_type_argument_test/02: MissingCompileTimeError # Issue 29920 generic_instanceof2_test: RuntimeError # Issue 29920; ReferenceError: FooOfK$String is not defined generic_is_check_test: RuntimeError # Issue 29920; Expect.isTrue(false) fails.