| 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 |
| 10 Resolution; |
| 9 import 'common/tasks.dart' show | 11 import 'common/tasks.dart' show |
| 10 CompilerTask; | 12 CompilerTask; |
| 11 import 'compiler.dart' show | 13 import 'compiler.dart' show |
| 12 Compiler; | 14 Compiler; |
| 13 import 'constants/expressions.dart'; | 15 import 'constants/expressions.dart'; |
| 14 import 'constants/values.dart'; | 16 import 'constants/values.dart'; |
| 15 import 'core_types.dart'; | 17 import 'core_types.dart'; |
| 16 import 'dart_types.dart'; | 18 import 'dart_types.dart'; |
| 17 import 'diagnostics/diagnostic_listener.dart' show | 19 import 'diagnostics/diagnostic_listener.dart' show |
| 18 DiagnosticMessage; | 20 DiagnosticMessage; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 97 | 99 |
| 98 /** | 100 /** |
| 99 * [ElementAccess] represents the access of [element], either as a property | 101 * [ElementAccess] represents the access of [element], either as a property |
| 100 * access or invocation. | 102 * access or invocation. |
| 101 */ | 103 */ |
| 102 abstract class ElementAccess { | 104 abstract class ElementAccess { |
| 103 Element get element; | 105 Element get element; |
| 104 | 106 |
| 105 String get name => element.name; | 107 String get name => element.name; |
| 106 | 108 |
| 107 DartType computeType(Compiler compiler); | 109 DartType computeType(Resolution resolution); |
| 108 | 110 |
| 109 /// Returns [: true :] if the element can be access as an invocation. | 111 /// Returns [: true :] if the element can be access as an invocation. |
| 110 bool isCallable(Compiler compiler) { | 112 bool isCallable(Compiler compiler) { |
| 111 if (element != null && element.isAbstractField) { | 113 if (element != null && element.isAbstractField) { |
| 112 AbstractFieldElement abstractFieldElement = element; | 114 AbstractFieldElement abstractFieldElement = element; |
| 113 if (abstractFieldElement.getter == null) { | 115 if (abstractFieldElement.getter == null) { |
| 114 // Setters cannot be invoked as function invocations. | 116 // Setters cannot be invoked as function invocations. |
| 115 return false; | 117 return false; |
| 116 } | 118 } |
| 117 } | 119 } |
| 118 return compiler.types.isAssignable( | 120 return compiler.types.isAssignable( |
| 119 computeType(compiler), compiler.coreTypes.functionType); | 121 computeType(compiler.resolution), compiler.coreTypes.functionType); |
| 120 } | 122 } |
| 121 } | 123 } |
| 122 | 124 |
| 123 /// An access of a instance member. | 125 /// An access of a instance member. |
| 124 class MemberAccess extends ElementAccess { | 126 class MemberAccess extends ElementAccess { |
| 125 final MemberSignature member; | 127 final MemberSignature member; |
| 126 | 128 |
| 127 MemberAccess(MemberSignature this.member); | 129 MemberAccess(MemberSignature this.member); |
| 128 | 130 |
| 129 Element get element => member.declarations.first.element; | 131 Element get element => member.declarations.first.element; |
| 130 | 132 |
| 131 DartType computeType(Compiler compiler) => member.type; | 133 DartType computeType(Resolution resolution) => member.type; |
| 132 | 134 |
| 133 String toString() => 'MemberAccess($member)'; | 135 String toString() => 'MemberAccess($member)'; |
| 134 } | 136 } |
| 135 | 137 |
| 136 /// An access of an unresolved element. | 138 /// An access of an unresolved element. |
| 137 class DynamicAccess implements ElementAccess { | 139 class DynamicAccess implements ElementAccess { |
| 138 const DynamicAccess(); | 140 const DynamicAccess(); |
| 139 | 141 |
| 140 Element get element => null; | 142 Element get element => null; |
| 141 | 143 |
| 142 String get name => 'dynamic'; | 144 String get name => 'dynamic'; |
| 143 | 145 |
| 144 DartType computeType(Compiler compiler) => const DynamicType(); | 146 DartType computeType(Resolution resolution) => const DynamicType(); |
| 145 | 147 |
| 146 bool isCallable(Compiler compiler) => true; | 148 bool isCallable(Compiler compiler) => true; |
| 147 | 149 |
| 148 String toString() => 'DynamicAccess'; | 150 String toString() => 'DynamicAccess'; |
| 149 } | 151 } |
| 150 | 152 |
| 151 /** | 153 /** |
| 152 * An access of a resolved top-level or static property or function, or an | 154 * An access of a resolved top-level or static property or function, or an |
| 153 * access of a resolved element through [:this:]. | 155 * access of a resolved element through [:this:]. |
| 154 */ | 156 */ |
| 155 class ResolvedAccess extends ElementAccess { | 157 class ResolvedAccess extends ElementAccess { |
| 156 final Element element; | 158 final Element element; |
| 157 | 159 |
| 158 ResolvedAccess(Element this.element) { | 160 ResolvedAccess(Element this.element) { |
| 159 assert(element != null); | 161 assert(element != null); |
| 160 } | 162 } |
| 161 | 163 |
| 162 DartType computeType(Compiler compiler) { | 164 DartType computeType(Resolution resolution) { |
| 163 if (element.isGetter) { | 165 if (element.isGetter) { |
| 164 GetterElement getter = element; | 166 GetterElement getter = element; |
| 165 FunctionType functionType = getter.computeType(compiler); | 167 FunctionType functionType = getter.computeType(resolution); |
| 166 return functionType.returnType; | 168 return functionType.returnType; |
| 167 } else if (element.isSetter) { | 169 } else if (element.isSetter) { |
| 168 SetterElement setter = element; | 170 SetterElement setter = element; |
| 169 FunctionType functionType = setter.computeType(compiler); | 171 FunctionType functionType = setter.computeType(resolution); |
| 170 if (functionType.parameterTypes.length != 1) { | 172 if (functionType.parameterTypes.length != 1) { |
| 171 // TODO(johnniwinther,karlklose): this happens for malformed static | 173 // TODO(johnniwinther,karlklose): this happens for malformed static |
| 172 // setters. Treat them the same as instance members. | 174 // setters. Treat them the same as instance members. |
| 173 return const DynamicType(); | 175 return const DynamicType(); |
| 174 } | 176 } |
| 175 return functionType.parameterTypes.first; | 177 return functionType.parameterTypes.first; |
| 176 } else if (element.isTypedef || element.isClass) { | 178 } else if (element.isTypedef || element.isClass) { |
| 177 TypeDeclarationElement typeDeclaration = element; | 179 TypeDeclarationElement typeDeclaration = element; |
| 178 typeDeclaration.computeType(compiler); | 180 typeDeclaration.computeType(resolution); |
| 179 return typeDeclaration.thisType; | 181 return typeDeclaration.thisType; |
| 180 } else { | 182 } else { |
| 181 TypedElement typedElement = element; | 183 TypedElement typedElement = element; |
| 182 typedElement.computeType(compiler); | 184 typedElement.computeType(resolution); |
| 183 return typedElement.type; | 185 return typedElement.type; |
| 184 } | 186 } |
| 185 } | 187 } |
| 186 | 188 |
| 187 String toString() => 'ResolvedAccess($element)'; | 189 String toString() => 'ResolvedAccess($element)'; |
| 188 } | 190 } |
| 189 | 191 |
| 190 /// An access to a promoted variable. | 192 /// An access to a promoted variable. |
| 191 class PromotedAccess extends ElementAccess { | 193 class PromotedAccess extends ElementAccess { |
| 192 final VariableElement element; | 194 final VariableElement element; |
| 193 final DartType type; | 195 final DartType type; |
| 194 | 196 |
| 195 PromotedAccess(VariableElement this.element, DartType this.type) { | 197 PromotedAccess(VariableElement this.element, DartType this.type) { |
| 196 assert(element != null); | 198 assert(element != null); |
| 197 assert(type != null); | 199 assert(type != null); |
| 198 } | 200 } |
| 199 | 201 |
| 200 DartType computeType(Compiler compiler) => type; | 202 DartType computeType(Resolution resolution) => type; |
| 201 | 203 |
| 202 String toString() => 'PromotedAccess($element,$type)'; | 204 String toString() => 'PromotedAccess($element,$type)'; |
| 203 } | 205 } |
| 204 | 206 |
| 205 /** | 207 /** |
| 206 * An access of a resolved top-level or static property or function, or an | 208 * An access of a resolved top-level or static property or function, or an |
| 207 * access of a resolved element through [:this:]. | 209 * access of a resolved element through [:this:]. |
| 208 */ | 210 */ |
| 209 class TypeAccess extends ElementAccess { | 211 class TypeAccess extends ElementAccess { |
| 210 final DartType type; | 212 final DartType type; |
| 211 TypeAccess(DartType this.type) { | 213 TypeAccess(DartType this.type) { |
| 212 assert(type != null); | 214 assert(type != null); |
| 213 } | 215 } |
| 214 | 216 |
| 215 Element get element => type.element; | 217 Element get element => type.element; |
| 216 | 218 |
| 217 DartType computeType(Compiler compiler) => type; | 219 DartType computeType(Resolution resolution) => type; |
| 218 | 220 |
| 219 String toString() => 'TypeAccess($type)'; | 221 String toString() => 'TypeAccess($type)'; |
| 220 } | 222 } |
| 221 | 223 |
| 222 /** | 224 /** |
| 223 * An access of a type literal. | 225 * An access of a type literal. |
| 224 */ | 226 */ |
| 225 class TypeLiteralAccess extends ElementAccess { | 227 class TypeLiteralAccess extends ElementAccess { |
| 226 final DartType type; | 228 final DartType type; |
| 227 | 229 |
| 228 TypeLiteralAccess(this.type) { | 230 TypeLiteralAccess(this.type) { |
| 229 assert(type != null); | 231 assert(type != null); |
| 230 } | 232 } |
| 231 | 233 |
| 232 Element get element => type.element; | 234 Element get element => type.element; |
| 233 | 235 |
| 234 String get name => type.name; | 236 String get name => type.name; |
| 235 | 237 |
| 236 DartType computeType(Compiler compiler) => compiler.typeClass.rawType; | 238 DartType computeType(Resolution resolution) => resolution.coreTypes.typeType; |
| 237 | 239 |
| 238 String toString() => 'TypeLiteralAccess($type)'; | 240 String toString() => 'TypeLiteralAccess($type)'; |
| 239 } | 241 } |
| 240 | 242 |
| 241 | 243 |
| 242 /// An access to the 'call' method of a function type. | 244 /// An access to the 'call' method of a function type. |
| 243 class FunctionCallAccess implements ElementAccess { | 245 class FunctionCallAccess implements ElementAccess { |
| 244 final Element element; | 246 final Element element; |
| 245 final DartType type; | 247 final DartType type; |
| 246 | 248 |
| 247 const FunctionCallAccess(this.element, this.type); | 249 const FunctionCallAccess(this.element, this.type); |
| 248 | 250 |
| 249 String get name => 'call'; | 251 String get name => 'call'; |
| 250 | 252 |
| 251 DartType computeType(Compiler compiler) => type; | 253 DartType computeType(Resolution resolution) => type; |
| 252 | 254 |
| 253 bool isCallable(Compiler compiler) => true; | 255 bool isCallable(Compiler compiler) => true; |
| 254 | 256 |
| 255 String toString() => 'FunctionAccess($element, $type)'; | 257 String toString() => 'FunctionAccess($element, $type)'; |
| 256 } | 258 } |
| 257 | 259 |
| 258 | 260 |
| 259 /// An is-expression that potentially promotes a variable. | 261 /// An is-expression that potentially promotes a variable. |
| 260 class TypePromotion { | 262 class TypePromotion { |
| 261 final Send node; | 263 final Send node; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 Node lastSeenNode; | 299 Node lastSeenNode; |
| 298 DartType expectedReturnType; | 300 DartType expectedReturnType; |
| 299 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; | 301 AsyncMarker currentAsyncMarker = AsyncMarker.SYNC; |
| 300 | 302 |
| 301 final ClassElement currentClass; | 303 final ClassElement currentClass; |
| 302 | 304 |
| 303 /// The immediately enclosing field, method or constructor being analyzed. | 305 /// The immediately enclosing field, method or constructor being analyzed. |
| 304 ExecutableElement executableContext; | 306 ExecutableElement executableContext; |
| 305 | 307 |
| 306 CoreTypes get coreTypes => compiler.coreTypes; | 308 CoreTypes get coreTypes => compiler.coreTypes; |
| 309 Resolution get resolution => compiler.resolution; |
| 307 | 310 |
| 308 InterfaceType get intType => coreTypes.intType; | 311 InterfaceType get intType => coreTypes.intType; |
| 309 InterfaceType get doubleType => coreTypes.doubleType; | 312 InterfaceType get doubleType => coreTypes.doubleType; |
| 310 InterfaceType get boolType => coreTypes.boolType; | 313 InterfaceType get boolType => coreTypes.boolType; |
| 311 InterfaceType get stringType => coreTypes.stringType; | 314 InterfaceType get stringType => coreTypes.stringType; |
| 312 | 315 |
| 313 DartType thisType; | 316 DartType thisType; |
| 314 DartType superType; | 317 DartType superType; |
| 315 | 318 |
| 316 Link<DartType> cascadeTypes = const Link<DartType>(); | 319 Link<DartType> cascadeTypes = const Link<DartType>(); |
| (...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 649 message: 'FunctionExpression with no element')); | 652 message: 'FunctionExpression with no element')); |
| 650 if (Elements.isUnresolved(element)) return const DynamicType(); | 653 if (Elements.isUnresolved(element)) return const DynamicType(); |
| 651 if (element.isGenerativeConstructor) { | 654 if (element.isGenerativeConstructor) { |
| 652 type = const DynamicType(); | 655 type = const DynamicType(); |
| 653 returnType = const VoidType(); | 656 returnType = const VoidType(); |
| 654 | 657 |
| 655 element.functionSignature.forEachParameter((ParameterElement parameter) { | 658 element.functionSignature.forEachParameter((ParameterElement parameter) { |
| 656 if (parameter.isInitializingFormal) { | 659 if (parameter.isInitializingFormal) { |
| 657 InitializingFormalElement fieldParameter = parameter; | 660 InitializingFormalElement fieldParameter = parameter; |
| 658 checkAssignable(parameter, parameter.type, | 661 checkAssignable(parameter, parameter.type, |
| 659 fieldParameter.fieldElement.computeType(compiler)); | 662 fieldParameter.fieldElement.computeType(resolution)); |
| 660 } | 663 } |
| 661 }); | 664 }); |
| 662 if (node.initializers != null) { | 665 if (node.initializers != null) { |
| 663 analyze(node.initializers, inInitializer: true); | 666 analyze(node.initializers, inInitializer: true); |
| 664 } | 667 } |
| 665 } else { | 668 } else { |
| 666 FunctionType functionType = element.computeType(compiler); | 669 FunctionType functionType = element.computeType(resolution); |
| 667 returnType = functionType.returnType; | 670 returnType = functionType.returnType; |
| 668 type = functionType; | 671 type = functionType; |
| 669 } | 672 } |
| 670 ExecutableElement previousExecutableContext = executableContext; | 673 ExecutableElement previousExecutableContext = executableContext; |
| 671 DartType previousReturnType = expectedReturnType; | 674 DartType previousReturnType = expectedReturnType; |
| 672 expectedReturnType = returnType; | 675 expectedReturnType = returnType; |
| 673 AsyncMarker previousAsyncMarker = currentAsyncMarker; | 676 AsyncMarker previousAsyncMarker = currentAsyncMarker; |
| 674 | 677 |
| 675 executableContext = element; | 678 executableContext = element; |
| 676 currentAsyncMarker = element.asyncMarker; | 679 currentAsyncMarker = element.asyncMarker; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 688 } else if (node.isSuper()) { | 691 } else if (node.isSuper()) { |
| 689 return superType; | 692 return superType; |
| 690 } else { | 693 } else { |
| 691 TypedElement element = elements[node]; | 694 TypedElement element = elements[node]; |
| 692 assert(invariant(node, element != null, | 695 assert(invariant(node, element != null, |
| 693 message: 'Missing element for identifier')); | 696 message: 'Missing element for identifier')); |
| 694 assert(invariant(node, element.isVariable || | 697 assert(invariant(node, element.isVariable || |
| 695 element.isParameter || | 698 element.isParameter || |
| 696 element.isField, | 699 element.isField, |
| 697 message: 'Unexpected context element ${element}')); | 700 message: 'Unexpected context element ${element}')); |
| 698 return element.computeType(compiler); | 701 return element.computeType(resolution); |
| 699 } | 702 } |
| 700 } | 703 } |
| 701 | 704 |
| 702 DartType visitIf(If node) { | 705 DartType visitIf(If node) { |
| 703 Expression condition = node.condition.expression; | 706 Expression condition = node.condition.expression; |
| 704 Statement thenPart = node.thenPart; | 707 Statement thenPart = node.thenPart; |
| 705 | 708 |
| 706 checkCondition(node.condition); | 709 checkCondition(node.condition); |
| 707 analyzeInPromotedContext(condition, thenPart); | 710 analyzeInPromotedContext(condition, thenPart); |
| 708 if (node.elsePart != null) { | 711 if (node.elsePart != null) { |
| (...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 871 } | 874 } |
| 872 } | 875 } |
| 873 } | 876 } |
| 874 return const DynamicAccess(); | 877 return const DynamicAccess(); |
| 875 } | 878 } |
| 876 | 879 |
| 877 DartType lookupMemberType(Node node, DartType type, String name, | 880 DartType lookupMemberType(Node node, DartType type, String name, |
| 878 MemberKind memberKind, | 881 MemberKind memberKind, |
| 879 {bool isHint: false}) { | 882 {bool isHint: false}) { |
| 880 return lookupMember(node, type, name, memberKind, null, isHint: isHint) | 883 return lookupMember(node, type, name, memberKind, null, isHint: isHint) |
| 881 .computeType(compiler); | 884 .computeType(resolution); |
| 882 } | 885 } |
| 883 | 886 |
| 884 void analyzeArguments(Send send, Element element, DartType type, | 887 void analyzeArguments(Send send, Element element, DartType type, |
| 885 [LinkBuilder<DartType> argumentTypes]) { | 888 [LinkBuilder<DartType> argumentTypes]) { |
| 886 Link<Node> arguments = send.arguments; | 889 Link<Node> arguments = send.arguments; |
| 887 DartType unaliasedType = type.unalias(compiler); | 890 DartType unaliasedType = type.unalias(resolution); |
| 888 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { | 891 if (identical(unaliasedType.kind, TypeKind.FUNCTION)) { |
| 889 | 892 |
| 890 /// Report [warning] including info(s) about the declaration of [element] | 893 /// Report [warning] including info(s) about the declaration of [element] |
| 891 /// or [type]. | 894 /// or [type]. |
| 892 void reportWarning(DiagnosticMessage warning) { | 895 void reportWarning(DiagnosticMessage warning) { |
| 893 // TODO(johnniwinther): Support pointing to individual parameters on | 896 // TODO(johnniwinther): Support pointing to individual parameters on |
| 894 // assignability warnings. | 897 // assignability warnings. |
| 895 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; | 898 List<DiagnosticMessage> infos = <DiagnosticMessage>[]; |
| 896 Element declaration = element; | 899 Element declaration = element; |
| 897 if (declaration == null) { | 900 if (declaration == null) { |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 } | 993 } |
| 991 } | 994 } |
| 992 } | 995 } |
| 993 | 996 |
| 994 // Analyze the invocation [node] of [elementAccess]. | 997 // Analyze the invocation [node] of [elementAccess]. |
| 995 // | 998 // |
| 996 // If provided [argumentTypes] is filled with the argument types during | 999 // If provided [argumentTypes] is filled with the argument types during |
| 997 // analysis. | 1000 // analysis. |
| 998 DartType analyzeInvocation(Send node, ElementAccess elementAccess, | 1001 DartType analyzeInvocation(Send node, ElementAccess elementAccess, |
| 999 [LinkBuilder<DartType> argumentTypes]) { | 1002 [LinkBuilder<DartType> argumentTypes]) { |
| 1000 DartType type = elementAccess.computeType(compiler); | 1003 DartType type = elementAccess.computeType(resolution); |
| 1001 if (elementAccess.isCallable(compiler)) { | 1004 if (elementAccess.isCallable(compiler)) { |
| 1002 analyzeArguments(node, elementAccess.element, type, argumentTypes); | 1005 analyzeArguments(node, elementAccess.element, type, argumentTypes); |
| 1003 } else { | 1006 } else { |
| 1004 reportTypeWarning(node, MessageKind.NOT_CALLABLE, | 1007 reportTypeWarning(node, MessageKind.NOT_CALLABLE, |
| 1005 {'elementName': elementAccess.name}); | 1008 {'elementName': elementAccess.name}); |
| 1006 analyzeArguments(node, elementAccess.element, const DynamicType(), | 1009 analyzeArguments(node, elementAccess.element, const DynamicType(), |
| 1007 argumentTypes); | 1010 argumentTypes); |
| 1008 } | 1011 } |
| 1009 type = type.unalias(compiler); | 1012 type = type.unalias(resolution); |
| 1010 if (identical(type.kind, TypeKind.FUNCTION)) { | 1013 if (identical(type.kind, TypeKind.FUNCTION)) { |
| 1011 FunctionType funType = type; | 1014 FunctionType funType = type; |
| 1012 return funType.returnType; | 1015 return funType.returnType; |
| 1013 } else { | 1016 } else { |
| 1014 return const DynamicType(); | 1017 return const DynamicType(); |
| 1015 } | 1018 } |
| 1016 } | 1019 } |
| 1017 | 1020 |
| 1018 /** | 1021 /** |
| 1019 * Computes the [ElementAccess] for [name] on the [node] possibly using the | 1022 * Computes the [ElementAccess] for [name] on the [node] possibly using the |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1110 | 1113 |
| 1111 /** | 1114 /** |
| 1112 * Computes the type of the access of [name] on the [node] possibly using the | 1115 * Computes the type of the access of [name] on the [node] possibly using the |
| 1113 * [element] provided for [node] by the resolver. | 1116 * [element] provided for [node] by the resolver. |
| 1114 */ | 1117 */ |
| 1115 DartType computeAccessType(Send node, String name, Element element, | 1118 DartType computeAccessType(Send node, String name, Element element, |
| 1116 MemberKind memberKind, | 1119 MemberKind memberKind, |
| 1117 {bool lookupClassMember: false}) { | 1120 {bool lookupClassMember: false}) { |
| 1118 DartType type = | 1121 DartType type = |
| 1119 computeAccess(node, name, element, memberKind, | 1122 computeAccess(node, name, element, memberKind, |
| 1120 lookupClassMember: lookupClassMember).computeType(compiler); | 1123 lookupClassMember: lookupClassMember).computeType(resolution); |
| 1121 if (type == null) { | 1124 if (type == null) { |
| 1122 compiler.internalError(node, 'Type is null on access of $name on $node.'); | 1125 compiler.internalError(node, 'Type is null on access of $name on $node.'); |
| 1123 } | 1126 } |
| 1124 return type; | 1127 return type; |
| 1125 } | 1128 } |
| 1126 | 1129 |
| 1127 /// Compute a version of [shownType] that is more specific that [knownType]. | 1130 /// Compute a version of [shownType] that is more specific that [knownType]. |
| 1128 /// This is used to provided better hints when trying to promote a supertype | 1131 /// This is used to provided better hints when trying to promote a supertype |
| 1129 /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List` | 1132 /// to a raw subtype. For instance trying to promote `Iterable<int>` to `List` |
| 1130 /// we suggest the use of `List<int>`, which would make promotion valid. | 1133 /// we suggest the use of `List<int>`, which would make promotion valid. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 return intType; | 1330 return intType; |
| 1328 } else if (identical(argumentType.element, compiler.doubleClass)) { | 1331 } else if (identical(argumentType.element, compiler.doubleClass)) { |
| 1329 return doubleType; | 1332 return doubleType; |
| 1330 } | 1333 } |
| 1331 } | 1334 } |
| 1332 } | 1335 } |
| 1333 return resultType; | 1336 return resultType; |
| 1334 } else if (node.isPropertyAccess) { | 1337 } else if (node.isPropertyAccess) { |
| 1335 ElementAccess access = | 1338 ElementAccess access = |
| 1336 computeAccess(node, selector.source, element, MemberKind.GETTER); | 1339 computeAccess(node, selector.source, element, MemberKind.GETTER); |
| 1337 return access.computeType(compiler); | 1340 return access.computeType(resolution); |
| 1338 } else if (node.isFunctionObjectInvocation) { | 1341 } else if (node.isFunctionObjectInvocation) { |
| 1339 return unhandledExpression(); | 1342 return unhandledExpression(); |
| 1340 } else { | 1343 } else { |
| 1341 ElementAccess access = | 1344 ElementAccess access = |
| 1342 computeAccess(node, selector.source, element, MemberKind.METHOD); | 1345 computeAccess(node, selector.source, element, MemberKind.METHOD); |
| 1343 return analyzeInvocation(node, access); | 1346 return analyzeInvocation(node, access); |
| 1344 } | 1347 } |
| 1345 } | 1348 } |
| 1346 | 1349 |
| 1347 /// Returns the first type in the list or [:dynamic:] if the list is empty. | 1350 /// Returns the first type in the list or [:dynamic:] if the list is empty. |
| (...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1571 return const DynamicType(); | 1574 return const DynamicType(); |
| 1572 } | 1575 } |
| 1573 | 1576 |
| 1574 DartType visitLiteralSymbol(LiteralSymbol node) { | 1577 DartType visitLiteralSymbol(LiteralSymbol node) { |
| 1575 return compiler.symbolClass.rawType; | 1578 return compiler.symbolClass.rawType; |
| 1576 } | 1579 } |
| 1577 | 1580 |
| 1578 DartType computeConstructorType(ConstructorElement constructor, | 1581 DartType computeConstructorType(ConstructorElement constructor, |
| 1579 DartType type) { | 1582 DartType type) { |
| 1580 if (Elements.isUnresolved(constructor)) return const DynamicType(); | 1583 if (Elements.isUnresolved(constructor)) return const DynamicType(); |
| 1581 DartType constructorType = constructor.computeType(compiler); | 1584 DartType constructorType = constructor.computeType(resolution); |
| 1582 if (identical(type.kind, TypeKind.INTERFACE)) { | 1585 if (identical(type.kind, TypeKind.INTERFACE)) { |
| 1583 if (constructor.isSynthesized) { | 1586 if (constructor.isSynthesized) { |
| 1584 // TODO(johnniwinther): Remove this when synthesized constructors handle | 1587 // TODO(johnniwinther): Remove this when synthesized constructors handle |
| 1585 // type variables correctly. | 1588 // type variables correctly. |
| 1586 InterfaceType interfaceType = type; | 1589 InterfaceType interfaceType = type; |
| 1587 ClassElement receiverElement = interfaceType.element; | 1590 ClassElement receiverElement = interfaceType.element; |
| 1588 while (receiverElement.isMixinApplication) { | 1591 while (receiverElement.isMixinApplication) { |
| 1589 receiverElement = receiverElement.supertype.element; | 1592 receiverElement = receiverElement.supertype.element; |
| 1590 } | 1593 } |
| 1591 constructorType = constructorType.substByContext( | 1594 constructorType = constructorType.substByContext( |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1794 analyzeWithDefault(declaredIdentifier.type, const DynamicType()); | 1797 analyzeWithDefault(declaredIdentifier.type, const DynamicType()); |
| 1795 } else { | 1798 } else { |
| 1796 return analyze(node.declaredIdentifier); | 1799 return analyze(node.declaredIdentifier); |
| 1797 } | 1800 } |
| 1798 } | 1801 } |
| 1799 | 1802 |
| 1800 visitAsyncForIn(AsyncForIn node) { | 1803 visitAsyncForIn(AsyncForIn node) { |
| 1801 DartType elementType = computeForInElementType(node); | 1804 DartType elementType = computeForInElementType(node); |
| 1802 DartType expressionType = analyze(node.expression); | 1805 DartType expressionType = analyze(node.expression); |
| 1803 // TODO(johnniwinther): Move this to _CompilerCoreTypes. | 1806 // TODO(johnniwinther): Move this to _CompilerCoreTypes. |
| 1804 compiler.streamClass.ensureResolved(compiler); | 1807 compiler.streamClass.ensureResolved(resolution); |
| 1805 DartType streamOfDynamic = coreTypes.streamType(); | 1808 DartType streamOfDynamic = coreTypes.streamType(); |
| 1806 if (!types.isAssignable(expressionType, streamOfDynamic)) { | 1809 if (!types.isAssignable(expressionType, streamOfDynamic)) { |
| 1807 reportMessage(node.expression, | 1810 reportMessage(node.expression, |
| 1808 MessageKind.NOT_ASSIGNABLE, | 1811 MessageKind.NOT_ASSIGNABLE, |
| 1809 {'fromType': expressionType, 'toType': streamOfDynamic}, | 1812 {'fromType': expressionType, 'toType': streamOfDynamic}, |
| 1810 isHint: true); | 1813 isHint: true); |
| 1811 } else { | 1814 } else { |
| 1812 InterfaceType interfaceType = | 1815 InterfaceType interfaceType = |
| 1813 Types.computeInterfaceType(compiler, expressionType); | 1816 Types.computeInterfaceType(compiler, expressionType); |
| 1814 if (interfaceType != null) { | 1817 if (interfaceType != null) { |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1970 | 1973 |
| 1971 visitTypedef(Typedef node) { | 1974 visitTypedef(Typedef node) { |
| 1972 // Do not typecheck [Typedef] nodes. | 1975 // Do not typecheck [Typedef] nodes. |
| 1973 } | 1976 } |
| 1974 | 1977 |
| 1975 visitNode(Node node) { | 1978 visitNode(Node node) { |
| 1976 compiler.internalError(node, | 1979 compiler.internalError(node, |
| 1977 'Unexpected node ${node.getObjectDescription()} in the type checker.'); | 1980 'Unexpected node ${node.getObjectDescription()} in the type checker.'); |
| 1978 } | 1981 } |
| 1979 } | 1982 } |
| OLD | NEW |