Skip to content

Commit 39e4804

Browse files
chloestefantsovaCommit Queue
authored and
Commit Queue
committed
Revert "[cfe] Check type variable dependency cycles via extension types"
This reverts commit 9bb61c0. Reason for revert: NPE detected in google3. Original change's description: > [cfe] Check type variable dependency cycles via extension types > > Closes #54097 > Closes #54164 > Part of #49731 > > Change-Id: I73aac5f7e2c7f05fd0872b37e6f39fa7b5ed4862 > Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/337183 > Commit-Queue: Chloe Stefantsova <[email protected]> > Reviewed-by: Johnni Winther <[email protected]> Change-Id: If1e102112546e333f2e7058e432af142ce7da56e No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/341922 Bot-Commit: Rubber Stamper <[email protected]> Reviewed-by: Johnni Winther <[email protected]> Commit-Queue: Johnni Winther <[email protected]> Auto-Submit: Chloe Stefantsova <[email protected]>
1 parent 8ca0aa2 commit 39e4804

File tree

64 files changed

+302
-4075
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+302
-4075
lines changed

pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2214,7 +2214,7 @@ const Template<Message Function(String name, String string)>
22142214
problemMessageTemplate:
22152215
r"""Type '#name' is a bound of itself via '#string'.""",
22162216
correctionMessageTemplate:
2217-
r"""Try breaking the cycle by removing at least one of the 'extends' clauses in the cycle.""",
2217+
r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
22182218
withArguments: _withArgumentsCycleInTypeVariables);
22192219

22202220
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2233,7 +2233,7 @@ Message _withArgumentsCycleInTypeVariables(String name, String string) {
22332233
problemMessage:
22342234
"""Type '${name}' is a bound of itself via '${string}'.""",
22352235
correctionMessage:
2236-
"""Try breaking the cycle by removing at least one of the 'extends' clauses in the cycle.""",
2236+
"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
22372237
arguments: {'name': name, 'string': string});
22382238
}
22392239

@@ -2555,7 +2555,7 @@ const Template<
25552555
Message Function(String name)>("DirectCycleInTypeVariables",
25562556
problemMessageTemplate: r"""Type '#name' can't use itself as a bound.""",
25572557
correctionMessageTemplate:
2558-
r"""Try breaking the cycle by removing at least one of the 'extends' clauses in the cycle.""",
2558+
r"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
25592559
withArguments: _withArgumentsDirectCycleInTypeVariables);
25602560

25612561
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -2570,7 +2570,7 @@ Message _withArgumentsDirectCycleInTypeVariables(String name) {
25702570
return new Message(codeDirectCycleInTypeVariables,
25712571
problemMessage: """Type '${name}' can't use itself as a bound.""",
25722572
correctionMessage:
2573-
"""Try breaking the cycle by removing at least one of the 'extends' clauses in the cycle.""",
2573+
"""Try breaking the cycle by removing at least on of the 'extends' clauses in the cycle.""",
25742574
arguments: {'name': name});
25752575
}
25762576

pkg/front_end/lib/src/fasta/builder/type_variable_builder.dart

Lines changed: 10 additions & 142 deletions
Original file line numberDiff line numberDiff line change
@@ -83,98 +83,6 @@ sealed class TypeVariableBuilderBase extends TypeDeclarationBuilderImpl
8383

