Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(21)

Side by Side Diff: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart

Issue 2949093002: Properly type infer for-in loops when the iterator type is a type parameter. (Closed)
Patch Set: Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/front_end/test/fasta/strong.status » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/front_end/test/fasta/strong.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698