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); |
} |