Sort classes topologically when checking for cycles

Change-Id: I4d2fd8a1d3f2d369e69ed93665ce43ca4747b02d
Reviewed-on: https://dart-review.googlesource.com/c/86204
Reviewed-by: Dmitry Stefantsov <dmitryas@google.com>
This commit is contained in:
Peter von der Ahé 2018-12-17 14:33:49 +00:00 committed by commit-bot@chromium.org
parent 77889c10e3
commit 6ec321f2b7
20 changed files with 218 additions and 292 deletions

View file

@ -57,9 +57,6 @@ class DillTarget extends TargetImplementation {
return new DillLibraryBuilder(uri, loader);
}
@override
void addDirectSupertype(ClassBuilder cls, Set<ClassBuilder> set) {}
@override
void breakCycle(ClassBuilder cls) {}
}

View file

@ -1754,27 +1754,24 @@ Message _withArgumentsCycleInTypeVariables(String name, String string) {
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name, String string)>
templateCyclicClassHierarchy =
const Template<Message Function(String name, String string)>(
messageTemplate: r"""'#name' is a supertype of itself via '#string'.""",
const Template<Message Function(String name)> templateCyclicClassHierarchy =
const Template<Message Function(String name)>(
messageTemplate: r"""'#name' is a supertype of itself.""",
withArguments: _withArgumentsCyclicClassHierarchy);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name, String string)>
codeCyclicClassHierarchy =
const Code<Message Function(String name, String string)>(
const Code<Message Function(String name)> codeCyclicClassHierarchy =
const Code<Message Function(String name)>(
"CyclicClassHierarchy", templateCyclicClassHierarchy,
analyzerCodes: <String>["RECURSIVE_INTERFACE_INHERITANCE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsCyclicClassHierarchy(String name, String string) {
Message _withArgumentsCyclicClassHierarchy(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
if (string.isEmpty) throw 'No string provided';
return new Message(codeCyclicClassHierarchy,
message: """'${name}' is a supertype of itself via '${string}'.""",
arguments: {'name': name, 'string': string});
message: """'${name}' is a supertype of itself.""",
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@ -2043,28 +2040,6 @@ Message _withArgumentsDirectCycleInTypeVariables(String name) {
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Template<Message Function(String name)>
templateDirectCyclicClassHierarchy =
const Template<Message Function(String name)>(
messageTemplate: r"""'#name' can't use itself as a supertype.""",
withArguments: _withArgumentsDirectCyclicClassHierarchy);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Message Function(String name)> codeDirectCyclicClassHierarchy =
const Code<Message Function(String name)>(
"DirectCyclicClassHierarchy", templateDirectCyclicClassHierarchy,
analyzerCodes: <String>["RECURSIVE_INTERFACE_INHERITANCE"]);
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
Message _withArgumentsDirectCyclicClassHierarchy(String name) {
if (name.isEmpty) throw 'No name provided';
name = demangleMixinApplicationName(name);
return new Message(codeDirectCyclicClassHierarchy,
message: """'${name}' can't use itself as a supertype.""",
arguments: {'name': name});
}
// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
const Code<Null> codeDirectiveAfterDeclaration =
messageDirectiveAfterDeclaration;

View file

@ -197,37 +197,6 @@ class KernelTarget extends TargetImplementation {
return new KernelLibraryBuilder(uri, fileUri, loader, origin);
}
void forEachDirectSupertype(ClassBuilder cls, void f(NamedTypeBuilder type)) {
TypeBuilder supertype = cls.supertype;
if (supertype is NamedTypeBuilder) {
f(supertype);
} else if (supertype != null) {
unhandled("${supertype.runtimeType}", "forEachDirectSupertype",
cls.charOffset, cls.fileUri);
}
if (cls.interfaces != null) {
for (NamedTypeBuilder t in cls.interfaces) {
f(t);
}
}
if (cls.library.loader == loader &&
// TODO(ahe): Implement DillClassBuilder.mixedInType and remove the
// above check.
cls.mixedInType != null) {
f(cls.mixedInType);
}
}
void addDirectSupertype(ClassBuilder cls, Set<ClassBuilder> set) {
if (cls == null) return;
forEachDirectSupertype(cls, (NamedTypeBuilder type) {
Declaration declaration = type.declaration;
if (declaration is ClassBuilder) {
set.add(declaration);
}
});
}
/// Returns classes defined in libraries in [loader].
List<SourceClassBuilder> collectMyClasses() {
List<SourceClassBuilder> result = <SourceClassBuilder>[];
@ -270,8 +239,8 @@ class KernelTarget extends TargetImplementation {
bottomType.bind(loader.coreLibrary["Null"]);
loader.resolveTypes();
loader.computeDefaultTypes(dynamicType, bottomType, objectClassBuilder);
List<SourceClassBuilder> myClasses = collectMyClasses();
loader.checkSemantics(myClasses, objectClassBuilder);
List<SourceClassBuilder> myClasses =
loader.checkSemantics(objectClassBuilder);
loader.finishTypeVariables(objectClassBuilder, dynamicType);
loader.buildComponent();
installDefaultSupertypes();
@ -412,7 +381,7 @@ class KernelTarget extends TargetImplementation {
void installSyntheticConstructors(List<SourceClassBuilder> builders) {
Class objectClass = this.objectClass;
for (SourceClassBuilder builder in builders) {
if (builder.target != objectClass) {
if (builder.target != objectClass && !builder.isPatch) {
if (builder.isPatch || builder.isMixinDeclaration) continue;
if (builder.isMixinApplication) {
installForwardingConstructors(builder);

View file

@ -24,12 +24,14 @@ import '../fasta_codes.dart'
import '../kernel/kernel_builder.dart'
show
ClassBuilder,
ConstructorReferenceBuilder,
Declaration,
KernelClassBuilder,
KernelFieldBuilder,
KernelFunctionBuilder,
KernelLibraryBuilder,
KernelNamedTypeBuilder,
KernelTypeBuilder,
KernelTypeVariableBuilder,
LibraryBuilder,
@ -69,7 +71,8 @@ ShadowClass initializeClass(
return cls;
}
class SourceClassBuilder extends KernelClassBuilder {
class SourceClassBuilder extends KernelClassBuilder
implements Comparable<SourceClassBuilder> {
@override
final Class actualCls;
@ -247,7 +250,9 @@ class SourceClassBuilder extends KernelClassBuilder {
declaration.prepareTopLevelInference();
}
});
cls.setupApiMembers(library.loader.interfaceResolver);
if (!isPatch) {
cls.setupApiMembers(library.loader.interfaceResolver);
}
}
@override
@ -274,4 +279,33 @@ class SourceClassBuilder extends KernelClassBuilder {
});
return count;
}
List<Declaration> computeDirectSupertypes(ClassBuilder objectClass) {
final List<Declaration> result = <Declaration>[];
final KernelNamedTypeBuilder supertype = this.supertype;
if (supertype != null) {
result.add(supertype.declaration);
} else if (objectClass != this) {
result.add(objectClass);
}
final List<KernelTypeBuilder> interfaces = this.interfaces;
if (interfaces != null) {
for (int i = 0; i < interfaces.length; i++) {
KernelNamedTypeBuilder interface = interfaces[i];
result.add(interface.declaration);
}
}
final KernelNamedTypeBuilder mixedInType = this.mixedInType;
if (mixedInType != null) {
result.add(mixedInType.declaration);
}
return result;
}
@override
int compareTo(SourceClassBuilder other) {
int result = "$fileUri".compareTo("${other.fileUri}");
if (result != 0) return result;
return charOffset.compareTo(other.charOffset);
}
}

View file

@ -66,7 +66,6 @@ import '../fasta_codes.dart'
templateIllegalMixinDueToConstructorsCause,
templateInternalProblemUriMissingScheme,
templateSourceOutlineSummary,
templateDirectCyclicClassHierarchy,
templateUntranslatableUri;
import '../fasta_codes.dart' as fasta_codes;
@ -95,7 +94,7 @@ import '../parser/class_member_parser.dart' show ClassMemberParser;
import '../parser.dart' show Parser, lengthForToken, offsetForToken;
import '../problems.dart' show internalProblem, unexpected, unhandled;
import '../problems.dart' show internalProblem, unhandled;
import '../scanner.dart' show ErrorToken, ScannerResult, Token, scan;
@ -142,8 +141,6 @@ class SourceLoader<L> extends Loader<L> {
Instrumentation instrumentation;
List<ClassBuilder> orderedClasses;
SourceLoader(this.fileSystem, this.includeComments, KernelTarget target)
: super(target);
@ -504,57 +501,6 @@ class SourceLoader<L> extends Loader<L> {
ticker.logMs("Finished $count patch methods");
}
/// Returns all the supertypes (including interfaces) of [cls]
/// transitively. Includes [cls].
Set<ClassBuilder> allSupertypes(ClassBuilder cls) {
int length = 0;
Set<ClassBuilder> result = new Set<ClassBuilder>()..add(cls);
while (length != result.length) {
length = result.length;
result.addAll(directSupertypes(result));
}
return result;
}
/// Returns the direct supertypes (including interface) of [classes]. A class
/// from [classes] is only included if it is a supertype of one of the other
/// classes in [classes].
Set<ClassBuilder> directSupertypes(Iterable<ClassBuilder> classes) {
Set<ClassBuilder> result = new Set<ClassBuilder>();
for (ClassBuilder cls in classes) {
target.addDirectSupertype(cls, result);
}
return result;
}
/// Computes a set of classes that may have cycles. The set is empty if there
/// are no cycles. If the set isn't empty, it will include supertypes of
/// classes with cycles, as well as the classes with cycles.
///
/// It is assumed that [classes] is a transitive closure with respect to
/// supertypes.
Iterable<ClassBuilder> cyclicCandidates(Iterable<ClassBuilder> classes) {
// The candidates are found by a fixed-point computation.
//
// On each iteration, the classes that have no supertypes in the input set
// will be removed.
//
// If there are no cycles, eventually, the set will converge on Object, and
// the next iteration will make the set empty (as Object has no
// supertypes).
//
// On the other hand, if there is a cycle, the cycle will remain in the
// set, and so will its supertypes, and eventually the input and output set
// will have the same length.
Iterable<ClassBuilder> input = const [];
Iterable<ClassBuilder> output = classes;
while (input.length != output.length) {
input = output;
output = directSupertypes(input);
}
return output;
}
/// Check that [objectClass] has no supertypes. Recover by removing any
/// found.
void checkObjectClassHierarchy(ClassBuilder objectClass) {
@ -578,111 +524,141 @@ class SourceLoader<L> extends Loader<L> {
}
}
void checkSemantics(
List<SourceClassBuilder> classes, ClassBuilder objectClass) {
checkObjectClassHierarchy(objectClass);
Iterable<ClassBuilder> candidates = cyclicCandidates(classes);
if (candidates.isNotEmpty) {
Map<ClassBuilder, Set<ClassBuilder>> realCycles =
<ClassBuilder, Set<ClassBuilder>>{};
for (ClassBuilder cls in candidates) {
Set<ClassBuilder> cycles = cyclicCandidates(allSupertypes(cls));
if (cycles.isNotEmpty) {
realCycles[cls] = cycles;
}
}
Map<LocatedMessage, ClassBuilder> messages =
<LocatedMessage, ClassBuilder>{};
realCycles.forEach((ClassBuilder cls, Set<ClassBuilder> cycles) {
target.breakCycle(cls);
List<ClassBuilder> involved = <ClassBuilder>[];
for (ClassBuilder cls in cycles) {
if (realCycles.containsKey(cls)) {
involved.add(cls);
/// Returns a list of all class builders declared in this loader. As the
/// classes are sorted, any cycles in the hiearchy are reported as
/// errors. Recover by breaking the cycles. This means that the rest of the
/// pipeline (including backends) can assume that there are no hierarchy
/// cycles.
List<SourceClassBuilder> handleHierarchyCycles(ClassBuilder objectClass) {
// Compute the initial work list of all classes declared in this loader.
List<SourceClassBuilder> workList = <SourceClassBuilder>[];
for (LibraryBuilder library in builders.values) {
if (library.loader == this) {
Iterator<Declaration> members = library.iterator;
while (members.moveNext()) {
Declaration member = members.current;
if (member is SourceClassBuilder) {
workList.add(member);
}
}
// Sort the class names alphabetically to ensure the order is stable.
// TODO(ahe): It's possible that a better UX would be to sort the
// classes based on walking the class hierarchy in breadth-first order.
String involvedString = (involved
.where((c) => c != cls)
.map((c) => c.fullNameForErrors)
.toList()
..sort())
.join("', '");
LocatedMessage message = involvedString.isEmpty
? templateDirectCyclicClassHierarchy
.withArguments(cls.fullNameForErrors)
.withLocation(cls.fileUri, cls.charOffset, noLength)
: templateCyclicClassHierarchy
.withArguments(cls.fullNameForErrors, involvedString)
.withLocation(cls.fileUri, cls.charOffset, noLength);
messages[message] = cls;
});
// Report all classes involved in a cycle, sorted to ensure stability as
// [cyclicCandidates] is sensitive to if the platform (or other modules)
// are included in [classes].
for (LocatedMessage message in messages.keys.toList()..sort()) {
messages[message].addProblem(
message.messageObject, message.charOffset, message.length);
}
}
ticker.logMs("Found cycles");
Set<ClassBuilder> blackListedClasses = new Set<ClassBuilder>();
for (int i = 0; i < blacklistedCoreClasses.length; i++) {
blackListedClasses.add(coreLibrary[blacklistedCoreClasses[i]]);
}
for (ClassBuilder cls in classes) {
if (cls.library.loader != this) continue;
Set<ClassBuilder> directSupertypes = new Set<ClassBuilder>();
target.addDirectSupertype(cls, directSupertypes);
for (ClassBuilder supertype in directSupertypes) {
if (supertype is EnumBuilder) {
cls.addProblem(templateExtendingEnum.withArguments(supertype.name),
cls.charOffset, noLength);
} else if (!cls.library.mayImplementRestrictedTypes &&
blackListedClasses.contains(supertype)) {
cls.addProblem(
templateExtendingRestricted.withArguments(supertype.name),
cls.charOffset,
noLength);
// Sort the classes topologically.
Set<SourceClassBuilder> topologicallySortedClasses =
new Set<SourceClassBuilder>();
List<SourceClassBuilder> previousWorkList;
do {
previousWorkList = workList;
workList = <SourceClassBuilder>[];
for (int i = 0; i < previousWorkList.length; i++) {
SourceClassBuilder cls = previousWorkList[i];
List<Declaration> directSupertypes =
cls.computeDirectSupertypes(objectClass);
bool allSupertypesProcessed = true;
for (int i = 0; i < directSupertypes.length; i++) {
Declaration supertype = directSupertypes[i];
if (supertype is SourceClassBuilder &&
supertype.library.loader == this &&
!topologicallySortedClasses.contains(supertype)) {
allSupertypesProcessed = false;
break;
}
}
if (allSupertypesProcessed) {
topologicallySortedClasses.add(cls);
checkClassSupertypes(cls, directSupertypes, blackListedClasses);
} else {
workList.add(cls);
}
}
TypeBuilder mixedInType = cls.mixedInType;
if (mixedInType != null) {
bool isClassBuilder = false;
if (mixedInType is NamedTypeBuilder) {
var builder = mixedInType.declaration;
if (builder is ClassBuilder) {
isClassBuilder = true;
for (Declaration constructory
in builder.constructors.local.values) {
if (constructory.isConstructor && !constructory.isSynthetic) {
cls.addProblem(
templateIllegalMixinDueToConstructors
.withArguments(builder.fullNameForErrors),
cls.charOffset,
noLength,
context: [
templateIllegalMixinDueToConstructorsCause
.withArguments(builder.fullNameForErrors)
.withLocation(constructory.fileUri,
constructory.charOffset, noLength)
]);
}
} while (previousWorkList.length != workList.length);
List<SourceClassBuilder> classes = topologicallySortedClasses.toList();
List<SourceClassBuilder> classesWithCycles = previousWorkList;
// Once the work list doesn't change in size, it's either empty, or
// contains all classes with cycles.
// Sort the classes to ensure consistent output.
classesWithCycles.sort();
for (int i = 0; i < classesWithCycles.length; i++) {
SourceClassBuilder cls = classesWithCycles[i];
target.breakCycle(cls);
classes.add(cls);
cls.addProblem(
templateCyclicClassHierarchy.withArguments(cls.fullNameForErrors),
cls.charOffset,
noLength);
}
ticker.logMs("Checked class hierarchy");
return classes;
}
void checkClassSupertypes(
SourceClassBuilder cls,
List<Declaration> directSupertypes,
Set<ClassBuilder> blackListedClasses) {
// Check that the direct supertypes aren't black-listed or enums.
for (int i = 0; i < directSupertypes.length; i++) {
Declaration supertype = directSupertypes[i];
if (supertype is EnumBuilder) {
cls.addProblem(templateExtendingEnum.withArguments(supertype.name),
cls.charOffset, noLength);
} else if (!cls.library.mayImplementRestrictedTypes &&
blackListedClasses.contains(supertype)) {
cls.addProblem(
templateExtendingRestricted
.withArguments(supertype.fullNameForErrors),
cls.charOffset,
noLength);
}
}
// Check that the mixed-in type can be used as a mixin.
final TypeBuilder mixedInType = cls.mixedInType;
if (mixedInType != null) {
bool isClassBuilder = false;
if (mixedInType is NamedTypeBuilder) {
var builder = mixedInType.declaration;
if (builder is ClassBuilder) {
isClassBuilder = true;
for (Declaration constructory in builder.constructors.local.values) {
if (constructory.isConstructor && !constructory.isSynthetic) {
cls.addProblem(
templateIllegalMixinDueToConstructors
.withArguments(builder.fullNameForErrors),
cls.charOffset,
noLength,
context: [
templateIllegalMixinDueToConstructorsCause
.withArguments(builder.fullNameForErrors)
.withLocation(constructory.fileUri,
constructory.charOffset, noLength)
]);
}
}
}
if (!isClassBuilder) {
cls.addProblem(
templateIllegalMixin.withArguments(mixedInType.fullNameForErrors),
cls.charOffset,
noLength);
}
}
if (!isClassBuilder) {
// TODO(ahe): Either we need to check this for superclass and
// interfaces, or this shouldn't be necessary (or handled elsewhere).
cls.addProblem(
templateIllegalMixin.withArguments(mixedInType.fullNameForErrors),
cls.charOffset,
noLength);
}
}
ticker.logMs("Checked restricted supertypes");
}
List<SourceClassBuilder> checkSemantics(ClassBuilder objectClass) {
checkObjectClassHierarchy(objectClass);
List<SourceClassBuilder> classes = handleHierarchyCycles(objectClass);
// Check imports and exports for duplicate names.
// This is rather silly, e.g. it makes importing 'foo' and exporting another
@ -757,6 +733,7 @@ class SourceLoader<L> extends Loader<L> {
}
});
ticker.logMs("Checked imports and exports for duplicate names");
return classes;
}
void buildComponent() {
@ -847,7 +824,7 @@ class SourceLoader<L> extends Loader<L> {
void checkSupertypes(List<SourceClassBuilder> sourceClasses) {
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
builder.checkSupertypes(coreTypes);
}
}
@ -871,7 +848,7 @@ class SourceLoader<L> extends Loader<L> {
void checkOverrides(List<SourceClassBuilder> sourceClasses) {
assert(hierarchy != null);
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
builder.checkOverrides(
hierarchy, typeInferenceEngine?.typeSchemaEnvironment);
}
@ -883,7 +860,7 @@ class SourceLoader<L> extends Loader<L> {
if (target.legacyMode) return;
assert(hierarchy != null);
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
builder.checkAbstractMembers(
coreTypes, hierarchy, typeInferenceEngine.typeSchemaEnvironment);
}
@ -894,7 +871,7 @@ class SourceLoader<L> extends Loader<L> {
void checkRedirectingFactories(List<SourceClassBuilder> sourceClasses) {
if (target.legacyMode) return;
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
builder.checkRedirectingFactories(
typeInferenceEngine.typeSchemaEnvironment);
}
@ -907,7 +884,7 @@ class SourceLoader<L> extends Loader<L> {
List<Class> changedClasses = new List<Class>();
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
if (builder.addNoSuchMethodForwarders(target, hierarchy)) {
changedClasses.add(builder.target);
}
@ -919,7 +896,7 @@ class SourceLoader<L> extends Loader<L> {
void checkMixins(List<SourceClassBuilder> sourceClasses) {
for (SourceClassBuilder builder in sourceClasses) {
if (builder.library.loader == this) {
if (builder.library.loader == this && !builder.isPatch) {
if (builder.isMixinDeclaration) {
builder.checkMixinDeclaration();
}
@ -962,27 +939,8 @@ class SourceLoader<L> extends Loader<L> {
}
}
}
{
// Note: we need to create a list before iterating, since calling
// builder.prepareTopLevelInference causes further class hierarchy
// queries to be made which would otherwise result in a concurrent
// modification exception.
List<Class> classes = new List<Class>(sourceClasses.length);
for (int i = 0; i < sourceClasses.length; i++) {
classes[i] = sourceClasses[i].target;
}
orderedClasses = null;
List<ClassBuilder> result = new List<ClassBuilder>(sourceClasses.length);
int i = 0;
for (Class cls
in new List<Class>.from(hierarchy.getOrderedClasses(classes))) {
result[i++] = ShadowClass.getClassInferenceInfo(cls).builder
..prepareTopLevelInference();
}
if (i != result.length) {
unexpected("${result.length}", "$i", -1, null);
}
orderedClasses = result;
for (int i = 0; i < sourceClasses.length; i++) {
sourceClasses[i].prepareTopLevelInference();
}
typeInferenceEngine.isTypeInferencePrepared = true;
ticker.logMs("Prepared top level inference");
@ -992,7 +950,8 @@ class SourceLoader<L> extends Loader<L> {
/// their types.
typeInferenceEngine.finishTopLevelFields();
List<Class> changedClasses = new List<Class>();
for (var builder in orderedClasses) {
for (var builder in sourceClasses) {
if (builder.isPatch) continue;
ShadowClass class_ = builder.target;
int memberCount = class_.fields.length +
class_.constructors.length +
@ -1012,7 +971,6 @@ class SourceLoader<L> extends Loader<L> {
}
}
orderedClasses = null;
typeInferenceEngine.finishTopLevelInitializingFormals();
if (instrumentation != null) {
builders.forEach((Uri uri, LibraryBuilder library) {

View file

@ -46,9 +46,6 @@ abstract class TargetImplementation extends Target {
LibraryBuilder createLibraryBuilder(
Uri uri, Uri fileUri, covariant LibraryBuilder origin);
/// Add the classes extended or implemented directly by [cls] to [set].
void addDirectSupertype(ClassBuilder cls, Set<ClassBuilder> set);
/// The class [cls] is involved in a cyclic definition. This method should
/// ensure that the cycle is broken, for example, by removing superclass and
/// implemented interfaces.

View file

@ -1792,7 +1792,7 @@ DuplicatedImportInType:
main.dart: "import 'lib1.dart'; import 'lib2.dart'; A a;"
CyclicClassHierarchy:
template: "'#name' is a supertype of itself via '#string'."
template: "'#name' is a supertype of itself."
analyzerCode: RECURSIVE_INTERFACE_INHERITANCE
script:
- |
@ -1801,11 +1801,6 @@ CyclicClassHierarchy:
- |
class A implements B {}
class B implements A {}
DirectCyclicClassHierarchy:
template: "'#name' can't use itself as a supertype."
analyzerCode: RECURSIVE_INTERFACE_INHERITANCE
script:
- "class C = Object with C;"
- "class C extends C {}"
- "class C implements C {}"

View file

@ -1,28 +1,28 @@
// Formatted problems:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^
// Unhandled errors:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^

View file

@ -1,14 +1,14 @@
// Unhandled errors:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^

View file

@ -1,14 +1,14 @@
// Formatted problems:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^

View file

@ -1,28 +1,28 @@
// Formatted problems:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^
// Unhandled errors:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^

View file

@ -1,14 +1,14 @@
// Unhandled errors:
//
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself via 'B', 'C'.
// pkg/front_end/testcases/cycles.dart:5:7: Error: 'A' is a supertype of itself.
// class A implements C {}
// ^
//
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself via 'A', 'C'.
// pkg/front_end/testcases/cycles.dart:7:7: Error: 'B' is a supertype of itself.
// class B extends A {}
// ^
//
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself via 'A', 'B'.
// pkg/front_end/testcases/cycles.dart:9:7: Error: 'C' is a supertype of itself.
// class C extends B implements D {}
// ^

View file

@ -1,9 +1,8 @@
# Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
# for details. All rights reserved. Use of this source code is governed by a
# BSD-style license that can be found in the LICENSE.md file.
language_2/deferred_super_dependency_test: Crash # missing "#errors"
language_2/missing_part_of_tag_test: Crash # missing empty library that shouldn't have been there in the first place
language_2/regress_27957_test: Crash # isSynthetic becomes false on C1 SuperInitializer.
language_2/script1_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place
language_2/script2_negative_test: Crash # missing "#errors", missing empty library that shouldn't have been there in the first place

View file

@ -1,20 +1,20 @@
// Formatted problems:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^
// Unhandled errors:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^

View file

@ -1,10 +1,10 @@
// Unhandled errors:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^

View file

@ -1,10 +1,10 @@
// Formatted problems:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^

View file

@ -1,20 +1,20 @@
// Formatted problems:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^
// Unhandled errors:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^

View file

@ -1,10 +1,10 @@
// Unhandled errors:
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself via 'B'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:12:16: Error: 'A' is a supertype of itself.
// abstract class A extends B {
// ^
//
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself via 'A'.
// pkg/front_end/testcases/inference/circular_method_inference.dart:16:16: Error: 'B' is a supertype of itself.
// abstract class B extends A {
// ^

View file

@ -4,6 +4,7 @@ import "dart:core" as core;
class C = self::D with self::E {
synthetic constructor •() → self::C
: super self::D::•()
;
}
class D extends core::Object {

View file

@ -32,6 +32,7 @@ class Bad extends core::Object {
}
abstract class _WithMixin&Supertype&Mixin = lib::Supertype with lib::Mixin {
synthetic constructor •() → self::_WithMixin&Supertype&Mixin
: super lib::Supertype::•()
;
}
class WithMixin extends self::_WithMixin&Supertype&Mixin {