| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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.typechecker; | 5 library dart2js.typechecker; |
| 6 | 6 |
| 7 import 'common/names.dart' show Identifiers; | 7 import 'common/names.dart' show Identifiers; |
| 8 import 'common/resolution.dart' show Resolution; | 8 import 'common/resolution.dart' show Resolution; |
| 9 import 'common/tasks.dart' show CompilerTask; | 9 import 'common/tasks.dart' show CompilerTask; |
| 10 import 'common.dart'; | 10 import 'common.dart'; |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 104 | 104 |
| 105 /// Returns [: true :] if the element can be access as an invocation. | 105 /// Returns [: true :] if the element can be access as an invocation. |
| 106 bool isCallable(Compiler compiler) { | 106 bool isCallable(Compiler compiler) { |
| 107 if (element != null && element.isAbstractField) { | 107 if (element != null && element.isAbstractField) { |
| 108 AbstractFieldElement abstractFieldElement = element; | 108 AbstractFieldElement abstractFieldElement = element; |
| 109 if (abstractFieldElement.getter == null) { | 109 if (abstractFieldElement.getter == null) { |
| 110 // Setters cannot be invoked as function invocations. | 110 // Setters cannot be invoked as function invocations. |
| 111 return false; | 111 return false; |
| 112 } | 112 } |
| 113 } | 113 } |
| 114 return compiler.types.isAssignable( | 114 ResolutionInterfaceType functionType = compiler.commonElements.functionType; |
| 115 computeType(compiler.resolution), compiler.commonElements.functionType); | 115 return compiler.types |
| 116 .isAssignable(computeType(compiler.resolution), functionType); |
| 116 } | 117 } |
| 117 } | 118 } |
| 118 | 119 |
| 119 /// An access of a instance member. | 120 /// An access of a instance member. |
| 120 class MemberAccess extends ElementAccess { | 121 class MemberAccess extends ElementAccess { |
| 121 final MemberSignature member; | 122 final MemberSignature member; |
| 122 | 123 |
| 123 MemberAccess(MemberSignature this.member); | 124 MemberAccess(MemberSignature this.member); |
| 124 | 125 |
| 125 Element get element => member.declarations.first.element; | 126 Element get element => member.declarations.first.element; |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 223 final ResolutionDartType type; | 224 final ResolutionDartType type; |
| 224 | 225 |
| 225 TypeLiteralAccess(this.type) { | 226 TypeLiteralAccess(this.type) { |
| 226 assert(type != null); | 227 assert(type != null); |
| 227 } | 228 } |
| 228 | 229 |
| 229 Element get element => type.element; | 230 Element get element => type.element; |
| 230 | 231 |
| 231 String get name => type.name; | 232 String get name => type.name; |
| 232 | 233 |
| 233 ResolutionDartType computeType(Resolution resolution) => | 234 ResolutionInterfaceType computeType(Resolution resolution) => |
| 234 resolution.commonElements.typeType; | 235 resolution.commonElements.typeType; |
| 235 | 236 |
| 236 String toString() => 'TypeLiteralAccess($type)'; | 237 String toString() => 'TypeLiteralAccess($type)'; |
| 237 } | 238 } |
| 238 | 239 |
| 239 /// An access to the 'call' method of a function type. | 240 /// An access to the 'call' method of a function type. |
| 240 class FunctionCallAccess implements ElementAccess { | 241 class FunctionCallAccess implements ElementAccess { |
| 241 final Element element; | 242 final Element element; |
| 242 final ResolutionDartType type; | 243 final ResolutionDartType type; |
| 243 | 244 |
| (...skipping 505 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 return const DynamicAccess(); | 750 return const DynamicAccess(); |
| 750 } else { | 751 } else { |
| 751 return new MemberAccess(member); | 752 return new MemberAccess(member); |
| 752 } | 753 } |
| 753 } | 754 } |
| 754 if (name == const PublicName('call')) { | 755 if (name == const PublicName('call')) { |
| 755 if (unaliasedBound.isFunctionType) { | 756 if (unaliasedBound.isFunctionType) { |
| 756 // This is an access the implicit 'call' method of a function type. | 757 // This is an access the implicit 'call' method of a function type. |
| 757 return new FunctionCallAccess(receiverElement, unaliasedBound); | 758 return new FunctionCallAccess(receiverElement, unaliasedBound); |
| 758 } | 759 } |
| 759 if (types.isSubtype(interface, commonElements.functionType)) { | 760 ResolutionInterfaceType functionType = commonElements.functionType; |
| 761 if (types.isSubtype(interface, functionType)) { |
| 760 // This is an access of the special 'call' method implicitly defined | 762 // This is an access of the special 'call' method implicitly defined |
| 761 // on 'Function'. This method can be called with any arguments, which | 763 // on 'Function'. This method can be called with any arguments, which |
| 762 // we ensure by giving it the type 'dynamic'. | 764 // we ensure by giving it the type 'dynamic'. |
| 763 return new FunctionCallAccess(null, const ResolutionDynamicType()); | 765 return new FunctionCallAccess(null, const ResolutionDynamicType()); |
| 764 } | 766 } |
| 765 } | 767 } |
| 766 return null; | 768 return null; |
| 767 } | 769 } |
| 768 | 770 |
| 769 ResolutionDartType unaliasedBound = | 771 ResolutionDartType unaliasedBound = |
| (...skipping 835 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1605 ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) { | 1607 ResolutionDartType visitStringJuxtaposition(StringJuxtaposition node) { |
| 1606 analyze(node.first); | 1608 analyze(node.first); |
| 1607 analyze(node.second); | 1609 analyze(node.second); |
| 1608 return stringType; | 1610 return stringType; |
| 1609 } | 1611 } |
| 1610 | 1612 |
| 1611 ResolutionDartType visitLiteralNull(LiteralNull node) { | 1613 ResolutionDartType visitLiteralNull(LiteralNull node) { |
| 1612 return const ResolutionDynamicType(); | 1614 return const ResolutionDynamicType(); |
| 1613 } | 1615 } |
| 1614 | 1616 |
| 1615 ResolutionDartType visitLiteralSymbol(LiteralSymbol node) { | 1617 ResolutionInterfaceType visitLiteralSymbol(LiteralSymbol node) { |
| 1616 return commonElements.symbolType; | 1618 return commonElements.symbolType; |
| 1617 } | 1619 } |
| 1618 | 1620 |
| 1619 ResolutionDartType computeConstructorType( | 1621 ResolutionDartType computeConstructorType( |
| 1620 ConstructorElement constructor, ResolutionDartType type) { | 1622 ConstructorElement constructor, ResolutionDartType type) { |
| 1621 if (Elements.isUnresolved(constructor)) | 1623 if (Elements.isUnresolved(constructor)) |
| 1622 return const ResolutionDynamicType(); | 1624 return const ResolutionDynamicType(); |
| 1623 ResolutionDartType constructorType = constructor.computeType(resolution); | 1625 ResolutionDartType constructorType = constructor.computeType(resolution); |
| 1624 if (identical(type.kind, ResolutionTypeKind.INTERFACE)) { | 1626 if (identical(type.kind, ResolutionTypeKind.INTERFACE)) { |
| 1625 if (constructor.isSynthesized) { | 1627 if (constructor.isSynthesized) { |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1693 | 1695 |
| 1694 // Executing a return statement return e; [...] It is a static type warning | 1696 // Executing a return statement return e; [...] It is a static type warning |
| 1695 // if the type of e may not be assigned to the declared return type of the | 1697 // if the type of e may not be assigned to the declared return type of the |
| 1696 // immediately enclosing function. | 1698 // immediately enclosing function. |
| 1697 if (expression != null) { | 1699 if (expression != null) { |
| 1698 ResolutionDartType expressionType = analyze(expression); | 1700 ResolutionDartType expressionType = analyze(expression); |
| 1699 if (executableContext.isGenerativeConstructor) { | 1701 if (executableContext.isGenerativeConstructor) { |
| 1700 // The resolver already emitted an error for this expression. | 1702 // The resolver already emitted an error for this expression. |
| 1701 } else { | 1703 } else { |
| 1702 if (currentAsyncMarker == AsyncMarker.ASYNC) { | 1704 if (currentAsyncMarker == AsyncMarker.ASYNC) { |
| 1703 expressionType = | 1705 ResolutionInterfaceType futureOfFlattenedType = |
| 1704 commonElements.futureType(types.flatten(expressionType)); | 1706 commonElements.futureType(types.flatten(expressionType)); |
| 1707 expressionType = futureOfFlattenedType; |
| 1705 } | 1708 } |
| 1706 if (expectedReturnType.isVoid && | 1709 if (expectedReturnType.isVoid && |
| 1707 !types.isAssignable(expressionType, const ResolutionVoidType())) { | 1710 !types.isAssignable(expressionType, const ResolutionVoidType())) { |
| 1708 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); | 1711 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); |
| 1709 } else { | 1712 } else { |
| 1710 checkAssignable(expression, expressionType, expectedReturnType); | 1713 checkAssignable(expression, expressionType, expectedReturnType); |
| 1711 } | 1714 } |
| 1712 } | 1715 } |
| 1713 } else if (currentAsyncMarker != AsyncMarker.SYNC) { | 1716 } else if (currentAsyncMarker != AsyncMarker.SYNC) { |
| 1714 // `return;` is allowed. | 1717 // `return;` is allowed. |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1732 | 1735 |
| 1733 ResolutionDartType visitAwait(Await node) { | 1736 ResolutionDartType visitAwait(Await node) { |
| 1734 ResolutionDartType expressionType = analyze(node.expression); | 1737 ResolutionDartType expressionType = analyze(node.expression); |
| 1735 if (resolution.target.supportsAsyncAwait) { | 1738 if (resolution.target.supportsAsyncAwait) { |
| 1736 return types.flatten(expressionType); | 1739 return types.flatten(expressionType); |
| 1737 } else { | 1740 } else { |
| 1738 return const ResolutionDynamicType(); | 1741 return const ResolutionDynamicType(); |
| 1739 } | 1742 } |
| 1740 } | 1743 } |
| 1741 | 1744 |
| 1742 ResolutionDartType visitYield(Yield node) { | 1745 visitYield(Yield node) { |
| 1743 ResolutionDartType resultType = analyze(node.expression); | 1746 ResolutionDartType resultType = analyze(node.expression); |
| 1744 if (!node.hasStar) { | 1747 if (!node.hasStar) { |
| 1745 if (currentAsyncMarker.isAsync) { | 1748 if (currentAsyncMarker.isAsync) { |
| 1746 resultType = commonElements.streamType(resultType); | 1749 ResolutionInterfaceType streamOfResultType = |
| 1750 commonElements.streamType(resultType); |
| 1751 resultType = streamOfResultType; |
| 1747 } else { | 1752 } else { |
| 1748 resultType = commonElements.iterableType(resultType); | 1753 ResolutionInterfaceType iterableOfResultType = |
| 1754 commonElements.iterableType(resultType); |
| 1755 resultType = iterableOfResultType; |
| 1749 } | 1756 } |
| 1750 } else { | 1757 } else { |
| 1751 if (currentAsyncMarker.isAsync) { | 1758 if (currentAsyncMarker.isAsync) { |
| 1752 // The static type of expression must be assignable to Stream. | 1759 // The static type of expression must be assignable to Stream. |
| 1753 checkAssignable(node, resultType, commonElements.streamType()); | 1760 ResolutionInterfaceType streamType = commonElements.streamType(); |
| 1761 checkAssignable(node, resultType, streamType); |
| 1754 } else { | 1762 } else { |
| 1755 // The static type of expression must be assignable to Iterable. | 1763 // The static type of expression must be assignable to Iterable. |
| 1756 checkAssignable(node, resultType, commonElements.iterableType()); | 1764 ResolutionInterfaceType iterableType = commonElements.iterableType(); |
| 1765 checkAssignable(node, resultType, iterableType); |
| 1757 } | 1766 } |
| 1758 } | 1767 } |
| 1759 // The static type of the result must be assignable to the declared type. | 1768 // The static type of the result must be assignable to the declared type. |
| 1760 checkAssignable(node, resultType, expectedReturnType); | 1769 checkAssignable(node, resultType, expectedReturnType); |
| 1761 } | 1770 } |
| 1762 | 1771 |
| 1763 ResolutionDartType visitTypeAnnotation(TypeAnnotation node) { | 1772 ResolutionDartType visitTypeAnnotation(TypeAnnotation node) { |
| 1764 return elements.getType(node); | 1773 return elements.getType(node); |
| 1765 } | 1774 } |
| 1766 | 1775 |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1867 declaredIdentifier.type, const ResolutionDynamicType()); | 1876 declaredIdentifier.type, const ResolutionDynamicType()); |
| 1868 } else { | 1877 } else { |
| 1869 return analyze(node.declaredIdentifier); | 1878 return analyze(node.declaredIdentifier); |
| 1870 } | 1879 } |
| 1871 } | 1880 } |
| 1872 | 1881 |
| 1873 visitAsyncForIn(AsyncForIn node) { | 1882 visitAsyncForIn(AsyncForIn node) { |
| 1874 ResolutionDartType elementType = computeForInElementType(node); | 1883 ResolutionDartType elementType = computeForInElementType(node); |
| 1875 ResolutionDartType expressionType = analyze(node.expression); | 1884 ResolutionDartType expressionType = analyze(node.expression); |
| 1876 if (resolution.target.supportsAsyncAwait) { | 1885 if (resolution.target.supportsAsyncAwait) { |
| 1877 ResolutionDartType streamOfDynamic = commonElements.streamType(); | 1886 ResolutionInterfaceType streamOfDynamic = commonElements.streamType(); |
| 1878 if (!types.isAssignable(expressionType, streamOfDynamic)) { | 1887 if (!types.isAssignable(expressionType, streamOfDynamic)) { |
| 1879 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE, | 1888 reportMessage(node.expression, MessageKind.NOT_ASSIGNABLE, |
| 1880 {'fromType': expressionType, 'toType': streamOfDynamic}, | 1889 {'fromType': expressionType, 'toType': streamOfDynamic}, |
| 1881 isHint: true); | 1890 isHint: true); |
| 1882 } else { | 1891 } else { |
| 1883 ResolutionInterfaceType interfaceType = | 1892 ResolutionInterfaceType interfaceType = |
| 1884 Types.computeInterfaceType(resolution, expressionType); | 1893 Types.computeInterfaceType(resolution, expressionType); |
| 1885 if (interfaceType != null) { | 1894 if (interfaceType != null) { |
| 1886 ResolutionInterfaceType streamType = | 1895 ResolutionInterfaceType streamType = |
| 1887 interfaceType.asInstanceOf(streamOfDynamic.element); | 1896 interfaceType.asInstanceOf(streamOfDynamic.element); |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2045 | 2054 |
| 2046 visitTypedef(Typedef node) { | 2055 visitTypedef(Typedef node) { |
| 2047 // Do not typecheck [Typedef] nodes. | 2056 // Do not typecheck [Typedef] nodes. |
| 2048 } | 2057 } |
| 2049 | 2058 |
| 2050 visitNode(Node node) { | 2059 visitNode(Node node) { |
| 2051 reporter.internalError(node, | 2060 reporter.internalError(node, |
| 2052 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 2061 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
| 2053 } | 2062 } |
| 2054 } | 2063 } |
| OLD | NEW |