| OLD | NEW |
| 1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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.resolution.types; | 5 library dart2js.resolution.types; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/resolution.dart' show | 8 import '../common/resolution.dart' show Feature, Resolution; |
| 9 Feature, | 9 import '../compiler.dart' show Compiler; |
| 10 Resolution; | 10 import '../dart_backend/dart_backend.dart' show DartBackend; |
| 11 import '../compiler.dart' show | |
| 12 Compiler; | |
| 13 import '../dart_backend/dart_backend.dart' show | |
| 14 DartBackend; | |
| 15 import '../dart_types.dart'; | 11 import '../dart_types.dart'; |
| 16 import '../elements/elements.dart' show | 12 import '../elements/elements.dart' |
| 17 AmbiguousElement, | 13 show |
| 18 ClassElement, | 14 AmbiguousElement, |
| 19 Element, | 15 ClassElement, |
| 20 Elements, | 16 Element, |
| 21 ErroneousElement, | 17 Elements, |
| 22 PrefixElement, | 18 ErroneousElement, |
| 23 TypedefElement, | 19 PrefixElement, |
| 24 TypeVariableElement; | 20 TypedefElement, |
| 25 import '../elements/modelx.dart' show | 21 TypeVariableElement; |
| 26 ErroneousElementX; | 22 import '../elements/modelx.dart' show ErroneousElementX; |
| 27 import '../tree/tree.dart'; | 23 import '../tree/tree.dart'; |
| 28 import '../util/util.dart' show | 24 import '../util/util.dart' show Link; |
| 29 Link; | |
| 30 | 25 |
| 31 import 'members.dart' show | 26 import 'members.dart' show lookupInScope; |
| 32 lookupInScope; | 27 import 'registry.dart' show ResolutionRegistry; |
| 33 import 'registry.dart' show | 28 import 'resolution_common.dart' show MappingVisitor; |
| 34 ResolutionRegistry; | 29 import 'scope.dart' show Scope; |
| 35 import 'resolution_common.dart' show | |
| 36 MappingVisitor; | |
| 37 import 'scope.dart' show | |
| 38 Scope; | |
| 39 | 30 |
| 40 class TypeResolver { | 31 class TypeResolver { |
| 41 final Compiler compiler; | 32 final Compiler compiler; |
| 42 | 33 |
| 43 TypeResolver(this.compiler); | 34 TypeResolver(this.compiler); |
| 44 | 35 |
| 45 DiagnosticReporter get reporter => compiler.reporter; | 36 DiagnosticReporter get reporter => compiler.reporter; |
| 46 | 37 |
| 47 Resolution get resolution => compiler.resolution; | 38 Resolution get resolution => compiler.resolution; |
| 48 | 39 |
| 49 /// Tries to resolve the type name as an element. | 40 /// Tries to resolve the type name as an element. |
| 50 Element resolveTypeName(Identifier prefixName, | 41 Element resolveTypeName( |
| 51 Identifier typeName, | 42 Identifier prefixName, Identifier typeName, Scope scope, |
| 52 Scope scope, | 43 {bool deferredIsMalformed: true}) { |
| 53 {bool deferredIsMalformed: true}) { | |
| 54 Element element; | 44 Element element; |
| 55 if (prefixName != null) { | 45 if (prefixName != null) { |
| 56 Element prefixElement = | 46 Element prefixElement = |
| 57 lookupInScope(reporter, prefixName, scope, prefixName.source); | 47 lookupInScope(reporter, prefixName, scope, prefixName.source); |
| 58 if (prefixElement != null && prefixElement.isPrefix) { | 48 if (prefixElement != null && prefixElement.isPrefix) { |
| 59 // The receiver is a prefix. Lookup in the imported members. | 49 // The receiver is a prefix. Lookup in the imported members. |
| 60 PrefixElement prefix = prefixElement; | 50 PrefixElement prefix = prefixElement; |
| 61 element = prefix.lookupLocalMember(typeName.source); | 51 element = prefix.lookupLocalMember(typeName.source); |
| 62 // TODO(17260, sigurdm): The test for DartBackend is there because | 52 // TODO(17260, sigurdm): The test for DartBackend is there because |
| 63 // dart2dart outputs malformed types with prefix. | 53 // dart2dart outputs malformed types with prefix. |
| 64 if (element != null && | 54 if (element != null && |
| 65 prefix.isDeferred && | 55 prefix.isDeferred && |
| 66 deferredIsMalformed && | 56 deferredIsMalformed && |
| 67 compiler.backend is! DartBackend) { | 57 compiler.backend is! DartBackend) { |
| 68 element = new ErroneousElementX(MessageKind.DEFERRED_TYPE_ANNOTATION, | 58 element = new ErroneousElementX(MessageKind.DEFERRED_TYPE_ANNOTATION, |
| 69 {'node': typeName}, | 59 {'node': typeName}, element.name, element); |
| 70 element.name, | |
| 71 element); | |
| 72 } | 60 } |
| 73 } else { | 61 } else { |
| 74 // The caller of this method will create the ErroneousElement for | 62 // The caller of this method will create the ErroneousElement for |
| 75 // the MalformedType. | 63 // the MalformedType. |
| 76 element = null; | 64 element = null; |
| 77 } | 65 } |
| 78 } else { | 66 } else { |
| 79 element = lookupInScope(reporter, typeName, scope, typeName.source); | 67 element = lookupInScope(reporter, typeName, scope, typeName.source); |
| 80 } | 68 } |
| 81 return element; | 69 return element; |
| 82 } | 70 } |
| 83 | 71 |
| 84 DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node, | 72 DartType resolveTypeAnnotation(MappingVisitor visitor, TypeAnnotation node, |
| 85 {bool malformedIsError: false, | 73 {bool malformedIsError: false, bool deferredIsMalformed: true}) { |
| 86 bool deferredIsMalformed: true}) { | |
| 87 ResolutionRegistry registry = visitor.registry; | 74 ResolutionRegistry registry = visitor.registry; |
| 88 | 75 |
| 89 Identifier typeName; | 76 Identifier typeName; |
| 90 DartType type; | 77 DartType type; |
| 91 | 78 |
| 92 DartType checkNoTypeArguments(DartType type) { | 79 DartType checkNoTypeArguments(DartType type) { |
| 93 List<DartType> arguments = new List<DartType>(); | 80 List<DartType> arguments = new List<DartType>(); |
| 94 bool hasTypeArgumentMismatch = resolveTypeArguments( | 81 bool hasTypeArgumentMismatch = |
| 95 visitor, node, const <DartType>[], arguments); | 82 resolveTypeArguments(visitor, node, const <DartType>[], arguments); |
| 96 if (hasTypeArgumentMismatch) { | 83 if (hasTypeArgumentMismatch) { |
| 97 return new MalformedType( | 84 return new MalformedType( |
| 98 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, | 85 new ErroneousElementX(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
| 99 {'type': node}, typeName.source, visitor.enclosingElement), | 86 {'type': node}, typeName.source, visitor.enclosingElement), |
| 100 type, arguments); | 87 type, |
| 88 arguments); |
| 101 } | 89 } |
| 102 return type; | 90 return type; |
| 103 } | 91 } |
| 104 | 92 |
| 105 Identifier prefixName; | 93 Identifier prefixName; |
| 106 Send send = node.typeName.asSend(); | 94 Send send = node.typeName.asSend(); |
| 107 if (send != null) { | 95 if (send != null) { |
| 108 // The type name is of the form [: prefix . identifier :]. | 96 // The type name is of the form [: prefix . identifier :]. |
| 109 prefixName = send.receiver.asIdentifier(); | 97 prefixName = send.receiver.asIdentifier(); |
| 110 typeName = send.selector.asIdentifier(); | 98 typeName = send.selector.asIdentifier(); |
| 111 } else { | 99 } else { |
| 112 typeName = node.typeName.asIdentifier(); | 100 typeName = node.typeName.asIdentifier(); |
| 113 if (identical(typeName.source, 'void')) { | 101 if (identical(typeName.source, 'void')) { |
| 114 type = const VoidType(); | 102 type = const VoidType(); |
| 115 checkNoTypeArguments(type); | 103 checkNoTypeArguments(type); |
| 116 registry.useType(node, type); | 104 registry.useType(node, type); |
| 117 return type; | 105 return type; |
| 118 } else if (identical(typeName.source, 'dynamic')) { | 106 } else if (identical(typeName.source, 'dynamic')) { |
| 119 type = const DynamicType(); | 107 type = const DynamicType(); |
| 120 checkNoTypeArguments(type); | 108 checkNoTypeArguments(type); |
| 121 registry.useType(node, type); | 109 registry.useType(node, type); |
| 122 return type; | 110 return type; |
| 123 } | 111 } |
| 124 } | 112 } |
| 125 | 113 |
| 126 Element element = resolveTypeName(prefixName, typeName, visitor.scope, | 114 Element element = resolveTypeName(prefixName, typeName, visitor.scope, |
| 127 deferredIsMalformed: deferredIsMalformed); | 115 deferredIsMalformed: deferredIsMalformed); |
| 128 | 116 |
| 129 DartType reportFailureAndCreateType( | 117 DartType reportFailureAndCreateType( |
| 130 MessageKind messageKind, | 118 MessageKind messageKind, Map messageArguments, |
| 131 Map messageArguments, | |
| 132 {DartType userProvidedBadType, | 119 {DartType userProvidedBadType, |
| 133 Element erroneousElement, | 120 Element erroneousElement, |
| 134 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { | 121 List<DiagnosticMessage> infos: const <DiagnosticMessage>[]}) { |
| 135 if (malformedIsError) { | 122 if (malformedIsError) { |
| 136 reporter.reportError( | 123 reporter.reportError( |
| 137 reporter.createMessage(node, messageKind, messageArguments), | 124 reporter.createMessage(node, messageKind, messageArguments), infos); |
| 138 infos); | |
| 139 } else { | 125 } else { |
| 140 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 126 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 141 reporter.reportWarning( | 127 reporter.reportWarning( |
| 142 reporter.createMessage(node, messageKind, messageArguments), | 128 reporter.createMessage(node, messageKind, messageArguments), infos); |
| 143 infos); | |
| 144 } | 129 } |
| 145 if (erroneousElement == null) { | 130 if (erroneousElement == null) { |
| 146 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 131 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 147 erroneousElement = new ErroneousElementX( | 132 erroneousElement = new ErroneousElementX(messageKind, messageArguments, |
| 148 messageKind, messageArguments, typeName.source, | 133 typeName.source, visitor.enclosingElement); |
| 149 visitor.enclosingElement); | |
| 150 } | 134 } |
| 151 List<DartType> arguments = <DartType>[]; | 135 List<DartType> arguments = <DartType>[]; |
| 152 resolveTypeArguments(visitor, node, const <DartType>[], arguments); | 136 resolveTypeArguments(visitor, node, const <DartType>[], arguments); |
| 153 return new MalformedType(erroneousElement, | 137 return new MalformedType( |
| 154 userProvidedBadType, arguments); | 138 erroneousElement, userProvidedBadType, arguments); |
| 155 } | 139 } |
| 156 | 140 |
| 157 // Try to construct the type from the element. | 141 // Try to construct the type from the element. |
| 158 if (element == null) { | 142 if (element == null) { |
| 159 type = reportFailureAndCreateType( | 143 type = reportFailureAndCreateType( |
| 160 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); | 144 MessageKind.CANNOT_RESOLVE_TYPE, {'typeName': node.typeName}); |
| 161 } else if (element.isAmbiguous) { | 145 } else if (element.isAmbiguous) { |
| 162 AmbiguousElement ambiguous = element; | 146 AmbiguousElement ambiguous = element; |
| 163 type = reportFailureAndCreateType( | 147 type = reportFailureAndCreateType( |
| 164 ambiguous.messageKind, | 148 ambiguous.messageKind, ambiguous.messageArguments, |
| 165 ambiguous.messageArguments, | |
| 166 infos: ambiguous.computeInfos( | 149 infos: ambiguous.computeInfos( |
| 167 registry.mapping.analyzedElement, reporter)); | 150 registry.mapping.analyzedElement, reporter)); |
| 168 ; | 151 ; |
| 169 } else if (element.isMalformed) { | 152 } else if (element.isMalformed) { |
| 170 if (element is ErroneousElement) { | 153 if (element is ErroneousElement) { |
| 171 type = reportFailureAndCreateType( | 154 type = reportFailureAndCreateType( |
| 172 element.messageKind, element.messageArguments, | 155 element.messageKind, element.messageArguments, |
| 173 erroneousElement: element); | 156 erroneousElement: element); |
| 174 } else { | 157 } else { |
| 175 type = const DynamicType(); | 158 type = const DynamicType(); |
| 176 } | 159 } |
| 177 } else if (!element.impliesType) { | 160 } else if (!element.impliesType) { |
| 178 type = reportFailureAndCreateType( | 161 type = reportFailureAndCreateType( |
| 179 MessageKind.NOT_A_TYPE, {'node': node.typeName}); | 162 MessageKind.NOT_A_TYPE, {'node': node.typeName}); |
| 180 } else { | 163 } else { |
| 181 bool addTypeVariableBoundsCheck = false; | 164 bool addTypeVariableBoundsCheck = false; |
| 182 if (element.isClass) { | 165 if (element.isClass) { |
| 183 ClassElement cls = element; | 166 ClassElement cls = element; |
| 184 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply | 167 // TODO(johnniwinther): [ensureClassWillBeResolvedInternal] should imply |
| 185 // [computeType]. | 168 // [computeType]. |
| 186 compiler.resolver.ensureClassWillBeResolvedInternal(cls); | 169 compiler.resolver.ensureClassWillBeResolvedInternal(cls); |
| 187 cls.computeType(resolution); | 170 cls.computeType(resolution); |
| 188 List<DartType> arguments = <DartType>[]; | 171 List<DartType> arguments = <DartType>[]; |
| 189 bool hasTypeArgumentMismatch = resolveTypeArguments( | 172 bool hasTypeArgumentMismatch = |
| 190 visitor, node, cls.typeVariables, arguments); | 173 resolveTypeArguments(visitor, node, cls.typeVariables, arguments); |
| 191 if (hasTypeArgumentMismatch) { | 174 if (hasTypeArgumentMismatch) { |
| 192 type = new BadInterfaceType(cls.declaration, | 175 type = new BadInterfaceType( |
| 193 new InterfaceType.forUserProvidedBadType(cls.declaration, | 176 cls.declaration, |
| 194 arguments)); | 177 new InterfaceType.forUserProvidedBadType( |
| 178 cls.declaration, arguments)); |
| 195 } else { | 179 } else { |
| 196 if (arguments.isEmpty) { | 180 if (arguments.isEmpty) { |
| 197 type = cls.rawType; | 181 type = cls.rawType; |
| 198 } else { | 182 } else { |
| 199 type = new InterfaceType( | 183 type = new InterfaceType( |
| 200 cls.declaration, arguments.toList(growable: false)); | 184 cls.declaration, arguments.toList(growable: false)); |
| 201 addTypeVariableBoundsCheck = true; | 185 addTypeVariableBoundsCheck = true; |
| 202 } | 186 } |
| 203 } | 187 } |
| 204 } else if (element.isTypedef) { | 188 } else if (element.isTypedef) { |
| (...skipping 25 matching lines...) Expand all Loading... |
| 230 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); | 214 registry.registerFeature(Feature.THROW_RUNTIME_ERROR); |
| 231 type = reportFailureAndCreateType( | 215 type = reportFailureAndCreateType( |
| 232 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | 216 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
| 233 {'typeVariableName': node}, | 217 {'typeVariableName': node}, |
| 234 userProvidedBadType: typeVariable.type); | 218 userProvidedBadType: typeVariable.type); |
| 235 } else { | 219 } else { |
| 236 type = typeVariable.type; | 220 type = typeVariable.type; |
| 237 } | 221 } |
| 238 type = checkNoTypeArguments(type); | 222 type = checkNoTypeArguments(type); |
| 239 } else { | 223 } else { |
| 240 reporter.internalError(node, | 224 reporter.internalError( |
| 241 "Unexpected element kind ${element.kind}."); | 225 node, "Unexpected element kind ${element.kind}."); |
| 242 } | 226 } |
| 243 if (addTypeVariableBoundsCheck) { | 227 if (addTypeVariableBoundsCheck) { |
| 244 registry.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); | 228 registry.registerFeature(Feature.TYPE_VARIABLE_BOUNDS_CHECK); |
| 245 visitor.addDeferredAction( | 229 visitor.addDeferredAction(visitor.enclosingElement, |
| 246 visitor.enclosingElement, | |
| 247 () => checkTypeVariableBounds(node, type)); | 230 () => checkTypeVariableBounds(node, type)); |
| 248 } | 231 } |
| 249 } | 232 } |
| 250 registry.useType(node, type); | 233 registry.useType(node, type); |
| 251 return type; | 234 return type; |
| 252 } | 235 } |
| 253 | 236 |
| 254 /// Checks the type arguments of [type] against the type variable bounds. | 237 /// Checks the type arguments of [type] against the type variable bounds. |
| 255 void checkTypeVariableBounds(TypeAnnotation node, GenericType type) { | 238 void checkTypeVariableBounds(TypeAnnotation node, GenericType type) { |
| 256 void checkTypeVariableBound(_, DartType typeArgument, | 239 void checkTypeVariableBound(_, DartType typeArgument, |
| 257 TypeVariableType typeVariable, | 240 TypeVariableType typeVariable, DartType bound) { |
| 258 DartType bound) { | |
| 259 if (!compiler.types.isSubtype(typeArgument, bound)) { | 241 if (!compiler.types.isSubtype(typeArgument, bound)) { |
| 260 reporter.reportWarningMessage( | 242 reporter.reportWarningMessage( |
| 261 node, | 243 node, MessageKind.INVALID_TYPE_VARIABLE_BOUND, { |
| 262 MessageKind.INVALID_TYPE_VARIABLE_BOUND, | 244 'typeVariable': typeVariable, |
| 263 {'typeVariable': typeVariable, | 245 'bound': bound, |
| 264 'bound': bound, | 246 'typeArgument': typeArgument, |
| 265 'typeArgument': typeArgument, | 247 'thisType': type.element.thisType |
| 266 'thisType': type.element.thisType}); | 248 }); |
| 267 } | 249 } |
| 268 }; | 250 } |
| 251 ; |
| 269 | 252 |
| 270 compiler.types.checkTypeVariableBounds(type, checkTypeVariableBound); | 253 compiler.types.checkTypeVariableBounds(type, checkTypeVariableBound); |
| 271 } | 254 } |
| 272 | 255 |
| 273 /** | 256 /** |
| 274 * Resolves the type arguments of [node] and adds these to [arguments]. | 257 * Resolves the type arguments of [node] and adds these to [arguments]. |
| 275 * | 258 * |
| 276 * Returns [: true :] if the number of type arguments did not match the | 259 * Returns [: true :] if the number of type arguments did not match the |
| 277 * number of type variables. | 260 * number of type variables. |
| 278 */ | 261 */ |
| 279 bool resolveTypeArguments(MappingVisitor visitor, | 262 bool resolveTypeArguments(MappingVisitor visitor, TypeAnnotation node, |
| 280 TypeAnnotation node, | 263 List<DartType> typeVariables, List<DartType> arguments) { |
| 281 List<DartType> typeVariables, | |
| 282 List<DartType> arguments) { | |
| 283 if (node.typeArguments == null) { | 264 if (node.typeArguments == null) { |
| 284 return false; | 265 return false; |
| 285 } | 266 } |
| 286 int expectedVariables = typeVariables.length; | 267 int expectedVariables = typeVariables.length; |
| 287 int index = 0; | 268 int index = 0; |
| 288 bool typeArgumentCountMismatch = false; | 269 bool typeArgumentCountMismatch = false; |
| 289 for (Link<Node> typeArguments = node.typeArguments.nodes; | 270 for (Link<Node> typeArguments = node.typeArguments.nodes; |
| 290 !typeArguments.isEmpty; | 271 !typeArguments.isEmpty; |
| 291 typeArguments = typeArguments.tail, index++) { | 272 typeArguments = typeArguments.tail, index++) { |
| 292 if (index > expectedVariables - 1) { | 273 if (index > expectedVariables - 1) { |
| 293 reporter.reportWarningMessage( | 274 reporter.reportWarningMessage( |
| 294 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 275 typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| 295 typeArgumentCountMismatch = true; | 276 typeArgumentCountMismatch = true; |
| 296 } | 277 } |
| 297 DartType argType = resolveTypeAnnotation(visitor, typeArguments.head); | 278 DartType argType = resolveTypeAnnotation(visitor, typeArguments.head); |
| 298 // TODO(karlklose): rewrite to not modify [arguments]. | 279 // TODO(karlklose): rewrite to not modify [arguments]. |
| 299 arguments.add(argType); | 280 arguments.add(argType); |
| 300 } | 281 } |
| 301 if (index < expectedVariables) { | 282 if (index < expectedVariables) { |
| 302 reporter.reportWarningMessage( | 283 reporter.reportWarningMessage( |
| 303 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 284 node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
| 304 typeArgumentCountMismatch = true; | 285 typeArgumentCountMismatch = true; |
| 305 } | 286 } |
| 306 return typeArgumentCountMismatch; | 287 return typeArgumentCountMismatch; |
| 307 } | 288 } |
| 308 } | 289 } |
| OLD | NEW |