From 2c02737d7af9227fe8aebcc0fd6ae294f925abd5 Mon Sep 17 00:00:00 2001 From: Konstantin Shcheglov Date: Sat, 27 Mar 2021 21:08:06 +0000 Subject: [PATCH] Support for bounds of generic function types for raw-depends / not simply bounded. Change-Id: I568f4ebb922b3ce40debff1f4ce20a9ac580f29d Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/193141 Reviewed-by: Samuel Rawlins Reviewed-by: Brian Wilkerson Commit-Queue: Konstantin Shcheglov --- .../lib/src/summary2/default_types_builder.dart | 13 +++++++++++++ pkg/analyzer/lib/src/summary2/simply_bounded.dart | 10 ++++++++++ .../diagnostics/not_instantiated_bound_test.dart | 8 ++++++++ .../test/src/summary/resynthesize_common.dart | 14 ++++++++++++++ tests/language/regress/regress33479_test.dart | 6 +++++- tests/language_2/regress/regress33479_test.dart | 6 +++++- 6 files changed, 55 insertions(+), 2 deletions(-) diff --git a/pkg/analyzer/lib/src/summary2/default_types_builder.dart b/pkg/analyzer/lib/src/summary2/default_types_builder.dart index 1153c8eae0a..8657fc787f4 100644 --- a/pkg/analyzer/lib/src/summary2/default_types_builder.dart +++ b/pkg/analyzer/lib/src/summary2/default_types_builder.dart @@ -289,6 +289,19 @@ class DefaultTypesBuilder { visited, ), ); + for (var typeParameter in startType.typeFormals) { + var bound = typeParameter.bound; + if (bound != null) { + paths.addAll( + _findRawTypePathsToDeclaration( + startParameter, + bound, + end, + visited, + ), + ); + } + } for (var formalParameter in startType.parameters) { paths.addAll( _findRawTypePathsToDeclaration( diff --git a/pkg/analyzer/lib/src/summary2/simply_bounded.dart b/pkg/analyzer/lib/src/summary2/simply_bounded.dart index a325de8a852..45a033635da 100644 --- a/pkg/analyzer/lib/src/summary2/simply_bounded.dart +++ b/pkg/analyzer/lib/src/summary2/simply_bounded.dart @@ -145,6 +145,7 @@ class SimplyBoundedDependencyWalker var collector = _TypeCollector(); if (type is GenericFunctionType) { collector.addType(type.returnType); + collector.visitTypeParameters(type.typeParameters); collector.visitParameters(type.parameters); } else { collector.addType(type); @@ -283,6 +284,7 @@ class SimplyBoundedNode extends graph.Node { if (type is GenericFunctionType) { var collector = _TypeCollector(); collector.addType(type.returnType); + collector.visitTypeParameters(type.typeParameters); collector.visitParameters(type.parameters); for (var type in collector.types) { if (!_visitType(dependencies, type, allowTypeParameters)) { @@ -326,4 +328,12 @@ class _TypeCollector { visitParameter(parameter); } } + + void visitTypeParameters(TypeParameterList? node) { + if (node != null) { + for (var typeParameter in node.typeParameters) { + addType(typeParameter.bound); + } + } + } } diff --git a/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart b/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart index d2c6f73cb19..c7254f75605 100644 --- a/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart +++ b/pkg/analyzer/test/src/diagnostics/not_instantiated_bound_test.dart @@ -102,6 +102,14 @@ class A {} ]); } + test_class_recursion_notInstantiated_genericFunctionType2() async { + await assertErrorsInCode(r''' +class A()> {} +''', [ + error(CompileTimeErrorCode.NOT_INSTANTIATED_BOUND, 42, 1), + ]); + } + test_class_recursion_typedef_notInstantiated() async { await assertErrorsInCode(r''' typedef F(C value); diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart index 9a6f8148b94..7403527fade 100644 --- a/pkg/analyzer/test/src/summary/resynthesize_common.dart +++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart @@ -1778,6 +1778,20 @@ notSimplyBounded class A)> { withTypeParameterVariance: true); } + test_class_typeParameters_defaultType_cycle_genericFunctionType2() async { + featureSet = FeatureSets.genericMetadata; + var library = await checkLibrary(r''' +class C()> {} +'''); + checkElementText( + library, + r''' +notSimplyBounded class C>()> { +} +''', + withTypeParameterVariance: true); + } + test_class_typeParameters_defaultType_functionTypeAlias_contravariant_legacy() async { featureSet = FeatureSets.beforeNullSafe; var library = await checkLibrary(r''' diff --git a/tests/language/regress/regress33479_test.dart b/tests/language/regress/regress33479_test.dart index 568b6f80b0a..a825b940c74 100644 --- a/tests/language/regress/regress33479_test.dart +++ b/tests/language/regress/regress33479_test.dart @@ -1,13 +1,17 @@ class Hest {} +// ^^^^ +// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND // ^ // [cfe] Type variables can't have generic function types in their bounds. typedef Fisk = void Function // don't merge lines -// [error line 5, column 1, length 346] +// [error line 7, column 1, length 346] // [analyzer] COMPILE_TIME_ERROR.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF // ^ // [cfe] Generic type 'Fisk' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest'. (); +// ^^^^ +// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND main() { Hest hest = new Hest(); diff --git a/tests/language_2/regress/regress33479_test.dart b/tests/language_2/regress/regress33479_test.dart index 568b6f80b0a..a825b940c74 100644 --- a/tests/language_2/regress/regress33479_test.dart +++ b/tests/language_2/regress/regress33479_test.dart @@ -1,13 +1,17 @@ class Hest {} +// ^^^^ +// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND // ^ // [cfe] Type variables can't have generic function types in their bounds. typedef Fisk = void Function // don't merge lines -// [error line 5, column 1, length 346] +// [error line 7, column 1, length 346] // [analyzer] COMPILE_TIME_ERROR.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF // ^ // [cfe] Generic type 'Fisk' can't be used without type arguments in the bounds of its own type variables. It is referenced indirectly through 'Hest'. (); +// ^^^^ +// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND main() { Hest hest = new Hest();