| Index: lib/compiler/implementation/dart_backend/backend.dart
|
| diff --git a/lib/compiler/implementation/dart_backend/backend.dart b/lib/compiler/implementation/dart_backend/backend.dart
|
| index f8436915f549084f126612d43627f88d6f351c85..4352390787bb9bde86a25422916f67704d6bf5e2 100644
|
| --- a/lib/compiler/implementation/dart_backend/backend.dart
|
| +++ b/lib/compiler/implementation/dart_backend/backend.dart
|
| @@ -89,6 +89,72 @@ class DartBackend extends Backend {
|
| Map<Element, TreeElements> get resolvedElements =>
|
| compiler.enqueuer.resolution.resolvedElements;
|
|
|
| + /**
|
| + * Tells whether it is safe to remove type declarations from variables,
|
| + * functions parameters. It becomes not safe if:
|
| + * 1) TypeError is used somewhere in the code,
|
| + * 2) The code has typedefs in right hand side of IS checks,
|
| + * 3) The code has classes which extend typedefs, have type arguments typedefs
|
| + * or type variable bounds typedefs.
|
| + * These restrictions can be less strict.
|
| + */
|
| + bool isSafeToRemoveTypeDeclarations(
|
| + Map<ClassElement, Set<Element>> classMembers) {
|
| + Set<DartType> processedTypes = new Set<DartType>();
|
| + List<DartType> workQueue = new List<DartType>();
|
| + workQueue.addAll(
|
| + classMembers.getKeys().map((classElement) => classElement.type));
|
| + workQueue.addAll(compiler.resolverWorld.isChecks);
|
| + DartType typeErrorType =
|
| + compiler.coreLibrary.find(new SourceString('TypeError')).type;
|
| + if (workQueue.indexOf(typeErrorType) != -1) {
|
| + return false;
|
| + }
|
| +
|
| + void processTypeArguments(Element classElement, NodeList typeArguments) {
|
| + if (typeArguments == null) return;
|
| + for (Node typeArgument in typeArguments.nodes) {
|
| + if (typeArgument is TypeVariable) {
|
| + typeArgument = typeArgument.bound;
|
| + }
|
| + if (typeArgument == null) continue;
|
| + assert(typeArgument is TypeAnnotation);
|
| + DartType argumentType =
|
| + compiler.resolveTypeAnnotation(classElement, typeArgument);
|
| + assert(argumentType !== null);
|
| + workQueue.add(argumentType);
|
| + }
|
| + }
|
| +
|
| + while (!workQueue.isEmpty()) {
|
| + DartType type = workQueue.removeLast();
|
| + if (processedTypes.contains(type)) continue;
|
| + processedTypes.add(type);
|
| + if (type is TypedefType) return false;
|
| + if (type is InterfaceType) {
|
| + ClassElement element = type.element;
|
| + ClassNode node = element.parseNode(compiler);
|
| + // Check class type args.
|
| + processTypeArguments(element, node.typeParameters);
|
| + // Check superclass type args.
|
| + if (node.superclass !== null) {
|
| + NodeList typeArguments = node.superclass.typeArguments;
|
| + processTypeArguments(element, node.superclass.typeArguments);
|
| + }
|
| + // Check interfaces type args.
|
| + for (Node interfaceNode in node.interfaces) {
|
| + processTypeArguments(
|
| + element, (interfaceNode as TypeAnnotation).typeArguments);
|
| + }
|
| + // Check all supertypes.
|
| + if (element.allSupertypes !== null) {
|
| + workQueue.addAll(element.allSupertypes.toList());
|
| + }
|
| + }
|
| + }
|
| + return true;
|
| + }
|
| +
|
| DartBackend(Compiler compiler, this.cutDeclarationTypes)
|
| : tasks = <CompilerTask>[],
|
| super(compiler);
|
| @@ -233,13 +299,15 @@ class DartBackend extends Backend {
|
| }
|
| }
|
| topLevelElements.forEach(makePlaceholders);
|
| -
|
| // Create renames.
|
| Map<Node, String> renames = new Map<Node, String>();
|
| Map<LibraryElement, String> imports = new Map<LibraryElement, String>();
|
| + bool shouldCutDeclarationTypes = cutDeclarationTypes
|
| + || (compiler.enableMinification
|
| + && isSafeToRemoveTypeDeclarations(classMembers));
|
| renamePlaceholders(
|
| compiler, collector, renames, imports,
|
| - fixedMemberNames, cutDeclarationTypes);
|
| + fixedMemberNames, shouldCutDeclarationTypes);
|
|
|
| // Sort elements.
|
| final sortedTopLevels = sortElements(topLevelElements);
|
|
|