| Index: pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| index f9297c8267d2cdab2ea6cca383ee27f0b2db0316..c98dd4961ad844135c142843e234e2348fce69e4 100644
|
| --- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| +++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
|
| @@ -298,6 +298,8 @@ abstract class TypeInferrerImpl extends TypeInferrer {
|
| // to fail. TODO(paulberry): fix this.
|
| if (!strongMode) return null;
|
|
|
| + receiverType = resolveTypeParameter(receiverType);
|
| +
|
| if (receiverType is InterfaceType) {
|
| var interfaceMember = classHierarchy
|
| .getInterfaceMember(receiverType.classNode, name, setter: setter);
|
| @@ -910,6 +912,41 @@ abstract class TypeInferrerImpl extends TypeInferrer {
|
| // TODO(paulberry): report an error.
|
| }
|
|
|
| + /// 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;
|
| + } 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();
|
| + }
|
| +
|
| + // Hare takes two steps
|
| + var step1 = resolveOneStep(hare);
|
| + if (step1 == null) return hare;
|
| + var step2 = resolveOneStep(step1);
|
| + if (step2 == null) return hare;
|
| + hare = step2;
|
| +
|
| + // Tortoise takes one step
|
| + type = resolveOneStep(type);
|
| + }
|
| + }
|
| +
|
| /// Begins a dry run of type inference, in which the goal is to collect the
|
| /// dependencies of a given accessor.
|
| void startDryRun() {
|
|
|