| 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 anyMalformedTypes(Link<DartType> list) { | 1041 Element resolveTypeName(Scope scope, |
| 1042 for (Link<DartType> link = list; | 1042 SourceString prefixName, |
| 1043 !link.isEmpty; | 1043 Identifier typeName) { |
| 1044 link = link.tail) { | 1044 if (prefixName != null) { |
| 1045 DartType dtype = link.head; | 1045 Element e = scope.lookup(prefixName); |
| 1046 if (dtype is MalformedType) { | 1046 if (e != null) { |
| 1047 return true; | 1047 if (identical(e.kind, ElementKind.PREFIX)) { |
| 1048 } | 1048 // The receiver is a prefix. Lookup in the imported members. |
| 1049 } | 1049 PrefixElement prefix = e; |
| 1050 return false; | 1050 return prefix.lookupLocalMember(typeName.source); |
| 1051 } | 1051 } else if (identical(e.kind, ElementKind.CLASS)) { |
| 1052 | 1052 // TODO(johnniwinther): Remove this case. |
| 1053 Element resolveTypeName(Scope scope, TypeAnnotation node) { | 1053 // The receiver is the class part of a named constructor. |
| 1054 Identifier typeName = node.typeName.asIdentifier(); | 1054 return e; |
| 1055 Send send = node.typeName.asSend(); | 1055 } |
| 1056 return resolveTypeNameInternal(scope, typeName, send); | |
| 1057 } | |
| 1058 | |
| 1059 Element resolveTypeNameInternal(Scope scope, Identifier typeName, Send send) { | |
| 1060 if (send != null) { | |
| 1061 typeName = send.selector; | |
| 1062 } | |
| 1063 String stringValue = typeName.source.stringValue; | |
| 1064 if (identical(stringValue, 'void')) { | |
| 1065 return compiler.types.voidType.element; | |
| 1066 } else if (identical(stringValue, 'Dynamic')) { | |
| 1067 // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support. | |
| 1068 compiler.onDeprecatedFeature(typeName, 'Dynamic'); | |
| 1069 return compiler.dynamicClass; | |
| 1070 } else if (identical(stringValue, 'dynamic')) { | |
| 1071 return compiler.dynamicClass; | |
| 1072 } else if (send != null) { | |
| 1073 Element e = scope.lookup(send.receiver.asIdentifier().source); | |
| 1074 if (e != null && identical(e.kind, ElementKind.PREFIX)) { | |
| 1075 // The receiver is a prefix. Lookup in the imported members. | |
| 1076 PrefixElement prefix = e; | |
| 1077 return prefix.lookupLocalMember(typeName.source); | |
| 1078 } else if (e != null && identical(e.kind, ElementKind.CLASS)) { | |
| 1079 // The receiver is the class part of a named constructor. | |
| 1080 return e; | |
| 1081 } else { | 1056 } else { |
| 1057 // The caller creates the ErroneousElement for the MalformedType. |
| 1082 return null; | 1058 return null; |
| 1083 } | 1059 } |
| 1084 } else { | 1060 } else { |
| 1085 return scope.lookup(typeName.source); | 1061 String stringValue = typeName.source.stringValue; |
| 1062 if (identical(stringValue, 'void')) { |
| 1063 return compiler.types.voidType.element; |
| 1064 } else if (identical(stringValue, 'Dynamic')) { |
| 1065 // TODO(aprelev@gmail.com): Remove deprecated Dynamic keyword support. |
| 1066 compiler.onDeprecatedFeature(typeName, 'Dynamic'); |
| 1067 return compiler.dynamicClass; |
| 1068 } else if (identical(stringValue, 'dynamic')) { |
| 1069 return compiler.dynamicClass; |
| 1070 } else { |
| 1071 return scope.lookup(typeName.source); |
| 1072 } |
| 1086 } | 1073 } |
| 1087 } | 1074 } |
| 1088 | 1075 |
| 1089 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean | 1076 // TODO(johnniwinther): Change [onFailure] and [whenResolved] to use boolean |
| 1090 // flags instead of closures. | 1077 // flags instead of closures. |
| 1091 // TODO(johnniwinther): Should never return [null] but instead an erroneous | |
| 1092 // type. | |
| 1093 DartType resolveTypeAnnotation( | 1078 DartType resolveTypeAnnotation( |
| 1094 TypeAnnotation node, | 1079 TypeAnnotation node, |
| 1095 Scope scope, | 1080 Scope scope, |
| 1096 bool inStaticContext, | 1081 Element enclosingElement, |
| 1097 {onFailure(Node node, MessageKind kind, [List arguments]), | 1082 {onFailure(Node node, MessageKind kind, [List arguments]), |
| 1098 whenResolved(Node node, DartType type)}) { | 1083 whenResolved(Node node, DartType type)}) { |
| 1099 if (onFailure == null) { | 1084 if (onFailure == null) { |
| 1100 onFailure = (n, k, [arguments]) {}; | 1085 onFailure = (n, k, [arguments]) {}; |
| 1101 } | 1086 } |
| 1102 if (whenResolved == null) { | 1087 if (whenResolved == null) { |
| 1103 whenResolved = (n, t) {}; | 1088 whenResolved = (n, t) {}; |
| 1104 } | 1089 } |
| 1105 if (scope == null) { | 1090 if (scope == null) { |
| 1106 compiler.internalError('resolveTypeAnnotation: no scope specified'); | 1091 compiler.internalError('resolveTypeAnnotation: no scope specified'); |
| 1107 } | 1092 } |
| 1108 return resolveTypeAnnotationInContext(scope, node, inStaticContext, | 1093 return resolveTypeAnnotationInContext(scope, node, enclosingElement, |
| 1109 onFailure, whenResolved); | 1094 onFailure, whenResolved); |
| 1110 } | 1095 } |
| 1111 | 1096 |
| 1112 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, | 1097 DartType resolveTypeAnnotationInContext(Scope scope, TypeAnnotation node, |
| 1113 bool inStaticContext, | 1098 Element enclosingElement, |
| 1114 onFailure, whenResolved) { | 1099 onFailure, whenResolved) { |
| 1115 Element element = resolveTypeName(scope, node); | 1100 Identifier typeName; |
| 1101 SourceString prefixName; |
| 1102 Send send = node.typeName.asSend(); |
| 1103 if (send != null) { |
| 1104 // The type name is of the form [: prefix . identifier :]. |
| 1105 prefixName = send.receiver.asIdentifier().source; |
| 1106 typeName = send.selector.asIdentifier(); |
| 1107 } else { |
| 1108 typeName = node.typeName.asIdentifier(); |
| 1109 } |
| 1110 |
| 1111 Element element = resolveTypeName(scope, prefixName, typeName); |
| 1116 DartType type; | 1112 DartType type; |
| 1113 |
| 1114 DartType reportFailureAndCreateType(MessageKind messageKind, |
| 1115 List messageArguments) { |
| 1116 onFailure(node, messageKind, messageArguments); |
| 1117 var erroneousElement = new ErroneousElement( |
| 1118 messageKind, messageArguments, typeName.source, enclosingElement); |
| 1119 var arguments = new LinkBuilder<DartType>(); |
| 1120 resolveTypeArguments( |
| 1121 node, null, enclosingElement, |
| 1122 scope, onFailure, whenResolved, arguments); |
| 1123 return new MalformedType(erroneousElement, null, arguments.toLink()); |
| 1124 } |
| 1125 |
| 1126 DartType checkNoTypeArguments(DartType type) { |
| 1127 var arguments = new LinkBuilder<DartType>(); |
| 1128 bool hashTypeArgumentMismatch = resolveTypeArguments( |
| 1129 node, const Link<DartType>(), enclosingElement, |
| 1130 scope, onFailure, whenResolved, arguments); |
| 1131 if (hashTypeArgumentMismatch) { |
| 1132 type = new MalformedType( |
| 1133 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
| 1134 [node], typeName.source, enclosingElement), |
| 1135 type, arguments.toLink()); |
| 1136 } |
| 1137 return type; |
| 1138 } |
| 1139 |
| 1117 if (element == null) { | 1140 if (element == null) { |
| 1118 onFailure(node, MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); | 1141 type = reportFailureAndCreateType( |
| 1142 MessageKind.CANNOT_RESOLVE_TYPE, [node.typeName]); |
| 1119 } else if (element.isAmbiguous()) { | 1143 } else if (element.isAmbiguous()) { |
| 1120 AmbiguousElement ambiguous = element; | 1144 AmbiguousElement ambiguous = element; |
| 1121 onFailure(node, ambiguous.messageKind, ambiguous.messageArguments); | 1145 type = reportFailureAndCreateType( |
| 1146 ambiguous.messageKind, ambiguous.messageArguments); |
| 1122 } else if (!element.impliesType()) { | 1147 } else if (!element.impliesType()) { |
| 1123 onFailure(node, MessageKind.NOT_A_TYPE, [node.typeName]); | 1148 type = reportFailureAndCreateType( |
| 1149 MessageKind.NOT_A_TYPE, [node.typeName]); |
| 1124 } else { | 1150 } else { |
| 1125 if (identical(element, compiler.types.voidType.element) || | 1151 if (identical(element, compiler.types.voidType.element) || |
| 1126 identical(element, compiler.types.dynamicType.element)) { | 1152 identical(element, compiler.types.dynamicType.element)) { |
| 1127 type = element.computeType(compiler); | 1153 type = checkNoTypeArguments(element.computeType(compiler)); |
| 1128 } else if (element.isClass()) { | 1154 } else if (element.isClass()) { |
| 1129 ClassElement cls = element; | 1155 ClassElement cls = element; |
| 1130 cls.ensureResolved(compiler); | 1156 cls.ensureResolved(compiler); |
| 1131 Link<DartType> arguments = | 1157 var arguments = new LinkBuilder<DartType>(); |
| 1132 resolveTypeArguments(node, cls.typeVariables, | 1158 bool hashTypeArgumentMismatch = resolveTypeArguments( |
| 1133 inStaticContext, scope, | 1159 node, cls.typeVariables, enclosingElement, |
| 1134 onFailure, whenResolved); | 1160 scope, onFailure, whenResolved, arguments); |
| 1135 if (cls.typeVariables.isEmpty && arguments.isEmpty) { | 1161 if (hashTypeArgumentMismatch) { |
| 1136 // Use the canonical type if it has no type parameters. | 1162 type = new MalformedType( |
| 1137 type = cls.computeType(compiler); | 1163 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
| 1164 [node], typeName.source, enclosingElement), |
| 1165 new InterfaceType(cls.declaration, arguments.toLink())); |
| 1138 } else { | 1166 } else { |
| 1139 if (anyMalformedTypes(arguments)) { | 1167 if (arguments.isEmpty) { |
| 1140 // Build interface type (with malformed arguments in it) and | 1168 type = cls.rawType; |
| 1141 // call [whenResolved] to let [ConstructorResolver] create | |
| 1142 // constructor selectors, which are used by | |
| 1143 // [SsaBuilder.visitNewSend] to figure out what class needs | |
| 1144 // to be built. | |
| 1145 whenResolved(node, | |
| 1146 new InterfaceType(cls.declaration, arguments)); | |
| 1147 // Return malformed type element below so that | |
| 1148 // [ConstructorResolver.visitTypeAnnotation] gets [:MalformedType:] | |
| 1149 // and can map (via resolver.mapping) NewExpression node to | |
| 1150 // this malformed type. | |
| 1151 // [SsaBuilder.visitNewExpression] picks up the fact that | |
| 1152 // NewExpression is mapped to malformed type and generates | |
| 1153 // runtime error in checked mode. | |
| 1154 type = new MalformedType(new MalformedTypeElement(node, element)); | |
| 1155 return type; | |
| 1156 } else { | 1169 } else { |
| 1157 if (arguments.isEmpty) { | 1170 type = new InterfaceType(cls.declaration, arguments.toLink()); |
| 1158 // Use the canonical raw type if the class is generic. | |
| 1159 type = cls.rawType; | |
| 1160 } else { | |
| 1161 type = new InterfaceType(cls.declaration, arguments); | |
| 1162 } | |
| 1163 } | 1171 } |
| 1164 } | 1172 } |
| 1165 } else if (element.isTypedef()) { | 1173 } else if (element.isTypedef()) { |
| 1166 TypedefElement typdef = element; | 1174 TypedefElement typdef = element; |
| 1167 // TODO(ahe): Should be [ensureResolved]. | 1175 // TODO(ahe): Should be [ensureResolved]. |
| 1168 compiler.resolveTypedef(typdef); | 1176 compiler.resolveTypedef(typdef); |
| 1169 Link<DartType> arguments = resolveTypeArguments( | 1177 var arguments = new LinkBuilder<DartType>(); |
| 1170 node, typdef.typeVariables, inStaticContext, | 1178 bool hashTypeArgumentMismatch = resolveTypeArguments( |
| 1171 scope, onFailure, whenResolved); | 1179 node, typdef.typeVariables, enclosingElement, |
| 1172 if (typdef.typeVariables.isEmpty && arguments.isEmpty) { | 1180 scope, onFailure, whenResolved, arguments); |
| 1173 // Return the canonical type if it has no type parameters. | 1181 if (hashTypeArgumentMismatch) { |
| 1174 type = typdef.computeType(compiler); | 1182 type = new MalformedType( |
| 1183 new ErroneousElement(MessageKind.TYPE_ARGUMENT_COUNT_MISMATCH, |
| 1184 [node], typeName.source, enclosingElement), |
| 1185 new TypedefType(typdef, arguments.toLink())); |
| 1175 } else { | 1186 } else { |
| 1176 if (arguments.isEmpty) { | 1187 if (arguments.isEmpty) { |
| 1177 type = typdef.rawType; | 1188 type = typdef.rawType; |
| 1178 } else { | 1189 } else { |
| 1179 type = new TypedefType(typdef, arguments); | 1190 type = new TypedefType(typdef, arguments.toLink()); |
| 1180 } | 1191 } |
| 1181 } | 1192 } |
| 1182 } else if (element.isTypeVariable()) { | 1193 } else if (element.isTypeVariable()) { |
| 1183 if (inStaticContext) { | 1194 if (enclosingElement.isInStaticMember()) { |
| 1184 compiler.reportWarning(node, | 1195 compiler.reportWarning(node, |
| 1185 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( | 1196 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER.message( |
| 1186 [element])); | 1197 [node])); |
| 1187 type = new MalformedType(new MalformedTypeElement(node, element)); | 1198 type = new MalformedType( |
| 1199 new ErroneousElement( |
| 1200 MessageKind.TYPE_VARIABLE_WITHIN_STATIC_MEMBER, |
| 1201 [node], typeName.source, enclosingElement), |
| 1202 element.computeType(compiler)); |
| 1188 } else { | 1203 } else { |
| 1189 type = element.computeType(compiler); | 1204 type = element.computeType(compiler); |
| 1190 } | 1205 } |
| 1206 type = checkNoTypeArguments(type); |
| 1191 } else { | 1207 } else { |
| 1192 compiler.cancel("unexpected element kind ${element.kind}", | 1208 compiler.cancel("unexpected element kind ${element.kind}", |
| 1193 node: node); | 1209 node: node); |
| 1194 } | 1210 } |
| 1195 } | 1211 } |
| 1196 whenResolved(node, type); | 1212 whenResolved(node, type); |
| 1197 return type; | 1213 return type; |
| 1198 } | 1214 } |
| 1199 | 1215 |
| 1200 Link<DartType> resolveTypeArguments(TypeAnnotation node, | 1216 /** |
| 1201 Link<DartType> typeVariables, | 1217 * Resolves the type arguments of [node] and adds these to [arguments]. |
| 1202 bool inStaticContext, | 1218 * |
| 1203 Scope scope, onFailure, whenResolved) { | 1219 * Returns [: true :] if the number of type arguments did not match the |
| 1220 * number of type variables. |
| 1221 */ |
| 1222 bool resolveTypeArguments( |
| 1223 TypeAnnotation node, |
| 1224 Link<DartType> typeVariables, |
| 1225 Element enclosingElement, |
| 1226 Scope scope, |
| 1227 onFailure, whenResolved, |
| 1228 LinkBuilder<DartType> arguments) { |
| 1204 if (node.typeArguments == null) { | 1229 if (node.typeArguments == null) { |
| 1205 return const Link<DartType>(); | 1230 return false; |
| 1206 } | 1231 } |
| 1207 var arguments = new LinkBuilder<DartType>(); | 1232 bool typeArgumentCountMismatch = false; |
| 1208 for (Link<Node> typeArguments = node.typeArguments.nodes; | 1233 for (Link<Node> typeArguments = node.typeArguments.nodes; |
| 1209 !typeArguments.isEmpty; | 1234 !typeArguments.isEmpty; |
| 1210 typeArguments = typeArguments.tail) { | 1235 typeArguments = typeArguments.tail) { |
| 1211 if (typeVariables.isEmpty) { | 1236 if (typeVariables != null && typeVariables.isEmpty) { |
| 1212 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); | 1237 onFailure(typeArguments.head, MessageKind.ADDITIONAL_TYPE_ARGUMENT); |
| 1238 typeArgumentCountMismatch = true; |
| 1213 } | 1239 } |
| 1214 DartType argType = resolveTypeAnnotationInContext(scope, | 1240 DartType argType = resolveTypeAnnotationInContext(scope, |
| 1215 typeArguments.head, | 1241 typeArguments.head, |
| 1216 inStaticContext, | 1242 enclosingElement, |
| 1217 onFailure, | 1243 onFailure, |
| 1218 whenResolved); | 1244 whenResolved); |
| 1219 arguments.addLast(argType); | 1245 arguments.addLast(argType); |
| 1220 if (!typeVariables.isEmpty) { | 1246 if (typeVariables != null && !typeVariables.isEmpty) { |
| 1221 typeVariables = typeVariables.tail; | 1247 typeVariables = typeVariables.tail; |
| 1222 } | 1248 } |
| 1223 } | 1249 } |
| 1224 if (!typeVariables.isEmpty) { | 1250 if (typeVariables != null && !typeVariables.isEmpty) { |
| 1225 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); | 1251 onFailure(node.typeArguments, MessageKind.MISSING_TYPE_ARGUMENT); |
| 1252 typeArgumentCountMismatch = true; |
| 1226 } | 1253 } |
| 1227 return arguments.toLink(); | 1254 return typeArgumentCountMismatch; |
| 1228 } | 1255 } |
| 1229 } | 1256 } |
| 1230 | 1257 |
| 1231 /** | 1258 /** |
| 1232 * Core implementation of resolution. | 1259 * Core implementation of resolution. |
| 1233 * | 1260 * |
| 1234 * Do not subclass or instantiate this class outside this library | 1261 * Do not subclass or instantiate this class outside this library |
| 1235 * except for testing. | 1262 * except for testing. |
| 1236 */ | 1263 */ |
| 1237 class ResolverVisitor extends CommonResolverVisitor<Element> { | 1264 class ResolverVisitor extends CommonResolverVisitor<Element> { |
| (...skipping 873 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2111 InterfaceType type = argument; | 2138 InterfaceType type = argument; |
| 2112 type.typeArguments.forEach((DartType argument) { | 2139 type.typeArguments.forEach((DartType argument) { |
| 2113 analyzeTypeArgument(type, argument); | 2140 analyzeTypeArgument(type, argument); |
| 2114 }); | 2141 }); |
| 2115 } | 2142 } |
| 2116 } | 2143 } |
| 2117 | 2144 |
| 2118 DartType resolveTypeAnnotation(TypeAnnotation node) { | 2145 DartType resolveTypeAnnotation(TypeAnnotation node) { |
| 2119 Function report = typeRequired ? error : warning; | 2146 Function report = typeRequired ? error : warning; |
| 2120 DartType type = typeResolver.resolveTypeAnnotation( | 2147 DartType type = typeResolver.resolveTypeAnnotation( |
| 2121 node, scope, enclosingElement.isInStaticMember(), | 2148 node, scope, enclosingElement, |
| 2122 onFailure: report, whenResolved: useType); | 2149 onFailure: report, whenResolved: useType); |
| 2123 if (type == null) return null; | 2150 if (type == null) return null; |
| 2124 if (inCheckContext) { | 2151 if (inCheckContext) { |
| 2125 compiler.enqueuer.resolution.registerIsCheck(type); | 2152 compiler.enqueuer.resolution.registerIsCheck(type); |
| 2126 } | 2153 } |
| 2127 if (typeRequired || inCheckContext) { | 2154 if (typeRequired || inCheckContext) { |
| 2128 if (type is InterfaceType) { | 2155 if (type is InterfaceType) { |
| 2129 InterfaceType itf = type; | 2156 InterfaceType itf = type; |
| 2130 itf.typeArguments.forEach((DartType argument) { | 2157 itf.typeArguments.forEach((DartType argument) { |
| 2131 analyzeTypeArgument(type, argument); | 2158 analyzeTypeArgument(type, argument); |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2479 SourceString typeName = typeVariable.name; | 2506 SourceString typeName = typeVariable.name; |
| 2480 TypeVariable typeNode = nodeLink.head; | 2507 TypeVariable typeNode = nodeLink.head; |
| 2481 if (nameSet.contains(typeName)) { | 2508 if (nameSet.contains(typeName)) { |
| 2482 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]); | 2509 error(typeNode, MessageKind.DUPLICATE_TYPE_VARIABLE_NAME, [typeName]); |
| 2483 } | 2510 } |
| 2484 nameSet.add(typeName); | 2511 nameSet.add(typeName); |
| 2485 | 2512 |
| 2486 TypeVariableElement variableElement = typeVariable.element; | 2513 TypeVariableElement variableElement = typeVariable.element; |
| 2487 if (typeNode.bound != null) { | 2514 if (typeNode.bound != null) { |
| 2488 DartType boundType = typeResolver.resolveTypeAnnotation( | 2515 DartType boundType = typeResolver.resolveTypeAnnotation( |
| 2489 typeNode.bound, scope, element.isInStaticMember(), | 2516 typeNode.bound, scope, element, |
| 2490 onFailure: warning); | 2517 onFailure: warning); |
| 2491 if (boundType != null && boundType.element == variableElement) { | 2518 if (boundType != null && boundType.element == variableElement) { |
| 2492 // TODO(johnniwinther): Check for more general cycles, like | 2519 // TODO(johnniwinther): Check for more general cycles, like |
| 2493 // [: <A extends B, B extends C, C extends B> :]. | 2520 // [: <A extends B, B extends C, C extends B> :]. |
| 2494 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, | 2521 warning(node, MessageKind.CYCLIC_TYPE_VARIABLE, |
| 2495 [variableElement.name]); | 2522 [variableElement.name]); |
| 2496 } else if (boundType != null) { | 2523 } else if (boundType != null) { |
| 2497 variableElement.bound = boundType; | 2524 variableElement.bound = boundType; |
| 2498 } else { | 2525 } else { |
| 2499 // TODO(johnniwinther): Should be an erroneous type. | 2526 // TODO(johnniwinther): Should be an erroneous type. |
| (...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3171 return e; | 3198 return e; |
| 3172 } | 3199 } |
| 3173 | 3200 |
| 3174 /// Assumed to be called by [resolveRedirectingFactory]. | 3201 /// Assumed to be called by [resolveRedirectingFactory]. |
| 3175 Element visitReturn(Return node) { | 3202 Element visitReturn(Return node) { |
| 3176 Node expression = node.expression; | 3203 Node expression = node.expression; |
| 3177 return finishConstructorReference(visit(expression), | 3204 return finishConstructorReference(visit(expression), |
| 3178 expression, expression); | 3205 expression, expression); |
| 3179 } | 3206 } |
| 3180 } | 3207 } |
| OLD | NEW |