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 |