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 part of resolution; | 5 part of resolution; |
6 | 6 |
7 abstract class TreeElements { | 7 abstract class TreeElements { |
8 Element operator[](Node node); | 8 Element operator[](Node node); |
9 Selector getSelector(Send send); | 9 Selector getSelector(Send send); |
10 DartType getType(Node node); | 10 DartType getType(Node node); |
(...skipping 1020 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1031 breakTargetStack = breakTargetStack.tail; | 1031 breakTargetStack = breakTargetStack.tail; |
1032 labels = labels.outer; | 1032 labels = labels.outer; |
1033 } | 1033 } |
1034 } | 1034 } |
1035 | 1035 |
1036 class TypeResolver { | 1036 class TypeResolver { |
1037 final Compiler compiler; | 1037 final Compiler compiler; |
1038 | 1038 |
1039 TypeResolver(this.compiler); | 1039 TypeResolver(this.compiler); |
1040 | 1040 |
1041 bool anyMalformedTypesInThere(Link<DartType> list) { | |
ngeoffray
2012/11/27 09:37:35
Personal taste, but I would remove 'InThere'.
aam-me
2012/11/28 01:49:47
I understand. No objections to this.
| |
1042 for (Link<DartType> link = list; | |
1043 !link.isEmpty; | |
1044 link = link.tail) { | |
1045 DartType dtype = link.head; | |
1046 if (dtype is MalformedType) { | |
1047 return true; | |
1048 } | |
1049 } | |
1050 return false; | |
1051 } | |
1052 | |
1041 Element resolveTypeName(Scope scope, TypeAnnotation node) { | 1053 Element resolveTypeName(Scope scope, TypeAnnotation node) { |
1042 Identifier typeName = node.typeName.asIdentifier(); | 1054 Identifier typeName = node.typeName.asIdentifier(); |
1043 Send send = node.typeName.asSend(); | 1055 Send send = node.typeName.asSend(); |
1044 return resolveTypeNameInternal(scope, typeName, send); | 1056 return resolveTypeNameInternal(scope, typeName, send); |
1045 } | 1057 } |
1046 | 1058 |
1047 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) { | 1059 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) { |
1048 if (send != null) { | 1060 if (send != null) { |
1049 typeName = send.selector; | 1061 typeName = send.selector; |
1050 } | 1062 } |
(...skipping 23 matching lines...) Expand all Loading... | |
1074 } | 1086 } |
1075 } | 1087 } |
1076 | 1088 |
1077 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean | 1089 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean |
1078 // flags instead of closures. | 1090 // flags instead of closures. |
1079 // TODO(johnniwinther): Should never return [null] but instead an erroneous | 1091 // TODO(johnniwinther): Should never return [null] but instead an erroneous |
1080 // type. | 1092 // type. |
1081 DartType resolveTypeAnnotation( | 1093 DartType resolveTypeAnnotation( |
1082 TypeAnnotation node, | 1094 TypeAnnotation node, |
1083 Scope scope, | 1095 Scope scope, |
1096 bool inStaticContext, | |
1084 {onFailure(Node node, MessageKind kind, [List arguments]), | 1097 {onFailure(Node node, MessageKind kind, [List arguments]), |
1085 whenResolved(Node node, DartType type)}) { | 1098 whenResolved(Node node, DartType type)}) { |
1086 if (onFailure == null) { | 1099 if (onFailure == null) { |
1087 onFailure = (n, k, [arguments]) {}; | 1100 onFailure = (n, k, [arguments]) {}; |
1088 } | 1101 } |
1089 if (whenResolved == null) { | 1102 if (whenResolved == null) { |
1090 whenResolved = (n, t) {}; | 1103 whenResolved = (n, t) {}; |
1091 } | 1104 } |
1092 if (scope == null) { | 1105 if (scope == null) { |
1093 compiler.internalError('resolveTypeAnnotation: no scope specified'); | 1106 compiler.internalError('resolveTypeAnnotation: no scope specified'); |
1094 } | 1107 } |
1095 return resolveTypeAnnotationInContext(scope, node, onFailure, | 1108 return resolveTypeAnnotationInContext(scope, node, inStaticContext, |
1096 whenResolved); | 1109 onFailure, whenResolved); |
1097 } | 1110 } |
1098 | 1111 |
1099 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, | 1112 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, |
1113 bool inStaticContext, | |
1100 onFailure, whenResolved) { | 1114 onFailure, whenResolved) { |
1101 Element element = resolveTypeName(scope, node); | 1115 Element element = resolveTypeName(scope, node); |
1102 DartType type; | 1116 DartType type; |
1103 if (element == null) { | 1117 if (element == null) { |
1104 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); | 1118 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); |
1105 } else if (element.isAmbiguous()) { | 1119 } else if (element.isAmbiguous()) { |
1106 AmbiguousElement ambiguous = element; | 1120 AmbiguousElement ambiguous = element; |
1107 onFailure(node, ambiguous.messageKind, ambiguous.messageArguments); | 1121 onFailure(node, ambiguous.messageKind, ambiguous.messageArguments); |
1108 } else if (!element.impliesType()) { | 1122 } else if (!element.impliesType()) { |
1109 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); | 1123 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); |
1110 } else { | 1124 } else { |
1111 if (identical(element, compiler.types.voidType.element) || | 1125 if (identical(element, compiler.types.voidType.element) || |
1112 identical(element, compiler.types.dynamicType.element)) { | 1126 identical(element, compiler.types.dynamicType.element)) { |
1113 type = element.computeType(compiler); | 1127 type = element.computeType(compiler); |
1114 } else if (element.isClass()) { | 1128 } else if (element.isClass()) { |
1115 ClassElement cls = element; | 1129 ClassElement cls = element; |
1116 cls.ensureResolved(compiler); | 1130 cls.ensureResolved(compiler); |
1117 Link<DartType> arguments = | 1131 Link<DartType> arguments = |
1118 resolveTypeArguments(node, cls.typeVariables, scope, | 1132 resolveTypeArguments(node, cls.typeVariables, |
1133 inStaticContext, scope, | |
1119 onFailure, whenResolved); | 1134 onFailure, whenResolved); |
1120 if (cls.typeVariables.isEmpty && arguments.isEmpty) { | 1135 if (cls.typeVariables.isEmpty && arguments.isEmpty) { |
1121 // Use the canonical type if it has no type parameters. | 1136 // Use the canonical type if it has no type parameters. |
1122 type = cls.computeType(compiler); | 1137 type = cls.computeType(compiler); |
1123 } else { | 1138 } else { |
1124 type = new InterfaceType(cls.declaration, arguments); | 1139 // In checked mode malformed-ness of the type argument bubbles up. |
ngeoffray
2012/11/27 09:37:35
Why not in non-checked mode? Is that an optimizati
aam-me
2012/11/28 01:49:47
When we produce MalformedTypeElement here, it trig
ahe
2012/11/28 02:08:50
I think what Nicolas is saying is that we generall
| |
1140 if (anyMalformedTypesInThere(arguments) && | |
1141 compiler.enableTypeAssertions) { | |
1142 type = new MalformedType( | |
1143 new MalformedTypeElement(node, element)); | |
1144 } else { | |
1145 type = new InterfaceType(cls.declaration, arguments); | |
1146 } | |
1125 } | 1147 } |
1126 } else if (element.isTypedef()) { | 1148 } else if (element.isTypedef()) { |
1127 TypedefElement typdef = element; | 1149 TypedefElement typdef = element; |
1128 // TODO(ahe): Should be [ensureResolved]. | 1150 // TODO(ahe): Should be [ensureResolved]. |
1129 compiler.resolveTypedef(typdef); | 1151 compiler.resolveTypedef(typdef); |
1130 typdef.computeType(compiler); | 1152 typdef.computeType(compiler); |
1131 Link<DartType> arguments = resolveTypeArguments( | 1153 Link<DartType> arguments = resolveTypeArguments( |
1132 node, typdef.typeVariables, | 1154 node, typdef.typeVariables, inStaticContext, |
1133 scope, onFailure, whenResolved); | 1155 scope, onFailure, whenResolved); |
1134 if (typdef.typeVariables.isEmpty && arguments.isEmpty) { | 1156 if (typdef.typeVariables.isEmpty && arguments.isEmpty) { |
1135 // Return the canonical type if it has no type parameters. | 1157 // Return the canonical type if it has no type parameters. |
1136 type = typdef.computeType(compiler); | 1158 type = typdef.computeType(compiler); |
1137 } else { | 1159 } else { |
1138 type = new TypedefType(typdef, arguments); | 1160 type = new TypedefType(typdef, arguments); |
1139 } | 1161 } |
1140 } else if (element.isTypeVariable()) { | 1162 } else if (element.isTypeVariable()) { |
1141 type = element.computeType(compiler); | 1163 if (inStaticContext) { |
1164 compiler.reportWarning(node, | |
1165 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( | |
1166 [element])); | |
1167 type = new MalformedType(new MalformedTypeElement(node, element)); | |
1168 } else { | |
1169 type = element.computeType(compiler); | |
1170 } | |
1142 } else { | 1171 } else { |
1143 compiler.cancel("unexpected element kind ${element.kind}", | 1172 compiler.cancel("unexpected element kind ${element.kind}", |
1144 node: node); | 1173 node: node); |
1145 } | 1174 } |
1146 } | 1175 } |
1147 whenResolved(node, type); | 1176 whenResolved(node, type); |
1148 return type; | 1177 return type; |
1149 } | 1178 } |
1150 | 1179 |
1151 Link<DartType> resolveTypeArguments(TypeAnnotation node, | 1180 Link<DartType> resolveTypeArguments(TypeAnnotation node, |
1152 Link<DartType> typeVariables, | 1181 Link<DartType> typeVariables, |
1182 bool inStaticContext, | |
1153 Scope scope, onFailure, whenResolved) { | 1183 Scope scope, onFailure, whenResolved) { |
1154 if (node.typeArguments == null) { | 1184 if (node.typeArguments == null) { |
1155 return const Link<DartType>(); | 1185 return const Link<DartType>(); |
1156 } | 1186 } |
1157 var arguments = new LinkBuilder<DartType>(); | 1187 var arguments = new LinkBuilder<DartType>(); |
1158 for (Link<Node> typeArguments = node.typeArguments.nodes; | 1188 for (Link<Node> typeArguments = node.typeArguments.nodes; |
1159 !typeArguments.isEmpty; | 1189 !typeArguments.isEmpty; |
1160 typeArguments = typeArguments.tail) { | 1190 typeArguments = typeArguments.tail) { |
1161 if (typeVariables.isEmpty) { | 1191 if (typeVariables.isEmpty) { |
1162 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 1192 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
1163 } | 1193 } |
1164 DartType argType = resolveTypeAnnotationInContext(scope, | 1194 DartType argType = resolveTypeAnnotationInContext(scope, |
1165 typeArguments.head, | 1195 typeArguments.head, |
1196 inStaticContext, | |
1166 onFailure, | 1197 onFailure, |
1167 whenResolved); | 1198 whenResolved); |
1168 arguments.addLast(argType); | 1199 arguments.addLast(argType); |
1169 if (!typeVariables.isEmpty) { | 1200 if (!typeVariables.isEmpty) { |
1170 typeVariables = typeVariables.tail; | 1201 typeVariables = typeVariables.tail; |
1171 } | 1202 } |
1172 } | 1203 } |
1173 if (!typeVariables.isEmpty) { | 1204 if (!typeVariables.isEmpty) { |
1174 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 1205 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
1175 } | 1206 } |
(...skipping 874 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2050 argument.element.enclosingElement); | 2081 argument.element.enclosingElement); |
2051 } else if (argument is InterfaceType) { | 2082 } else if (argument is InterfaceType) { |
2052 InterfaceType type = argument; | 2083 InterfaceType type = argument; |
2053 type.arguments.forEach((DartType argument) { | 2084 type.arguments.forEach((DartType argument) { |
2054 analyzeTypeArgument(type, argument); | 2085 analyzeTypeArgument(type, argument); |
2055 }); | 2086 }); |
2056 } | 2087 } |
2057 } | 2088 } |
2058 | 2089 |
2059 DartType resolveTypeAnnotation(TypeAnnotation node) { | 2090 DartType resolveTypeAnnotation(TypeAnnotation node) { |
2060 // TODO(johnniwinther): Remove this together with the named arguments | |
2061 // on [TypeResolver.resolveTypeAnnotation]. | |
2062 void checkAndUseType(TypeAnnotation annotation, DartType type) { | |
2063 useType(annotation, type); | |
2064 if (type != null && | |
2065 identical(type.kind, TypeKind.TYPE_VARIABLE) && | |
2066 enclosingElement.isInStaticMember()) { | |
2067 warning(annotation, MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, | |
2068 [type]); | |
2069 } | |
2070 } | |
2071 | |
2072 Function report = typeRequired ? error : warning; | 2091 Function report = typeRequired ? error : warning; |
2073 DartType type = typeResolver.resolveTypeAnnotation( | 2092 DartType type = typeResolver.resolveTypeAnnotation( |
2074 node, scope, onFailure: report, whenResolved: checkAndUseType); | 2093 node, scope, enclosingElement.isInStaticMember(), |
2094 onFailure: report, whenResolved: useType); | |
2075 if (type == null) return null; | 2095 if (type == null) return null; |
2076 if (inCheckContext) { | 2096 if (inCheckContext) { |
2077 compiler.enqueuer.resolution.registerIsCheck(type); | 2097 compiler.enqueuer.resolution.registerIsCheck(type); |
2078 } | 2098 } |
2079 if (typeRequired || inCheckContext) { | 2099 if (typeRequired || inCheckContext) { |
2080 if (type is InterfaceType) { | 2100 if (type is InterfaceType) { |
2081 InterfaceType itf = type; | 2101 InterfaceType itf = type; |
2082 itf.arguments.forEach((DartType argument) { | 2102 itf.arguments.forEach((DartType argument) { |
2083 analyzeTypeArgument(type, argument); | 2103 analyzeTypeArgument(type, argument); |
2084 }); | 2104 }); |
(...skipping 346 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2431 SourceString typeName = typeVariable.name; | 2451 SourceString typeName = typeVariable.name; |
2432 TypeVariable typeNode = nodeLink.head; | 2452 TypeVariable typeNode = nodeLink.head; |
2433 if (nameSet.contains(typeName)) { | 2453 if (nameSet.contains(typeName)) { |
2434 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]); | 2454 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]); |
2435 } | 2455 } |
2436 nameSet.add(typeName); | 2456 nameSet.add(typeName); |
2437 | 2457 |
2438 TypeVariableElement variableElement = typeVariable.element; | 2458 TypeVariableElement variableElement = typeVariable.element; |
2439 if (typeNode.bound != null) { | 2459 if (typeNode.bound != null) { |
2440 DartType boundType = typeResolver.resolveTypeAnnotation( | 2460 DartType boundType = typeResolver.resolveTypeAnnotation( |
2441 typeNode.bound, scope, onFailure: warning); | 2461 typeNode.bound, scope, element.isInStaticMember(), |
2462 onFailure: warning); | |
2442 if (boundType != null && boundType.element == variableElement) { | 2463 if (boundType != null && boundType.element == variableElement) { |
2443 // TODO(johnniwinther): Check for more general cycles, like | 2464 // TODO(johnniwinther): Check for more general cycles, like |
2444 // [: <A extends B, B extends C, C extends B> :]. | 2465 // [: <A extends B, B extends C, C extends B> :]. |
2445 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, | 2466 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, |
2446 [variableElement.name]); | 2467 [variableElement.name]); |
2447 } else if (boundType != null) { | 2468 } else if (boundType != null) { |
2448 variableElement.bound = boundType; | 2469 variableElement.bound = boundType; |
2449 } else { | 2470 } else { |
2450 // TODO(johnniwinther): Should be an erroneous type. | 2471 // TODO(johnniwinther): Should be an erroneous type. |
2451 variableElement.bound = compiler.objectClass.computeType(compiler); | 2472 variableElement.bound = compiler.objectClass.computeType(compiler); |
(...skipping 667 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
3119 return e; | 3140 return e; |
3120 } | 3141 } |
3121 | 3142 |
3122 /// Assumed to be called by [resolveRedirectingFactory]. | 3143 /// Assumed to be called by [resolveRedirectingFactory]. |
3123 Element visitReturn(Return node) { | 3144 Element visitReturn(Return node) { |
3124 Node expression = node.expression; | 3145 Node expression = node.expression; |
3125 return finishConstructorReference(visit(expression), | 3146 return finishConstructorReference(visit(expression), |
3126 expression, expression); | 3147 expression, expression); |
3127 } | 3148 } |
3128 } | 3149 } |
OLD | NEW |