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 | 7 import 'common/names.dart' show |
8 Identifiers; | 8 Identifiers; |
9 import 'common/resolution.dart' show | 9 import 'common/resolution.dart' show |
10 Resolution; | 10 Resolution; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
52 TypedefElement, | 52 TypedefElement, |
53 VariableElement; | 53 VariableElement; |
54 import 'resolution/tree_elements.dart' show | 54 import 'resolution/tree_elements.dart' show |
55 TreeElements; | 55 TreeElements; |
56 import 'resolution/class_members.dart' show | 56 import 'resolution/class_members.dart' show |
57 MembersCreator; | 57 MembersCreator; |
58 import 'tree/tree.dart'; | 58 import 'tree/tree.dart'; |
59 import 'util/util.dart' show | 59 import 'util/util.dart' show |
60 Link, | 60 Link, |
61 LinkBuilder; | 61 LinkBuilder; |
62 import '../compiler_new.dart' as api; | |
63 | 62 |
64 class TypeCheckerTask extends CompilerTask { | 63 class TypeCheckerTask extends CompilerTask { |
65 TypeCheckerTask(Compiler compiler) : super(compiler); | 64 TypeCheckerTask(Compiler compiler) : super(compiler); |
66 String get name => "Type checker"; | 65 String get name => "Type checker"; |
67 | 66 |
68 void check(AstElement element) { | 67 void check(AstElement element) { |
69 if (element.isClass) return; | 68 if (element.isClass) return; |
70 if (element.isTypedef) return; | 69 if (element.isTypedef) return; |
71 ResolvedAst resolvedAst = element.resolvedAst; | 70 ResolvedAst resolvedAst = element.resolvedAst; |
72 reporter.withCurrentElement(element.implementation, () { | 71 reporter.withCurrentElement(element.implementation, () { |
(...skipping 695 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 // This is an access of the special 'call' method implicitly defined | 767 // This is an access of the special 'call' method implicitly defined |
769 // on 'Function'. This method can be called with any arguments, which | 768 // on 'Function'. This method can be called with any arguments, which |
770 // we ensure by giving it the type 'dynamic'. | 769 // we ensure by giving it the type 'dynamic'. |
771 return new FunctionCallAccess(null, const DynamicType()); | 770 return new FunctionCallAccess(null, const DynamicType()); |
772 } | 771 } |
773 } | 772 } |
774 return null; | 773 return null; |
775 } | 774 } |
776 | 775 |
777 DartType unaliasedBound = | 776 DartType unaliasedBound = |
778 Types.computeUnaliasedBound(compiler, receiverType); | 777 Types.computeUnaliasedBound(resolution, receiverType); |
779 if (unaliasedBound.treatAsDynamic) { | 778 if (unaliasedBound.treatAsDynamic) { |
780 return new DynamicAccess(); | 779 return new DynamicAccess(); |
781 } | 780 } |
782 InterfaceType interface = | 781 InterfaceType interface = |
783 Types.computeInterfaceType(compiler, unaliasedBound); | 782 Types.computeInterfaceType(resolution, unaliasedBound); |
784 ElementAccess access = getAccess(memberName, unaliasedBound, interface); | 783 ElementAccess access = getAccess(memberName, unaliasedBound, interface); |
785 if (access != null) { | 784 if (access != null) { |
786 return access; | 785 return access; |
787 } | 786 } |
788 if (receiverElement != null && | 787 if (receiverElement != null && |
789 (receiverElement.isVariable || receiverElement.isParameter)) { | 788 (receiverElement.isVariable || receiverElement.isParameter)) { |
790 Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement]; | 789 Link<TypePromotion> typePromotions = typePromotionsMap[receiverElement]; |
791 if (typePromotions != null) { | 790 if (typePromotions != null) { |
792 while (!typePromotions.isEmpty) { | 791 while (!typePromotions.isEmpty) { |
793 TypePromotion typePromotion = typePromotions.head; | 792 TypePromotion typePromotion = typePromotions.head; |
794 if (!typePromotion.isValid) { | 793 if (!typePromotion.isValid) { |
795 DartType unaliasedBound = | 794 DartType unaliasedBound = |
796 Types.computeUnaliasedBound(compiler, typePromotion.type); | 795 Types.computeUnaliasedBound(resolution, typePromotion.type); |
797 if (!unaliasedBound.treatAsDynamic) { | 796 if (!unaliasedBound.treatAsDynamic) { |
798 InterfaceType interface = | 797 InterfaceType interface = |
799 Types.computeInterfaceType(compiler, unaliasedBound); | 798 Types.computeInterfaceType(resolution, unaliasedBound); |
800 if (getAccess(memberName, unaliasedBound, interface) != null) { | 799 if (getAccess(memberName, unaliasedBound, interface) != null) { |
801 reportTypePromotionHint(typePromotion); | 800 reportTypePromotionHint(typePromotion); |
802 } | 801 } |
803 } | 802 } |
804 } | 803 } |
805 typePromotions = typePromotions.tail; | 804 typePromotions = typePromotions.tail; |
806 } | 805 } |
807 } | 806 } |
808 } | 807 } |
809 // We didn't find a member with the correct name. If this lookup is for a | 808 // We didn't find a member with the correct name. If this lookup is for a |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
884 DartType lookupMemberType(Node node, DartType type, String name, | 883 DartType lookupMemberType(Node node, DartType type, String name, |
885 MemberKind memberKind, | 884 MemberKind memberKind, |
886 {bool isHint: false}) { | 885 {bool isHint: false}) { |
887 return lookupMember(node, type, name, memberKind, null, isHint: isHint) | 886 return lookupMember(node, type, name, memberKind, null, isHint: isHint) |
888 .computeType(resolution); | 887 .computeType(resolution); |
889 } | 888 } |
890 | 889 |
891 void analyzeArguments(Send send, Element element, DartType type, | 890 void analyzeArguments(Send send, Element element, DartType type, |
892 [LinkBuilder<DartType> argumentTypes]) { | 891 [LinkBuilder<DartType> argumentTypes]) { |
893 Link<Node> arguments = send.arguments; | 892 Link<Node> arguments = send.arguments; |
894 DartType unaliasedType = type.unalias(resolution); | 893 type.computeUnaliased(resolution); |
| 894 DartType unaliasedType = type.unaliased; |
895 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { | 895 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { |
896 | 896 |
897 /// Report [warning] including info(s) about the declaration of [element] | 897 /// Report [warning] including info(s) about the declaration of [element] |
898 /// or [type]. | 898 /// or [type]. |
899 void reportWarning(DiagnosticMessage warning) { | 899 void reportWarning(DiagnosticMessage warning) { |
900 // TODO(johnniwinther): Support pointing to individual parameters on | 900 // TODO(johnniwinther): Support pointing to individual parameters on |
901 // assignability warnings. | 901 // assignability warnings. |
902 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 902 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
903 Element declaration = element; | 903 Element declaration = element; |
904 if (declaration == null) { | 904 if (declaration == null) { |
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 [LinkBuilder<DartType> argumentTypes]) { | 1006 [LinkBuilder<DartType> argumentTypes]) { |
1007 DartType type = elementAccess.computeType(resolution); | 1007 DartType type = elementAccess.computeType(resolution); |
1008 if (elementAccess.isCallable(compiler)) { | 1008 if (elementAccess.isCallable(compiler)) { |
1009 analyzeArguments(node, elementAccess.element, type, argumentTypes); | 1009 analyzeArguments(node, elementAccess.element, type, argumentTypes); |
1010 } else { | 1010 } else { |
1011 reportTypeWarning(node, MessageKind.NOT_CALLABLE, | 1011 reportTypeWarning(node, MessageKind.NOT_CALLABLE, |
1012 {'elementName': elementAccess.name}); | 1012 {'elementName': elementAccess.name}); |
1013 analyzeArguments(node, elementAccess.element, const DynamicType(), | 1013 analyzeArguments(node, elementAccess.element, const DynamicType(), |
1014 argumentTypes); | 1014 argumentTypes); |
1015 } | 1015 } |
1016 type = type.unalias(resolution); | 1016 type.computeUnaliased(resolution); |
1017 if (identical(type.kind, TypeKind.FUNCTION)) { | 1017 type = type.unaliased; |
| 1018 if (type.isFunctionType) { |
1018 FunctionType funType = type; | 1019 FunctionType funType = type; |
1019 return funType.returnType; | 1020 return funType.returnType; |
1020 } else { | 1021 } else { |
1021 return const DynamicType(); | 1022 return const DynamicType(); |
1022 } | 1023 } |
1023 } | 1024 } |
1024 | 1025 |
1025 /** | 1026 /** |
1026 * Computes the [ElementAccess] for [name] on the [node] possibly using the | 1027 * Computes the [ElementAccess] for [name] on the [node] possibly using the |
1027 * [element] provided for [node] by the resolver. | 1028 * [element] provided for [node] by the resolver. |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1144 // class A<T, V> {} | 1145 // class A<T, V> {} |
1145 // class B<S, U> extends A<S, int> {} | 1146 // class B<S, U> extends A<S, int> {} |
1146 // and a promotion from a [knownType] of `A<double, int>` to a | 1147 // and a promotion from a [knownType] of `A<double, int>` to a |
1147 // [shownType] of `B`. | 1148 // [shownType] of `B`. |
1148 InterfaceType knownInterfaceType = knownType; | 1149 InterfaceType knownInterfaceType = knownType; |
1149 ClassElement shownClass = shownType.element; | 1150 ClassElement shownClass = shownType.element; |
1150 | 1151 |
1151 // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using | 1152 // Compute `B<double, dynamic>` as the subtype of `A<double, int>` using |
1152 // the relation between `A<S, int>` and `A<double, int>`. | 1153 // the relation between `A<S, int>` and `A<double, int>`. |
1153 MoreSpecificSubtypeVisitor visitor = | 1154 MoreSpecificSubtypeVisitor visitor = |
1154 new MoreSpecificSubtypeVisitor(compiler); | 1155 new MoreSpecificSubtypeVisitor(types); |
1155 InterfaceType shownTypeGeneric = visitor.computeMoreSpecific( | 1156 InterfaceType shownTypeGeneric = visitor.computeMoreSpecific( |
1156 shownClass, knownInterfaceType); | 1157 shownClass, knownInterfaceType); |
1157 | 1158 |
1158 if (shownTypeGeneric != null && | 1159 if (shownTypeGeneric != null && |
1159 types.isMoreSpecific(shownTypeGeneric, knownType)) { | 1160 types.isMoreSpecific(shownTypeGeneric, knownType)) { |
1160 // This should be the case but we double-check. | 1161 // This should be the case but we double-check. |
1161 // TODO(johnniwinther): Ensure that we don't suggest malbounded types. | 1162 // TODO(johnniwinther): Ensure that we don't suggest malbounded types. |
1162 return shownTypeGeneric; | 1163 return shownTypeGeneric; |
1163 } | 1164 } |
1164 } | 1165 } |
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1838 // TODO(johnniwinther): Move this to _CompilerCoreTypes. | 1839 // TODO(johnniwinther): Move this to _CompilerCoreTypes. |
1839 compiler.streamClass.ensureResolved(resolution); | 1840 compiler.streamClass.ensureResolved(resolution); |
1840 DartType streamOfDynamic = coreTypes.streamType(); | 1841 DartType streamOfDynamic = coreTypes.streamType(); |
1841 if (!types.isAssignable(expressionType, streamOfDynamic)) { | 1842 if (!types.isAssignable(expressionType, streamOfDynamic)) { |
1842 reportMessage(node.expression, | 1843 reportMessage(node.expression, |
1843 MessageKind.NOT_ASSIGNABLE, | 1844 MessageKind.NOT_ASSIGNABLE, |
1844 {'fromType': expressionType, 'toType': streamOfDynamic}, | 1845 {'fromType': expressionType, 'toType': streamOfDynamic}, |
1845 isHint: true); | 1846 isHint: true); |
1846 } else { | 1847 } else { |
1847 InterfaceType interfaceType = | 1848 InterfaceType interfaceType = |
1848 Types.computeInterfaceType(compiler, expressionType); | 1849 Types.computeInterfaceType(resolution, expressionType); |
1849 if (interfaceType != null) { | 1850 if (interfaceType != null) { |
1850 InterfaceType streamType = | 1851 InterfaceType streamType = |
1851 interfaceType.asInstanceOf(compiler.streamClass); | 1852 interfaceType.asInstanceOf(compiler.streamClass); |
1852 if (streamType != null) { | 1853 if (streamType != null) { |
1853 DartType streamElementType = streamType.typeArguments.first; | 1854 DartType streamElementType = streamType.typeArguments.first; |
1854 if (!types.isAssignable(streamElementType, elementType)) { | 1855 if (!types.isAssignable(streamElementType, elementType)) { |
1855 reportMessage(node.expression, | 1856 reportMessage(node.expression, |
1856 MessageKind.FORIN_NOT_ASSIGNABLE, | 1857 MessageKind.FORIN_NOT_ASSIGNABLE, |
1857 {'currentType': streamElementType, | 1858 {'currentType': streamElementType, |
1858 'expressionType': expressionType, | 1859 'expressionType': expressionType, |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2005 | 2006 |
2006 visitTypedef(Typedef node) { | 2007 visitTypedef(Typedef node) { |
2007 // Do not typecheck [Typedef] nodes. | 2008 // Do not typecheck [Typedef] nodes. |
2008 } | 2009 } |
2009 | 2010 |
2010 visitNode(Node node) { | 2011 visitNode(Node node) { |
2011 reporter.internalError(node, | 2012 reporter.internalError(node, |
2012 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 2013 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
2013 } | 2014 } |
2014 } | 2015 } |
OLD | NEW |