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 <srawlins@google.com>
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-03-27 21:08:06 +00:00 committed by commit-bot@chromium.org
parent 0e8bc12b51
commit 2c02737d7a
6 changed files with 55 additions and 2 deletions

View file

@ -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(

View file

@ -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<SimplyBoundedNode> {
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);
}
}
}
}

View file

@ -102,6 +102,14 @@ class A<T extends void Function(A)> {}
]);
}
test_class_recursion_notInstantiated_genericFunctionType2() async {
await assertErrorsInCode(r'''
class A<T extends void Function<U extends A>()> {}
''', [
error(CompileTimeErrorCode.NOT_INSTANTIATED_BOUND, 42, 1),
]);
}
test_class_recursion_typedef_notInstantiated() async {
await assertErrorsInCode(r'''
typedef F(C value);

View file

@ -1778,6 +1778,20 @@ notSimplyBounded class A<covariant T extends void Function(A<dynamic>)> {
withTypeParameterVariance: true);
}
test_class_typeParameters_defaultType_cycle_genericFunctionType2() async {
featureSet = FeatureSets.genericMetadata;
var library = await checkLibrary(r'''
class C<T extends void Function<U extends C>()> {}
''');
checkElementText(
library,
r'''
notSimplyBounded class C<covariant T extends void Function<U extends C<dynamic>>()> {
}
''',
withTypeParameterVariance: true);
}
test_class_typeParameters_defaultType_functionTypeAlias_contravariant_legacy() async {
featureSet = FeatureSets.beforeNullSafe;
var library = await checkLibrary(r'''

View file

@ -1,13 +1,17 @@
class Hest<TypeX extends Fisk> {}
// ^^^^
// [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'.
<TypeY extends Hest>();
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
main() {
Hest hest = new Hest();

View file

@ -1,13 +1,17 @@
class Hest<TypeX extends Fisk> {}
// ^^^^
// [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'.
<TypeY extends Hest>();
// ^^^^
// [analyzer] COMPILE_TIME_ERROR.NOT_INSTANTIATED_BOUND
main() {
Hest hest = new Hest();