Chromium Code Reviews| Index: pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
| diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
| index d3c0fd2b82ac09ce1b2ec329dac03770a3d2d39b..119978f0f09b4fee916e584f0e049480b1695abd 100644 |
| --- a/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
| +++ b/pkg/front_end/lib/src/fasta/kernel/kernel_shadow_ast.dart |
| @@ -687,8 +687,8 @@ class KernelForInStatement extends ForInStatement implements KernelStatement { |
| // that occur related to this assignment are reported at the correct |
| // locations. |
| } |
| - var inferredExpressionType = |
| - inferrer.inferExpression(iterable, context, typeNeeded); |
| + var inferredExpressionType = inferrer.resolveTypeParameter( |
| + inferrer.inferExpression(iterable, context, typeNeeded)); |
| if (typeNeeded) { |
| var inferredType = const DynamicType(); |
| if (inferredExpressionType is InterfaceType) { |
| @@ -2034,6 +2034,38 @@ class KernelTypeInferrer extends TypeInferrerImpl { |
| // everything, this case should no longer be needed. |
| } |
| } |
| + |
| + /// If the given [type] is a [TypeParameterType], resolve it to its bound. |
| + DartType resolveTypeParameter(DartType type) { |
| + DartType resolveOneStep(DartType type) { |
| + if (type is TypeParameterType) { |
| + return type.bound ?? type.parameter.bound; |
| + } else { |
| + return null; |
| + } |
| + } |
| + |
| + var resolved = resolveOneStep(type); |
| + if (resolved == null) return type; |
| + |
| + // Detect circularities using the tortoise-and-hare algorithm. |
| + type = resolved; |
| + DartType hare = resolveOneStep(type); |
| + if (hare == null) return type; |
| + while (true) { |
| + if (identical(type, hare)) { |
| + // We found a circularity. Give up and return `dynamic`. |
| + return const DynamicType(); |
| + } |
| + 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
|
| + if (resolved == null) return hare; |
| + hare = resolved; |
| + resolved = resolveOneStep(hare); |
| + if (resolved == null) return hare; |
| + hare = resolved; |
| + type = resolveOneStep(type); |
| + } |
| + } |
| } |
| /// Shadow object for [TypeLiteral]. |
| @@ -2185,14 +2217,17 @@ class KernelVariableDeclaration extends VariableDeclaration |
| void _inferStatement(KernelTypeInferrer inferrer) { |
| inferrer.listener.variableDeclarationEnter(this); |
| var declaredType = _implicitlyTyped ? null : type; |
| + DartType inferredType; |
| if (initializer != null) { |
| - var inferredType = inferrer.inferDeclarationType(inferrer.inferExpression( |
| + inferredType = inferrer.inferDeclarationType(inferrer.inferExpression( |
| initializer, declaredType, _implicitlyTyped)); |
| - if (inferrer.strongMode && _implicitlyTyped) { |
| - inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, |
| - 'type', new InstrumentationValueForType(inferredType)); |
| - type = inferredType; |
| - } |
| + } else { |
| + inferredType = const DynamicType(); |
| + } |
| + if (inferrer.strongMode && _implicitlyTyped) { |
| + inferrer.instrumentation?.record(Uri.parse(inferrer.uri), fileOffset, |
| + 'type', new InstrumentationValueForType(inferredType)); |
| + type = inferredType; |
| } |
| inferrer.listener.variableDeclarationExit(this); |
| } |