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 |