Skip to content

Commit 47ac03f

Browse files
scheglovcommit-bot@chromium.org
authored andcommitted
Break cycles in type parameters during linking.
Change-Id: Ibb31d2e1e4ea61451c6fff6c248938a7df333dea Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/155061 Reviewed-by: Brian Wilkerson <[email protected]> Commit-Queue: Konstantin Shcheglov <[email protected]>
1 parent baf740e commit 47ac03f

File tree

3 files changed

+86
-0
lines changed

3 files changed

+86
-0
lines changed

pkg/analyzer/lib/src/summary2/default_types_builder.dart

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,22 +19,27 @@ class DefaultTypesBuilder {
1919
for (var node in nodes) {
2020
if (node is ClassDeclaration) {
2121
var element = node.declaredElement;
22+
_breakSelfCycles(node.typeParameters);
2223
_breakRawTypeCycles(element, node.typeParameters);
2324
_computeBounds(element, node.typeParameters);
2425
} else if (node is ClassTypeAlias) {
2526
var element = node.declaredElement;
27+
_breakSelfCycles(node.typeParameters);
2628
_breakRawTypeCycles(element, node.typeParameters);
2729
_computeBounds(element, node.typeParameters);
2830
} else if (node is FunctionTypeAlias) {
2931
var element = node.declaredElement;
32+
_breakSelfCycles(node.typeParameters);
3033
_breakRawTypeCycles(element, node.typeParameters);
3134
_computeBounds(element, node.typeParameters);
3235
} else if (node is GenericTypeAlias) {
3336
var element = node.declaredElement;
37+
_breakSelfCycles(node.typeParameters);
3438
_breakRawTypeCycles(element, node.typeParameters);
3539
_computeBounds(element, node.typeParameters);
3640
} else if (node is MixinDeclaration) {
3741
var element = node.declaredElement;
42+
_breakSelfCycles(node.typeParameters);
3843
_breakRawTypeCycles(element, node.typeParameters);
3944
_computeBounds(element, node.typeParameters);
4045
}
@@ -86,6 +91,45 @@ class DefaultTypesBuilder {
8691
}
8792
}
8893

94+
void _breakSelfCycles(TypeParameterList parameterList) {
95+
if (parameterList == null) return;
96+
var typeParameters = parameterList.typeParameters;
97+
98+
Map<String, TypeParameter> typeParametersByName;
99+
for (var parameter in typeParameters) {
100+
var boundNode = parameter.bound;
101+
if (boundNode is TypeName) {
102+
if (typeParametersByName == null) {
103+
typeParametersByName = {};
104+
for (var parameterNode in typeParameters) {
105+
var name = parameterNode.name.name;
106+
typeParametersByName[name] = parameterNode;
107+
}
108+
}
109+
110+
var current = parameter;
111+
for (var step = 0;
112+
current != null && step < typeParameters.length;
113+
++step) {
114+
var bound = current.bound;
115+
if (bound is TypeName) {
116+
var typeNameIdentifier = bound.name;
117+
if (typeNameIdentifier is SimpleIdentifier) {
118+
current = typeParametersByName[typeNameIdentifier.name];
119+
continue;
120+
}
121+
}
122+
current = null;
123+
break;
124+
}
125+
126+
if (current != null) {
127+
boundNode.type = DynamicTypeImpl.instance;
128+
}
129+
}
130+
}
131+
}
132+
89133
/// Build actual default type [DartType]s from computed [TypeBuilder]s.
90134
void _build(TypeParameterList parameterList) {
91135
if (parameterList == null) return;

pkg/analyzer/test/src/diagnostics/type_parameter_supertype_of_its_bound_test.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ import 'package:analyzer/src/error/codes.dart';
66
import 'package:test_reflective_loader/test_reflective_loader.dart';
77

88
import '../dart/resolution/driver_resolution.dart';
9+
import '../dart/resolution/with_null_safety_mixin.dart';
910

1011
main() {
1112
defineReflectiveSuite(() {
1213
defineReflectiveTests(TypeParameterSupertypeOfItsBoundTest);
14+
defineReflectiveTests(TypeParameterSupertypeOfItsBoundWithNullSafetyTest);
1315
});
1416
}
1517

@@ -24,6 +26,18 @@ class A<T extends T> {
2426
]);
2527
}
2628

29+
test_1of1_used() async {
30+
await assertErrorsInCode('''
31+
class A<T extends T> {
32+
void foo(x) {
33+
x is T;
34+
}
35+
}
36+
''', [
37+
error(StaticTypeWarningCode.TYPE_PARAMETER_SUPERTYPE_OF_ITS_BOUND, 8, 11),
38+
]);
39+
}
40+
2741
test_2of3() async {
2842
await assertErrorsInCode(r'''
2943
class A<T1 extends T3, T2, T3 extends T1> {
@@ -35,3 +49,7 @@ class A<T1 extends T3, T2, T3 extends T1> {
3549
]);
3650
}
3751
}
52+
53+
@reflectiveTest
54+
class TypeParameterSupertypeOfItsBoundWithNullSafetyTest
55+
extends TypeParameterSupertypeOfItsBoundTest with WithNullSafetyMixin {}

pkg/analyzer/test/src/summary/resynthesize_common.dart

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1685,6 +1685,30 @@ class D {
16851685
''');
16861686
}
16871687

1688+
test_class_type_parameters_cycle_1of1() async {
1689+
var library = await checkLibrary('class C<T extends T> {}');
1690+
checkElementText(
1691+
library,
1692+
r'''
1693+
notSimplyBounded class C<T extends dynamic> {
1694+
}
1695+
''',
1696+
withTypes: true);
1697+
}
1698+
1699+
test_class_type_parameters_cycle_2of3() async {
1700+
var library = await checkLibrary(r'''
1701+
class C<T extends V, U, V extends T> {}
1702+
''');
1703+
checkElementText(
1704+
library,
1705+
r'''
1706+
notSimplyBounded class C<T extends dynamic, U, V extends dynamic> {
1707+
}
1708+
''',
1709+
withTypes: true);
1710+
}
1711+
16881712
test_class_type_parameters_f_bound_complex() async {
16891713
var library = await checkLibrary('class C<T extends List<U>, U> {}');
16901714
checkElementText(library, r'''

0 commit comments

Comments
 (0)