8484
void finish(SourceLibraryBuilder library, ClassBuilder object,
8585
TypeBuilder dynamicType);
86-
87-
TypeBuilder? _unaliasAndErase(TypeBuilder? typeBuilder) {
88-
if (typeBuilder is! NamedTypeBuilder) {
89-
return typeBuilder;
90-
} else {
91-
TypeDeclarationBuilder? declaration = typeBuilder.declaration;
92-
if (declaration is TypeAliasBuilder) {
93-
// We pass empty lists as [unboundTypes] and [unboundTypeVariables]
94-
// because new builders can be generated during unaliasing. We ignore
95-
// the returned builders, however, because they will not be used in the
96-
// output and are needed only for the checks.
97-
//
98-
// We also don't instantiate-to-bound raw types because it won't affect
99-
// the dependency cycle analysis.
100-
return _unaliasAndErase(declaration.unalias(typeBuilder.typeArguments,
101-
unboundTypes: [], unboundTypeVariables: []));
102-
} else if (declaration is ExtensionTypeDeclarationBuilder) {
103-
TypeBuilder? representationType =
104-
declaration.declaredRepresentationTypeBuilder;
105-
if (representationType == null) {
106-
return null;
107-
} else {
108-
List<NominalVariableBuilder>? typeParameters =
109-
declaration.typeParameters;
110-
List<TypeBuilder>? typeArguments = typeBuilder.typeArguments;
111-
if (typeParameters != null && typeArguments != null) {
112-
representationType = representationType.subst(
113-
new Map<NominalVariableBuilder, TypeBuilder>.fromIterables(
114-
typeParameters, typeArguments));
115-
}
116-
return _unaliasAndErase(representationType);
117-
}
118-
} else {
119-
return typeBuilder;
120-
}
121-
}
122-
}
123-
124-
TypeVariableCyclicDependency? findCyclicDependency(
125-
{Map<TypeVariableBuilderBase, TypeVariableTraversalState>?
126-
typeVariablesTraversalState,
127-
Map<TypeVariableBuilderBase, TypeVariableBuilderBase>? cycleElements}) {
128-
typeVariablesTraversalState ??= {};
129-
cycleElements ??= {};
130-
131-
switch (typeVariablesTraversalState[this] ??=
132-
TypeVariableTraversalState.unvisited) {
133-
case TypeVariableTraversalState.visited:
134-
return null;
135-
case TypeVariableTraversalState.active:
136-
typeVariablesTraversalState[this] = TypeVariableTraversalState.visited;
137-
List<TypeVariableBuilderBase>? viaTypeVariables;
138-
TypeVariableBuilderBase? nextViaTypeVariable = cycleElements[this];
139-
while (nextViaTypeVariable != null && nextViaTypeVariable != this) {
140-
(viaTypeVariables ??= []).add(nextViaTypeVariable);
141-
nextViaTypeVariable = cycleElements[nextViaTypeVariable];
142-
}
143-
return new TypeVariableCyclicDependency(this,
144-
viaTypeVariables: viaTypeVariables);
145-
case TypeVariableTraversalState.unvisited:
146-
typeVariablesTraversalState[this] = TypeVariableTraversalState.active;
147-
TypeBuilder? bound = this.bound;
148-
if (bound is NamedTypeBuilder) {
149-
TypeBuilder? unaliasedAndErasedBound = _unaliasAndErase(bound);
150-
TypeDeclarationBuilder? unaliasedAndErasedBoundDeclaration =
151-
unaliasedAndErasedBound?.declaration;
152-
TypeVariableBuilderBase? nextVariable;
153-
if (unaliasedAndErasedBoundDeclaration is TypeVariableBuilderBase) {
154-
nextVariable = unaliasedAndErasedBoundDeclaration;
155-
}
156-
157-
if (nextVariable != null) {
158-
cycleElements[this] = nextVariable;
159-
TypeVariableCyclicDependency? result =
160-
nextVariable.findCyclicDependency(
161-
typeVariablesTraversalState: typeVariablesTraversalState,
162-
cycleElements: cycleElements);
163-
typeVariablesTraversalState[this] =
164-
TypeVariableTraversalState.visited;
165-
return result;
166-
} else {
167-
typeVariablesTraversalState[this] =
168-
TypeVariableTraversalState.visited;
169-
return null;
170-
}
171-
} else {
172-
typeVariablesTraversalState[this] =
173-
TypeVariableTraversalState.visited;
174-
return null;
175-
}
176-
}
177-
}
17886
}
17987

