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 634 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
645 | 645 |
646 ResolutionDartType visitFunctionExpression(FunctionExpression node) { | 646 ResolutionDartType visitFunctionExpression(FunctionExpression node) { |
647 ResolutionDartType type; | 647 ResolutionDartType type; |
648 ResolutionDartType returnType; | 648 ResolutionDartType returnType; |
649 final FunctionElement element = elements.getFunctionDefinition(node); | 649 final FunctionElement element = elements.getFunctionDefinition(node); |
650 assert(invariant(node, element != null, | 650 assert(invariant(node, element != null, |
651 message: 'FunctionExpression with no element')); | 651 message: 'FunctionExpression with no element')); |
652 if (Elements.isUnresolved(element)) return const ResolutionDynamicType(); | 652 if (Elements.isUnresolved(element)) return const ResolutionDynamicType(); |
653 if (element.isGenerativeConstructor) { | 653 if (element.isGenerativeConstructor) { |
654 type = const ResolutionDynamicType(); | 654 type = const ResolutionDynamicType(); |
655 returnType = const ResolutionVoidType(); | 655 // TODO(floitsch): would be nice to have the voidType directly on |
| 656 // commonElements. |
| 657 returnType = new ResolutionVoidType(commonElements.objectClass); |
656 | 658 |
657 element.functionSignature.forEachParameter((ParameterElement parameter) { | 659 element.functionSignature.forEachParameter((ParameterElement parameter) { |
658 if (parameter.isInitializingFormal) { | 660 if (parameter.isInitializingFormal) { |
659 InitializingFormalElement fieldParameter = parameter; | 661 InitializingFormalElement fieldParameter = parameter; |
660 checkAssignable(parameter, parameter.type, | 662 checkAssignable(parameter, parameter.type, |
661 fieldParameter.fieldElement.computeType(resolution)); | 663 fieldParameter.fieldElement.computeType(resolution)); |
662 } | 664 } |
663 }); | 665 }); |
664 if (node.initializers != null) { | 666 if (node.initializers != null) { |
665 analyzeUntyped(node.initializers, inInitializer: true); | 667 analyzeUntyped(node.initializers, inInitializer: true); |
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1686 } | 1688 } |
1687 | 1689 |
1688 /** Dart Programming Language Specification: 11.10 Return */ | 1690 /** Dart Programming Language Specification: 11.10 Return */ |
1689 visitReturn(Return node) { | 1691 visitReturn(Return node) { |
1690 if (identical(node.beginToken.stringValue, 'native')) { | 1692 if (identical(node.beginToken.stringValue, 'native')) { |
1691 return; | 1693 return; |
1692 } | 1694 } |
1693 | 1695 |
1694 final Node expression = node.expression; | 1696 final Node expression = node.expression; |
1695 | 1697 |
| 1698 // TODO(floitsch): would be nice if the voidType was directly accessible |
| 1699 // from `commonElements`. |
| 1700 ResolutionVoidType voidType = |
| 1701 new ResolutionVoidType(commonElements.objectClass); |
1696 // Executing a return statement return e; [...] It is a static type warning | 1702 // Executing a return statement return e; [...] It is a static type warning |
1697 // if the type of e may not be assigned to the declared return type of the | 1703 // if the type of e may not be assigned to the declared return type of the |
1698 // immediately enclosing function. | 1704 // immediately enclosing function. |
1699 if (expression != null) { | 1705 if (expression != null) { |
1700 ResolutionDartType expressionType = analyze(expression); | 1706 ResolutionDartType expressionType = analyze(expression); |
1701 if (executableContext.isGenerativeConstructor) { | 1707 if (executableContext.isGenerativeConstructor) { |
1702 // The resolver already emitted an error for this expression. | 1708 // The resolver already emitted an error for this expression. |
1703 } else { | 1709 } else { |
1704 if (currentAsyncMarker == AsyncMarker.ASYNC) { | 1710 if (currentAsyncMarker == AsyncMarker.ASYNC) { |
1705 ResolutionInterfaceType futureOfFlattenedType = | 1711 ResolutionInterfaceType futureOfFlattenedType = |
1706 commonElements.futureType(types.flatten(expressionType)); | 1712 commonElements.futureType(types.flatten(expressionType)); |
1707 expressionType = futureOfFlattenedType; | 1713 expressionType = futureOfFlattenedType; |
1708 } | 1714 } |
| 1715 // TODO(floitsch): this is probably where we want to have the checks |
| 1716 // that `void` must not have a `return` unless it returns void. |
1709 if (expectedReturnType.isVoid && | 1717 if (expectedReturnType.isVoid && |
1710 !types.isAssignable(expressionType, const ResolutionVoidType())) { | 1718 !types.isAssignable(expressionType, voidType)) { |
1711 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); | 1719 reportTypeWarning(expression, MessageKind.RETURN_VALUE_IN_VOID); |
1712 } else { | 1720 } else { |
1713 checkAssignable(expression, expressionType, expectedReturnType); | 1721 checkAssignable(expression, expressionType, expectedReturnType); |
1714 } | 1722 } |
1715 } | 1723 } |
1716 } else if (currentAsyncMarker != AsyncMarker.SYNC) { | 1724 } else if (currentAsyncMarker != AsyncMarker.SYNC) { |
1717 // `return;` is allowed. | 1725 // `return;` is allowed. |
1718 } else if (!types.isAssignable( | 1726 } else if (!types.isAssignable(expectedReturnType, voidType)) { |
1719 expectedReturnType, const ResolutionVoidType())) { | 1727 // TODO(floitsch): this is probably where we want to have the checks |
| 1728 // that `void` must not have a `return` unless it returns void. |
| 1729 |
1720 // Let f be the function immediately enclosing a return statement of the | 1730 // Let f be the function immediately enclosing a return statement of the |
1721 // form 'return;' It is a static warning if both of the following | 1731 // form 'return;' It is a static warning if both of the following |
1722 // conditions hold: | 1732 // conditions hold: |
1723 // - f is not a generative constructor. | 1733 // - f is not a generative constructor. |
1724 // - The return type of f may not be assigned to void. | 1734 // - The return type of f may not be assigned to void. |
1725 reportTypeWarning( | 1735 reportTypeWarning( |
1726 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType}); | 1736 node, MessageKind.RETURN_NOTHING, {'returnType': expectedReturnType}); |
1727 } | 1737 } |
1728 } | 1738 } |
1729 | 1739 |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2054 | 2064 |
2055 visitTypedef(Typedef node) { | 2065 visitTypedef(Typedef node) { |
2056 // Do not typecheck [Typedef] nodes. | 2066 // Do not typecheck [Typedef] nodes. |
2057 } | 2067 } |
2058 | 2068 |
2059 visitNode(Node node) { | 2069 visitNode(Node node) { |
2060 reporter.internalError(node, | 2070 reporter.internalError(node, |
2061 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 2071 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
2062 } | 2072 } |
2063 } | 2073 } |
OLD | NEW |