Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 /// This file declares a "shadow hierarchy" of concrete classes which extend | 5 /// This file declares a "shadow hierarchy" of concrete classes which extend |
| 6 /// the kernel class hierarchy, adding methods and fields needed by the | 6 /// the kernel class hierarchy, adding methods and fields needed by the |
| 7 /// BodyBuilder. | 7 /// BodyBuilder. |
| 8 /// | 8 /// |
| 9 /// Instances of these classes may be created using the factory methods in | 9 /// Instances of these classes may be created using the factory methods in |
| 10 /// `ast_factory.dart`. | 10 /// `ast_factory.dart`. |
| (...skipping 669 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 680 } | 680 } |
| 681 } else { | 681 } else { |
| 682 // TODO(paulberry): In this case, should the context be based on the | 682 // TODO(paulberry): In this case, should the context be based on the |
| 683 // declared type of the loop variable? | 683 // declared type of the loop variable? |
| 684 // TODO(paulberry): Note that when [_declaresVariable] is `false`, the | 684 // TODO(paulberry): Note that when [_declaresVariable] is `false`, the |
| 685 // body starts with an assignment from the synthetic loop variable to | 685 // body starts with an assignment from the synthetic loop variable to |
| 686 // another variable. We need to make sure any type inference diagnostics | 686 // another variable. We need to make sure any type inference diagnostics |
| 687 // that occur related to this assignment are reported at the correct | 687 // that occur related to this assignment are reported at the correct |
| 688 // locations. | 688 // locations. |
| 689 } | 689 } |
| 690 var inferredExpressionType = | 690 var inferredExpressionType = inferrer.resolveTypeParameter( |
| 691 inferrer.inferExpression(iterable, context, typeNeeded); | 691 inferrer.inferExpression(iterable, context, typeNeeded)); |
| 692 if (typeNeeded) { | 692 if (typeNeeded) { |
| 693 var inferredType = const DynamicType(); | 693 var inferredType = const DynamicType(); |
| 694 if (inferredExpressionType is InterfaceType) { | 694 if (inferredExpressionType is InterfaceType) { |
| 695 InterfaceType supertype = inferrer.classHierarchy | 695 InterfaceType supertype = inferrer.classHierarchy |
| 696 .getTypeAsInstanceOf(inferredExpressionType, iterableClass); | 696 .getTypeAsInstanceOf(inferredExpressionType, iterableClass); |
| 697 if (supertype != null) { | 697 if (supertype != null) { |
| 698 inferredType = supertype.typeArguments[0]; | 698 inferredType = supertype.typeArguments[0]; |
| 699 } | 699 } |
| 700 } | 700 } |
| 701 inferrer.instrumentation?.record( | 701 inferrer.instrumentation?.record( |
| (...skipping 1325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2027 // so that the type hierarchy will be simpler (which may speed up "is" | 2027 // so that the type hierarchy will be simpler (which may speed up "is" |
| 2028 // checks). | 2028 // checks). |
| 2029 return statement._inferStatement(this); | 2029 return statement._inferStatement(this); |
| 2030 } else { | 2030 } else { |
| 2031 // Encountered a statement type for which type inference is not yet | 2031 // Encountered a statement type for which type inference is not yet |
| 2032 // implemented, so just skip it for now. | 2032 // implemented, so just skip it for now. |
| 2033 // TODO(paulberry): once the BodyBuilder uses shadow classes for | 2033 // TODO(paulberry): once the BodyBuilder uses shadow classes for |
| 2034 // everything, this case should no longer be needed. | 2034 // everything, this case should no longer be needed. |
| 2035 } | 2035 } |
| 2036 } | 2036 } |
| 2037 | |
| 2038 /// If the given [type] is a [TypeParameterType], resolve it to its bound. | |
| 2039 DartType resolveTypeParameter(DartType type) { | |
| 2040 DartType resolveOneStep(DartType type) { | |
| 2041 if (type is TypeParameterType) { | |
| 2042 return type.bound ?? type.parameter.bound; | |
| 2043 } else { | |
| 2044 return null; | |
| 2045 } | |
| 2046 } | |
| 2047 | |
| 2048 var resolved = resolveOneStep(type); | |
| 2049 if (resolved == null) return type; | |
| 2050 | |
| 2051 // Detect circularities using the tortoise-and-hare algorithm. | |
| 2052 type = resolved; | |
| 2053 DartType hare = resolveOneStep(type); | |
| 2054 if (hare == null) return type; | |
| 2055 while (true) { | |
| 2056 if (identical(type, hare)) { | |
| 2057 // We found a circularity. Give up and return `dynamic`. | |
| 2058 return const DynamicType(); | |
| 2059 } | |
| 2060 resolved = resolveOneStep(hare); | |
|
Siggi Cherem (dart-lang)
2017/06/21 21:12:10
random optional idea here - it took me some time t
Paul Berry
2017/06/21 21:44:16
I like it! Thanks
| |
| 2061 if (resolved == null) return hare; | |
| 2062 hare = resolved; | |
| 2063 resolved = resolveOneStep(hare); | |
| 2064 if (resolved == null) return hare; | |
| 2065 hare = resolved; | |
| 2066 type = resolveOneStep(type); | |
| 2067 } | |
| 2068 } | |
| 2037 } | 2069 } |
| 2038 | 2070 |
| 2039 /// Shadow object for [TypeLiteral]. | 2071 /// Shadow object for [TypeLiteral]. |
| 2040 class KernelTypeLiteral extends TypeLiteral implements KernelExpression { | 2072 class KernelTypeLiteral extends TypeLiteral implements KernelExpression { |
| 2041 KernelTypeLiteral(DartType type) : super(type); | 2073 KernelTypeLiteral(DartType type) : super(type); |
| 2042 | 2074 |
| 2043 @override | 2075 @override |
| 2044 void _collectDependencies(KernelDependencyCollector collector) { | 2076 void _collectDependencies(KernelDependencyCollector collector) { |
| 2045 // No inference dependencies. | 2077 // No inference dependencies. |
| 2046 } | 2078 } |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2178 KernelVariableDeclaration.forValue( | 2210 KernelVariableDeclaration.forValue( |
| 2179 Expression initializer, this._functionNestingLevel) | 2211 Expression initializer, this._functionNestingLevel) |
| 2180 : _implicitlyTyped = true, | 2212 : _implicitlyTyped = true, |
| 2181 _isLocalFunction = false, | 2213 _isLocalFunction = false, |
| 2182 super.forValue(initializer); | 2214 super.forValue(initializer); |
| 2183 | 2215 |
| 2184 @override | 2216 @override |
| 2185 void _inferStatement(KernelTypeInferrer inferrer) { | 2217 void _inferStatement(KernelTypeInferrer inferrer) { |
| 2186 inferrer.listener.variableDeclarationEnter(this); | 2218 inferrer.listener.variableDeclarationEnter(this); |
| 2187 var declaredType = _implicitlyTyped ? null : type; | 2219 var declaredType = _implicitlyTyped ? null : type; |
| 2220 DartType inferredType; | |
| 2188 if (initializer != null) { | 2221 if (initializer != null) { |
| 2189 var inferredType = inferrer.inferDeclarationType(inferrer.inferExpression( | 2222 inferredType = inferrer.inferDeclarationType(inferrer.inferExpression( |
| 2190 initializer, declaredType, _implicitlyTyped)); | 2223 initializer, declaredType, _implicitlyTyped)); |
| 2191 if (inferrer.strongMode && _implicitlyTyped) { | 2224 } else { |
| 2192 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, | 2225 inferredType = const DynamicType(); |
| 2193 'type', new InstrumentationValueForType(inferredType)); | 2226 } |
| 2194 type = inferredType; | 2227 if (inferrer.strongMode && _implicitlyTyped) { |
| 2195 } | 2228 inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, |
| 2229 'type', new InstrumentationValueForType(inferredType)); | |
| 2230 type = inferredType; | |
| 2196 } | 2231 } |
| 2197 inferrer.listener.variableDeclarationExit(this); | 2232 inferrer.listener.variableDeclarationExit(this); |
| 2198 } | 2233 } |
| 2199 | 2234 |
| 2200 /// Determine whether the given [KernelVariableDeclaration] had an implicit | 2235 /// Determine whether the given [KernelVariableDeclaration] had an implicit |
| 2201 /// type. | 2236 /// type. |
| 2202 /// | 2237 /// |
| 2203 /// This is static to avoid introducing a method that would be visible to | 2238 /// This is static to avoid introducing a method that would be visible to |
| 2204 /// the kernel. | 2239 /// the kernel. |
| 2205 static bool isImplicitlyTyped(KernelVariableDeclaration variable) => | 2240 static bool isImplicitlyTyped(KernelVariableDeclaration variable) => |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2280 } | 2315 } |
| 2281 | 2316 |
| 2282 transformChildren(v) { | 2317 transformChildren(v) { |
| 2283 return internalError("Internal error: Unsupported operation."); | 2318 return internalError("Internal error: Unsupported operation."); |
| 2284 } | 2319 } |
| 2285 | 2320 |
| 2286 visitChildren(v) { | 2321 visitChildren(v) { |
| 2287 return internalError("Internal error: Unsupported operation."); | 2322 return internalError("Internal error: Unsupported operation."); |
| 2288 } | 2323 } |
| 2289 } | 2324 } |
| OLD | NEW |