| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 library dart2js.resolution.class_hierarchy; | 5 library dart2js.resolution.class_hierarchy; |
| 6 | 6 |
| 7 import '../compiler.dart' show | 7 import '../compiler.dart' show |
| 8 Compiler; | 8 Compiler; |
| 9 import '../dart_types.dart'; | 9 import '../dart_types.dart'; |
| 10 import '../diagnostics/invariant.dart' show | 10 import '../diagnostics/invariant.dart' show |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 | 135 |
| 136 DartType visitClassNode(ClassNode node) { | 136 DartType visitClassNode(ClassNode node) { |
| 137 if (element == null) { | 137 if (element == null) { |
| 138 throw compiler.internalError(node, 'element is null'); | 138 throw compiler.internalError(node, 'element is null'); |
| 139 } | 139 } |
| 140 if (element.resolutionState != STATE_STARTED) { | 140 if (element.resolutionState != STATE_STARTED) { |
| 141 throw compiler.internalError(element, | 141 throw compiler.internalError(element, |
| 142 'cyclic resolution of class $element'); | 142 'cyclic resolution of class $element'); |
| 143 } | 143 } |
| 144 | 144 |
| 145 element.computeType(compiler); | 145 element.computeType(resolution); |
| 146 scope = new TypeDeclarationScope(scope, element); | 146 scope = new TypeDeclarationScope(scope, element); |
| 147 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. | 147 // TODO(ahe): It is not safe to call resolveTypeVariableBounds yet. |
| 148 // As a side-effect, this may get us back here trying to | 148 // As a side-effect, this may get us back here trying to |
| 149 // resolve this class again. | 149 // resolve this class again. |
| 150 resolveTypeVariableBounds(node.typeParameters); | 150 resolveTypeVariableBounds(node.typeParameters); |
| 151 | 151 |
| 152 // Setup the supertype for the element (if there is a cycle in the | 152 // Setup the supertype for the element (if there is a cycle in the |
| 153 // class hierarchy, it has already been set to Object). | 153 // class hierarchy, it has already been set to Object). |
| 154 if (element.supertype == null && node.superclass != null) { | 154 if (element.supertype == null && node.superclass != null) { |
| 155 MixinApplication superMixin = node.superclass.asMixinApplication(); | 155 MixinApplication superMixin = node.superclass.asMixinApplication(); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 171 // of Object - the JavaScript backend chooses between Object and | 171 // of Object - the JavaScript backend chooses between Object and |
| 172 // Interceptor. | 172 // Interceptor. |
| 173 if (element.supertype == null) { | 173 if (element.supertype == null) { |
| 174 ClassElement superElement = registry.defaultSuperclass(element); | 174 ClassElement superElement = registry.defaultSuperclass(element); |
| 175 // Avoid making the superclass (usually Object) extend itself. | 175 // Avoid making the superclass (usually Object) extend itself. |
| 176 if (element != superElement) { | 176 if (element != superElement) { |
| 177 if (superElement == null) { | 177 if (superElement == null) { |
| 178 compiler.internalError(node, | 178 compiler.internalError(node, |
| 179 "Cannot resolve default superclass for $element."); | 179 "Cannot resolve default superclass for $element."); |
| 180 } else { | 180 } else { |
| 181 superElement.ensureResolved(compiler); | 181 superElement.ensureResolved(resolution); |
| 182 } | 182 } |
| 183 element.supertype = superElement.computeType(compiler); | 183 element.supertype = superElement.computeType(resolution); |
| 184 } | 184 } |
| 185 } | 185 } |
| 186 | 186 |
| 187 if (element.interfaces == null) { | 187 if (element.interfaces == null) { |
| 188 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); | 188 element.interfaces = resolveInterfaces(node.interfaces, node.superclass); |
| 189 } else { | 189 } else { |
| 190 assert(invariant(element, element.hasIncompleteHierarchy)); | 190 assert(invariant(element, element.hasIncompleteHierarchy)); |
| 191 } | 191 } |
| 192 calculateAllSupertypes(element); | 192 calculateAllSupertypes(element); |
| 193 | 193 |
| 194 if (!element.hasConstructor) { | 194 if (!element.hasConstructor) { |
| 195 Element superMember = element.superclass.localLookup(''); | 195 Element superMember = element.superclass.localLookup(''); |
| 196 if (superMember == null || !superMember.isGenerativeConstructor) { | 196 if (superMember == null || !superMember.isGenerativeConstructor) { |
| 197 MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR; | 197 MessageKind kind = MessageKind.CANNOT_FIND_CONSTRUCTOR; |
| 198 Map arguments = {'constructorName': ''}; | 198 Map arguments = {'constructorName': ''}; |
| 199 // TODO(ahe): Why is this a compile-time error? Or if it is an error, | 199 // TODO(ahe): Why is this a compile-time error? Or if it is an error, |
| 200 // why do we bother to registerThrowNoSuchMethod below? | 200 // why do we bother to registerThrowNoSuchMethod below? |
| 201 compiler.reportErrorMessage(node, kind, arguments); | 201 compiler.reportErrorMessage(node, kind, arguments); |
| 202 superMember = new ErroneousElementX( | 202 superMember = new ErroneousElementX( |
| 203 kind, arguments, '', element); | 203 kind, arguments, '', element); |
| 204 registry.registerThrowNoSuchMethod(); | 204 registry.registerThrowNoSuchMethod(); |
| 205 } else { | 205 } else { |
| 206 ConstructorElement superConstructor = superMember; | 206 ConstructorElement superConstructor = superMember; |
| 207 superConstructor.computeType(compiler); | 207 superConstructor.computeType(resolution); |
| 208 if (!CallStructure.NO_ARGS.signatureApplies( | 208 if (!CallStructure.NO_ARGS.signatureApplies( |
| 209 superConstructor.functionSignature)) { | 209 superConstructor.functionSignature)) { |
| 210 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; | 210 MessageKind kind = MessageKind.NO_MATCHING_CONSTRUCTOR_FOR_IMPLICIT; |
| 211 compiler.reportErrorMessage(node, kind); | 211 compiler.reportErrorMessage(node, kind); |
| 212 superMember = new ErroneousElementX(kind, {}, '', element); | 212 superMember = new ErroneousElementX(kind, {}, '', element); |
| 213 } | 213 } |
| 214 } | 214 } |
| 215 FunctionElement constructor = | 215 FunctionElement constructor = |
| 216 new SynthesizedConstructorElementX.forDefault(superMember, element); | 216 new SynthesizedConstructorElementX.forDefault(superMember, element); |
| 217 if (superMember.isErroneous) { | 217 if (superMember.isErroneous) { |
| 218 compiler.elementsWithCompileTimeErrors.add(constructor); | 218 compiler.elementsWithCompileTimeErrors.add(constructor); |
| 219 } | 219 } |
| 220 element.setDefaultConstructor(constructor, compiler); | 220 element.setDefaultConstructor(constructor, compiler); |
| 221 } | 221 } |
| 222 return element.computeType(compiler); | 222 return element.computeType(resolution); |
| 223 } | 223 } |
| 224 | 224 |
| 225 @override | 225 @override |
| 226 DartType visitEnum(Enum node) { | 226 DartType visitEnum(Enum node) { |
| 227 if (element == null) { | 227 if (element == null) { |
| 228 throw compiler.internalError(node, 'element is null'); | 228 throw compiler.internalError(node, 'element is null'); |
| 229 } | 229 } |
| 230 if (element.resolutionState != STATE_STARTED) { | 230 if (element.resolutionState != STATE_STARTED) { |
| 231 throw compiler.internalError(element, | 231 throw compiler.internalError(element, |
| 232 'cyclic resolution of class $element'); | 232 'cyclic resolution of class $element'); |
| 233 } | 233 } |
| 234 | 234 |
| 235 InterfaceType enumType = element.computeType(compiler); | 235 InterfaceType enumType = element.computeType(resolution); |
| 236 element.supertype = compiler.objectClass.computeType(compiler); | 236 element.supertype = compiler.coreTypes.objectType; |
| 237 element.interfaces = const Link<DartType>(); | 237 element.interfaces = const Link<DartType>(); |
| 238 calculateAllSupertypes(element); | 238 calculateAllSupertypes(element); |
| 239 | 239 |
| 240 if (node.names.nodes.isEmpty) { | 240 if (node.names.nodes.isEmpty) { |
| 241 compiler.reportErrorMessage( | 241 compiler.reportErrorMessage( |
| 242 node, | 242 node, |
| 243 MessageKind.EMPTY_ENUM_DECLARATION, | 243 MessageKind.EMPTY_ENUM_DECLARATION, |
| 244 {'enumName': element.name}); | 244 {'enumName': element.name}); |
| 245 } | 245 } |
| 246 | 246 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 286 } | 286 } |
| 287 | 287 |
| 288 if (identical(node.classKeyword.stringValue, 'typedef')) { | 288 if (identical(node.classKeyword.stringValue, 'typedef')) { |
| 289 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic | 289 // TODO(aprelev@gmail.com): Remove this deprecation diagnostic |
| 290 // together with corresponding TODO in parser.dart. | 290 // together with corresponding TODO in parser.dart. |
| 291 compiler.reportWarningMessage( | 291 compiler.reportWarningMessage( |
| 292 node.classKeyword, | 292 node.classKeyword, |
| 293 MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); | 293 MessageKind.DEPRECATED_TYPEDEF_MIXIN_SYNTAX); |
| 294 } | 294 } |
| 295 | 295 |
| 296 element.computeType(compiler); | 296 element.computeType(resolution); |
| 297 scope = new TypeDeclarationScope(scope, element); | 297 scope = new TypeDeclarationScope(scope, element); |
| 298 resolveTypeVariableBounds(node.typeParameters); | 298 resolveTypeVariableBounds(node.typeParameters); |
| 299 | 299 |
| 300 // Generate anonymous mixin application elements for the | 300 // Generate anonymous mixin application elements for the |
| 301 // intermediate mixin applications (excluding the last). | 301 // intermediate mixin applications (excluding the last). |
| 302 DartType supertype = resolveSupertype(element, node.superclass); | 302 DartType supertype = resolveSupertype(element, node.superclass); |
| 303 Link<Node> link = node.mixins.nodes; | 303 Link<Node> link = node.mixins.nodes; |
| 304 while (!link.tail.isEmpty) { | 304 while (!link.tail.isEmpty) { |
| 305 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); | 305 supertype = applyMixin(supertype, checkMixinType(link.head), link.head); |
| 306 link = link.tail; | 306 link = link.tail; |
| 307 } | 307 } |
| 308 doApplyMixinTo(element, supertype, checkMixinType(link.head)); | 308 doApplyMixinTo(element, supertype, checkMixinType(link.head)); |
| 309 return element.computeType(compiler); | 309 return element.computeType(resolution); |
| 310 } | 310 } |
| 311 | 311 |
| 312 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { | 312 DartType applyMixin(DartType supertype, DartType mixinType, Node node) { |
| 313 String superName = supertype.name; | 313 String superName = supertype.name; |
| 314 String mixinName = mixinType.name; | 314 String mixinName = mixinType.name; |
| 315 MixinApplicationElementX mixinApplication = new MixinApplicationElementX( | 315 MixinApplicationElementX mixinApplication = new MixinApplicationElementX( |
| 316 "${superName}+${mixinName}", | 316 "${superName}+${mixinName}", |
| 317 element.compilationUnit, | 317 element.compilationUnit, |
| 318 compiler.getNextFreeClassId(), | 318 compiler.getNextFreeClassId(), |
| 319 node, | 319 node, |
| (...skipping 10 matching lines...) Expand all Loading... |
| 330 } | 330 } |
| 331 // Setup bounds on the synthetic type variables. | 331 // Setup bounds on the synthetic type variables. |
| 332 for (TypeVariableType type in element.typeVariables) { | 332 for (TypeVariableType type in element.typeVariables) { |
| 333 TypeVariableType typeVariable = typeVariables[type.element.index]; | 333 TypeVariableType typeVariable = typeVariables[type.element.index]; |
| 334 TypeVariableElementX typeVariableElement = typeVariable.element; | 334 TypeVariableElementX typeVariableElement = typeVariable.element; |
| 335 typeVariableElement.typeCache = typeVariable; | 335 typeVariableElement.typeCache = typeVariable; |
| 336 typeVariableElement.boundCache = | 336 typeVariableElement.boundCache = |
| 337 type.element.bound.subst(typeVariables, element.typeVariables); | 337 type.element.bound.subst(typeVariables, element.typeVariables); |
| 338 } | 338 } |
| 339 // Setup this and raw type for the mixin application. | 339 // Setup this and raw type for the mixin application. |
| 340 mixinApplication.computeThisAndRawType(compiler, typeVariables); | 340 mixinApplication.computeThisAndRawType(resolution, typeVariables); |
| 341 // Substitute in synthetic type variables in super and mixin types. | 341 // Substitute in synthetic type variables in super and mixin types. |
| 342 supertype = supertype.subst(typeVariables, element.typeVariables); | 342 supertype = supertype.subst(typeVariables, element.typeVariables); |
| 343 mixinType = mixinType.subst(typeVariables, element.typeVariables); | 343 mixinType = mixinType.subst(typeVariables, element.typeVariables); |
| 344 | 344 |
| 345 doApplyMixinTo(mixinApplication, supertype, mixinType); | 345 doApplyMixinTo(mixinApplication, supertype, mixinType); |
| 346 mixinApplication.resolutionState = STATE_DONE; | 346 mixinApplication.resolutionState = STATE_DONE; |
| 347 mixinApplication.supertypeLoadState = STATE_DONE; | 347 mixinApplication.supertypeLoadState = STATE_DONE; |
| 348 // Replace the synthetic type variables by the original type variables in | 348 // Replace the synthetic type variables by the original type variables in |
| 349 // the returned type (which should be the type actually extended). | 349 // the returned type (which should be the type actually extended). |
| 350 InterfaceType mixinThisType = mixinApplication.thisType; | 350 InterfaceType mixinThisType = mixinApplication.thisType; |
| 351 return mixinThisType.subst(element.typeVariables, | 351 return mixinThisType.subst(element.typeVariables, |
| 352 mixinThisType.typeArguments); | 352 mixinThisType.typeArguments); |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool isDefaultConstructor(FunctionElement constructor) { | 355 bool isDefaultConstructor(FunctionElement constructor) { |
| 356 if (constructor.name != '') return false; | 356 if (constructor.name != '') return false; |
| 357 constructor.computeType(compiler); | 357 constructor.computeType(resolution); |
| 358 return constructor.functionSignature.parameterCount == 0; | 358 return constructor.functionSignature.parameterCount == 0; |
| 359 } | 359 } |
| 360 | 360 |
| 361 FunctionElement createForwardingConstructor(ConstructorElement target, | 361 FunctionElement createForwardingConstructor(ConstructorElement target, |
| 362 ClassElement enclosing) { | 362 ClassElement enclosing) { |
| 363 FunctionElement constructor = | 363 FunctionElement constructor = |
| 364 new SynthesizedConstructorElementX.notForDefault( | 364 new SynthesizedConstructorElementX.notForDefault( |
| 365 target.name, target, enclosing); | 365 target.name, target, enclosing); |
| 366 constructor.computeType(compiler); | 366 constructor.computeType(resolution); |
| 367 return constructor; | 367 return constructor; |
| 368 } | 368 } |
| 369 | 369 |
| 370 void doApplyMixinTo(MixinApplicationElementX mixinApplication, | 370 void doApplyMixinTo(MixinApplicationElementX mixinApplication, |
| 371 DartType supertype, | 371 DartType supertype, |
| 372 DartType mixinType) { | 372 DartType mixinType) { |
| 373 Node node = mixinApplication.parseNode(compiler); | 373 Node node = mixinApplication.parseNode(resolution.parsing); |
| 374 | 374 |
| 375 if (mixinApplication.supertype != null) { | 375 if (mixinApplication.supertype != null) { |
| 376 // [supertype] is not null if there was a cycle. | 376 // [supertype] is not null if there was a cycle. |
| 377 assert(invariant(node, compiler.compilationFailed)); | 377 assert(invariant(node, compiler.compilationFailed)); |
| 378 supertype = mixinApplication.supertype; | 378 supertype = mixinApplication.supertype; |
| 379 assert(invariant(node, supertype.element == compiler.objectClass)); | 379 assert(invariant(node, supertype.element == compiler.objectClass)); |
| 380 } else { | 380 } else { |
| 381 mixinApplication.supertype = supertype; | 381 mixinApplication.supertype = supertype; |
| 382 } | 382 } |
| 383 | 383 |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 428 return; | 428 return; |
| 429 } | 429 } |
| 430 mixinApplication.addConstructor(forwarder); | 430 mixinApplication.addConstructor(forwarder); |
| 431 }); | 431 }); |
| 432 calculateAllSupertypes(mixinApplication); | 432 calculateAllSupertypes(mixinApplication); |
| 433 } | 433 } |
| 434 | 434 |
| 435 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, | 435 InterfaceType resolveMixinFor(MixinApplicationElement mixinApplication, |
| 436 DartType mixinType) { | 436 DartType mixinType) { |
| 437 ClassElement mixin = mixinType.element; | 437 ClassElement mixin = mixinType.element; |
| 438 mixin.ensureResolved(compiler); | 438 mixin.ensureResolved(resolution); |
| 439 | 439 |
| 440 // Check for cycles in the mixin chain. | 440 // Check for cycles in the mixin chain. |
| 441 ClassElement previous = mixinApplication; // For better error messages. | 441 ClassElement previous = mixinApplication; // For better error messages. |
| 442 ClassElement current = mixin; | 442 ClassElement current = mixin; |
| 443 while (current != null && current.isMixinApplication) { | 443 while (current != null && current.isMixinApplication) { |
| 444 MixinApplicationElement currentMixinApplication = current; | 444 MixinApplicationElement currentMixinApplication = current; |
| 445 if (currentMixinApplication == mixinApplication) { | 445 if (currentMixinApplication == mixinApplication) { |
| 446 compiler.reportErrorMessage( | 446 compiler.reportErrorMessage( |
| 447 mixinApplication, | 447 mixinApplication, |
| 448 MessageKind.ILLEGAL_MIXIN_CYCLE, | 448 MessageKind.ILLEGAL_MIXIN_CYCLE, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 574 interfaces = interfaces.tail) { | 574 interfaces = interfaces.tail) { |
| 575 allSupertypes.add(compiler, interfaces.head); | 575 allSupertypes.add(compiler, interfaces.head); |
| 576 } | 576 } |
| 577 | 577 |
| 578 addAllSupertypes(allSupertypes, supertype); | 578 addAllSupertypes(allSupertypes, supertype); |
| 579 for (Link<DartType> interfaces = cls.interfaces; | 579 for (Link<DartType> interfaces = cls.interfaces; |
| 580 !interfaces.isEmpty; | 580 !interfaces.isEmpty; |
| 581 interfaces = interfaces.tail) { | 581 interfaces = interfaces.tail) { |
| 582 addAllSupertypes(allSupertypes, interfaces.head); | 582 addAllSupertypes(allSupertypes, interfaces.head); |
| 583 } | 583 } |
| 584 allSupertypes.add(compiler, cls.computeType(compiler)); | 584 allSupertypes.add(compiler, cls.computeType(resolution)); |
| 585 cls.allSupertypesAndSelf = allSupertypes.toTypeSet(); | 585 cls.allSupertypesAndSelf = allSupertypes.toTypeSet(); |
| 586 } else { | 586 } else { |
| 587 assert(identical(cls, compiler.objectClass)); | 587 assert(identical(cls, compiler.objectClass)); |
| 588 cls.allSupertypesAndSelf = | 588 cls.allSupertypesAndSelf = |
| 589 new OrderedTypeSet.singleton(cls.computeType(compiler)); | 589 new OrderedTypeSet.singleton(cls.computeType(resolution)); |
| 590 } | 590 } |
| 591 } | 591 } |
| 592 | 592 |
| 593 /** | 593 /** |
| 594 * Adds [type] and all supertypes of [type] to [allSupertypes] while | 594 * Adds [type] and all supertypes of [type] to [allSupertypes] while |
| 595 * substituting type variables. | 595 * substituting type variables. |
| 596 */ | 596 */ |
| 597 void addAllSupertypes(OrderedTypeSetBuilder allSupertypes, | 597 void addAllSupertypes(OrderedTypeSetBuilder allSupertypes, |
| 598 InterfaceType type) { | 598 InterfaceType type) { |
| 599 ClassElement classElement = type.element; | 599 ClassElement classElement = type.element; |
| (...skipping 28 matching lines...) Expand all Loading... |
| 628 ClassElement classElement; | 628 ClassElement classElement; |
| 629 | 629 |
| 630 ClassSupertypeResolver(Compiler compiler, ClassElement cls) | 630 ClassSupertypeResolver(Compiler compiler, ClassElement cls) |
| 631 : context = Scope.buildEnclosingScope(cls), | 631 : context = Scope.buildEnclosingScope(cls), |
| 632 this.classElement = cls, | 632 this.classElement = cls, |
| 633 super(compiler); | 633 super(compiler); |
| 634 | 634 |
| 635 void loadSupertype(ClassElement element, Node from) { | 635 void loadSupertype(ClassElement element, Node from) { |
| 636 if (!element.isResolved) { | 636 if (!element.isResolved) { |
| 637 compiler.resolver.loadSupertypes(element, from); | 637 compiler.resolver.loadSupertypes(element, from); |
| 638 element.ensureResolved(compiler); | 638 element.ensureResolved(resolution); |
| 639 } | 639 } |
| 640 } | 640 } |
| 641 | 641 |
| 642 void visitNodeList(NodeList node) { | 642 void visitNodeList(NodeList node) { |
| 643 if (node != null) { | 643 if (node != null) { |
| 644 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { | 644 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { |
| 645 link.head.accept(this); | 645 link.head.accept(this); |
| 646 } | 646 } |
| 647 } | 647 } |
| 648 } | 648 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 703 if (e == null || !e.impliesType) { | 703 if (e == null || !e.impliesType) { |
| 704 compiler.reportErrorMessage( | 704 compiler.reportErrorMessage( |
| 705 node.selector, | 705 node.selector, |
| 706 MessageKind.CANNOT_RESOLVE_TYPE, | 706 MessageKind.CANNOT_RESOLVE_TYPE, |
| 707 {'typeName': node.selector}); | 707 {'typeName': node.selector}); |
| 708 return; | 708 return; |
| 709 } | 709 } |
| 710 loadSupertype(e, node); | 710 loadSupertype(e, node); |
| 711 } | 711 } |
| 712 } | 712 } |
| OLD | NEW |