18088
class NominalVariableBuilder extends TypeVariableBuilderBase {
@@ -402,17 +310,21 @@ class NominalVariableBuilder extends TypeVariableBuilderBase {
402310
}
403311
}
404312

405-
List<TypeVariableBuilderBase> sortAllTypeVariablesTopologically(
406-
Iterable<TypeVariableBuilderBase> typeVariables) {
313+
List< /* TypeVariableBuilder | FunctionTypeTypeVariableBuilder */ Object>
314+
sortAllTypeVariablesTopologically(
315+
Iterable< /* TypeVariableBuilder | FunctionTypeTypeVariableBuilder */
316+
Object>
317+
typeVariables) {
407318
assert(typeVariables.every((typeVariable) =>
408319
typeVariable is NominalVariableBuilder ||
409320
typeVariable is StructuralVariableBuilder));
410321

411-
Set<TypeVariableBuilderBase> unhandled =
412-
new Set<TypeVariableBuilderBase>.identity()..addAll(typeVariables);
413-
List<TypeVariableBuilderBase> result = <TypeVariableBuilderBase>[];
322+
Set< /* TypeVariableBuilder | FunctionTypeTypeVariableBuilder */ Object>
323+
unhandled = new Set<Object>.identity()..addAll(typeVariables);
324+
List< /* TypeVariableBuilder | FunctionTypeTypeVariableBuilder */ Object>
325+
result = <Object>[];
414326
while (unhandled.isNotEmpty) {
415-
TypeVariableBuilderBase rootVariable = unhandled.first;
327+
Object rootVariable = unhandled.first;
416328
unhandled.remove(rootVariable);
417329

418330
TypeBuilder? rootVariableBound;
@@ -772,47 +684,3 @@ class FreshStructuralVariableBuildersFromNominalVariableBuilders {
772684
FreshStructuralVariableBuildersFromNominalVariableBuilders(
773685
this.freshStructuralVariableBuilders, this.substitutionMap);
774686
}
775-
776-
/// This enum is used internally for dependency analysis of type variables.
777-
enum TypeVariableTraversalState {
778-
/// An [unvisited] type variable isn't yet visited by the traversal algorithm.
779-
unvisited,
780-
781-
/// An [active] type variable is traversed, but not fully processed.
782-
active,
783-
784-
/// A [visited] type variable is fully processed.
785-
visited;
786-
}
787-
788-
/// Represents a cyclic dependency of a type variable on itself.
789-
///
790-
/// An examples of such dependencies are X in the following cases.
791-
///
792-
/// typedef F<Y> = Y;
793-
/// extension type E<Y>(Y it) {}
794-
///
795-
/// class A<X extends X> {} // Error.
796-
/// class B<X extends Y, Y extends X> {} // Error.
797-
/// class C<X extends F<Y>, Y extends X> {} // Error.
798-
/// class D<X extends E<Y>, Y extends X> {} // Error.
799-
class TypeVariableCyclicDependency {
800-
/// Type variable that's the bound of itself.
801-
final TypeVariableBuilderBase typeVariableBoundOfItself;
802-
803-
/// The elements in a non-trivial self-dependency cycle.
804-
///
805-
/// The loop is considered non-trivial if it includes more than one type
806-
/// variable.
807-
final List<TypeVariableBuilderBase>? viaTypeVariables;
808-
809-
TypeVariableCyclicDependency(this.typeVariableBoundOfItself,
810-
{this.viaTypeVariables});
811-
812-
@override
813-
String toString() {
814-
return "TypeVariableCyclicDependency("
815-
"typeVariableBoundOfItself=${typeVariableBoundOfItself}, "
816-
"viaTypeVariable=${viaTypeVariables})";
817-
}
818-
}

pkg/front_end/lib/src/fasta/kernel/body_builder.dart

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8786,7 +8786,6 @@ class BodyBuilder extends StackListenerImpl
87868786
// Peek to leave type parameters on top of stack.
87878787
List<TypeVariableBuilderBase> typeVariables =
87888788
peek() as List<TypeVariableBuilderBase>;
8789-
libraryBuilder.checkTypeVariableDependencies(typeVariables);
87908789

87918790
List<TypeBuilder> unboundTypes = [];
87928791
List<StructuralVariableBuilder> unboundTypeVariables = [];

pkg/front_end/lib/src/fasta/source/outline_builder.dart

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3643,6 +3643,70 @@ class OutlineBuilder extends StackListenerImpl {
36433643
libraryFeatures.enhancedEnums, beginToken.charOffset, noLength);
36443644
}
36453645

3646+
// Peek to leave type parameters on top of stack.
3647+
List<TypeVariableBuilderBase>? typeParameters =
3648+
peek() as List<TypeVariableBuilderBase>?;
3649+
3650+
Map<String, TypeVariableBuilderBase>? typeVariablesByName;
3651+
if (typeParameters != null) {
3652+
for (TypeVariableBuilderBase builder in typeParameters) {
3653+
if (builder.bound != null) {
3654+
typeVariablesByName ??= <String, TypeVariableBuilderBase>{
3655+
for (TypeVariableBuilderBase builder in typeParameters)
3656+
builder.name: builder
3657+
};
3658+
3659+
// Find cycle: If there's no cycle we can at most step through all
3660+
// `typeParameters` (at which point the last builders bound will be
3661+
// null).
3662+
// If there is a cycle with `builder` 'inside' the steps to get back
3663+
// to it will also be bound by `typeParameters.length`.
3664+
// If there is a cycle without `builder` 'inside' we will just ignore
3665+
// it for now. It will be reported when processing one of the
3666+
// `builder`s that is in fact `inside` the cycle. This matches the
3667+
// cyclic class hierarchy error.
3668+
TypeVariableBuilderBase? bound = builder;
3669+
for (int steps = 0;
3670+
bound!.bound != null && steps < typeParameters.length;
3671+
++steps) {
3672+
TypeName? typeName = bound.bound!.typeName;
3673+
bound = typeVariablesByName[typeName?.name];
3674+
if (bound == null || bound == builder) break;
3675+
}
3676+
if (bound == builder && bound!.bound != null) {
3677+
// Write out cycle.
3678+
List<String> via = <String>[];
3679+
TypeName? typeName = bound.bound!.typeName;
3680+
bound = typeVariablesByName[typeName?.name];
3681+
while (bound != builder) {
3682+
via.add(bound!.name);
3683+
TypeName? typeName = bound.bound!.typeName;
3684+
bound = typeVariablesByName[typeName?.name];
3685+
}
3686+
Message message = via.isEmpty
3687+
? templateDirectCycleInTypeVariables.withArguments(builder.name)
3688+
: templateCycleInTypeVariables.withArguments(
3689+
builder.name, via.join("', '"));
3690+
addProblem(message, builder.charOffset, builder.name.length);
3691+
builder.bound = new NamedTypeBuilderImpl(
3692+
new SyntheticTypeName(builder.name, builder.charOffset),
3693+
const NullabilityBuilder.omitted(),
3694+
fileUri: uri,
3695+
charOffset: builder.charOffset,
3696+
instanceTypeVariableAccess:
3697+
//InstanceTypeVariableAccessState.Unexpected
3698+
declarationContext.instanceTypeVariableAccessState)
3699+
..bind(
3700+
libraryBuilder,
3701+
new InvalidTypeDeclarationBuilder(
3702+
builder.name,
3703+
message.withLocation(
3704+
uri, builder.charOffset, builder.name.length)));
3705+
}
3706+
}
3707+
}
3708+
}
3709+
36463710
if (inConstructorName) {
36473711
addProblem(messageConstructorWithTypeParameters,
36483712
offsetForToken(beginToken), lengthOfSpan(beginToken, endToken));

0 commit comments

Comments
 (0)