| Index: pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart | 
| diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart | 
| index b21d5929a211cd9fe5fc54ce1356c1a345dbb4f8..ee4166216ede6c53cb54d942acab19886ed6dfb4 100644 | 
| --- a/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart | 
| +++ b/pkg/front_end/lib/src/fasta/type_inference/type_inference_engine.dart | 
| @@ -15,8 +15,8 @@ import 'package:kernel/class_hierarchy.dart'; | 
| import 'package:kernel/core_types.dart'; | 
| import 'package:kernel/type_algebra.dart'; | 
|  | 
| -/// Data structure for tracking dependencies between fields that require type | 
| -/// inference. | 
| +/// Data structure for tracking dependencies among fields, getters, and setters | 
| +/// that require type inference. | 
| /// | 
| /// TODO(paulberry): see if it's possible to make this class more lightweight | 
| /// by changing the API so that the walker is passed to computeDependencies(). | 
| @@ -24,7 +24,7 @@ import 'package:kernel/type_algebra.dart'; | 
| class FieldNode extends dependencyWalker.Node<FieldNode> { | 
| final TypeInferenceEngineImpl _typeInferenceEngine; | 
|  | 
| -  final KernelField field; | 
| +  final KernelMember member; | 
|  | 
| bool isImmediatelyEvident = false; | 
|  | 
| @@ -39,7 +39,7 @@ class FieldNode extends dependencyWalker.Node<FieldNode> { | 
|  | 
| final overrides = <Member>[]; | 
|  | 
| -  FieldNode(this._typeInferenceEngine, this.field); | 
| +  FieldNode(this._typeInferenceEngine, this.member); | 
|  | 
| @override | 
| bool get isEvaluated => state == FieldState.Inferred; | 
| @@ -50,7 +50,7 @@ class FieldNode extends dependencyWalker.Node<FieldNode> { | 
| } | 
|  | 
| @override | 
| -  String toString() => field.toString(); | 
| +  String toString() => member.toString(); | 
| } | 
|  | 
| /// Enum tracking the type inference state of a field. | 
| @@ -87,7 +87,7 @@ abstract class TypeInferenceEngine { | 
| /// Creates a [TypeInferrer] object which is ready to perform type inference | 
| /// on the given [field]. | 
| TypeInferrer createTopLevelTypeInferrer(TypeInferenceListener listener, | 
| -      InterfaceType thisType, KernelField field); | 
| +      InterfaceType thisType, KernelMember member); | 
|  | 
| /// Performs the second phase of top level initializer inference, which is to | 
| /// visit all fields and top level variables that were passed to [recordField] | 
| @@ -98,12 +98,12 @@ abstract class TypeInferenceEngine { | 
| /// [hierarchy], using the given [coreTypes]. | 
| void prepareTopLevel(CoreTypes coreTypes, ClassHierarchy hierarchy); | 
|  | 
| -  /// Records that the given [field] will need top level type inference. | 
| -  void recordField(KernelField field); | 
| - | 
| /// Records that the given initializing [formal] will need top level type | 
| /// inference. | 
| void recordInitializingFormal(KernelVariableDeclaration formal); | 
| + | 
| +  /// Records that the given [member] will need top level type inference. | 
| +  void recordMember(KernelMember member); | 
| } | 
|  | 
| /// Derived class containing generic implementations of | 
| @@ -154,9 +154,6 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
|  | 
| TypeInferenceEngineImpl(this.instrumentation, this.strongMode); | 
|  | 
| -  /// Clears the initializer of [field]. | 
| -  void clearFieldInitializer(KernelField field); | 
| - | 
| /// Computes type inference dependencies for the given [field]. | 
| List<FieldNode> computeFieldDependencies(FieldNode fieldNode) { | 
| // If the field's type is going to be determined by inheritance, then its | 
| @@ -165,41 +162,47 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| var dependencies = <FieldNode>[]; | 
| for (var override in fieldNode.overrides) { | 
| // TODO(paulberry): support dependencies on getters/setters too. | 
| -        if (override is Field) { | 
| -          dependencies.add(KernelField.getFieldNode(override)); | 
| -        } | 
| +        var dep = KernelMember.getFieldNode(override); | 
| +        if (dep != null) dependencies.add(dep); | 
| } | 
| fieldNode.isImmediatelyEvident = true; | 
| return dependencies; | 
| } | 
|  | 
| // Otherwise its dependencies are based on the initializer expression. | 
| -    if (expandedTopLevelInference) { | 
| -      // In expanded top level inference, we determine the dependencies by | 
| -      // doing a "dry run" of top level inference and recording which static | 
| -      // fields were accessed. | 
| -      var typeInferrer = getFieldTypeInferrer(fieldNode.field); | 
| -      if (typeInferrer == null) { | 
| -        // This can happen when there are errors in the field declaration. | 
| -        return const []; | 
| +    var member = fieldNode.member; | 
| +    if (member is KernelField) { | 
| +      if (expandedTopLevelInference) { | 
| +        // In expanded top level inference, we determine the dependencies by | 
| +        // doing a "dry run" of top level inference and recording which static | 
| +        // fields were accessed. | 
| +        var typeInferrer = getFieldTypeInferrer(member); | 
| +        if (typeInferrer == null) { | 
| +          // This can happen when there are errors in the field declaration. | 
| +          return const []; | 
| +        } else { | 
| +          typeInferrer.startDryRun(); | 
| +          typeInferrer.listener.dryRunEnter(member.initializer); | 
| +          typeInferrer.inferFieldTopLevel(member, null, true); | 
| +          typeInferrer.listener.dryRunExit(member.initializer); | 
| +          fieldNode.isImmediatelyEvident = true; | 
| +          return typeInferrer.finishDryRun(); | 
| +        } | 
| } else { | 
| -        typeInferrer.startDryRun(); | 
| -        typeInferrer.listener.dryRunEnter(fieldNode.field.initializer); | 
| -        typeInferrer.inferFieldTopLevel(fieldNode.field, null, true); | 
| -        typeInferrer.listener.dryRunExit(fieldNode.field.initializer); | 
| -        fieldNode.isImmediatelyEvident = true; | 
| -        return typeInferrer.finishDryRun(); | 
| +        // In non-expanded top level inference, we determine the dependencies by | 
| +        // calling `collectDependencies`; as a side effect this flags any | 
| +        // expressions that are not "immediately evident". | 
| +        // TODO(paulberry): get rid of this mode once we are sure we no longer | 
| +        // need it. | 
| +        var collector = new KernelDependencyCollector(); | 
| +        collector.collectDependencies(member.initializer); | 
| +        fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident; | 
| +        return collector.dependencies; | 
| } | 
| } else { | 
| -      // In non-expanded top level inference, we determine the dependencies by | 
| -      // calling `collectDependencies`; as a side effect this flags any | 
| -      // expressions that are not "immediately evident". | 
| -      // TODO(paulberry): get rid of this mode once we are sure we no longer | 
| -      // need it. | 
| -      var collector = new KernelDependencyCollector(); | 
| -      collector.collectDependencies(fieldNode.field.initializer); | 
| -      fieldNode.isImmediatelyEvident = collector.isImmediatelyEvident; | 
| -      return collector.dependencies; | 
| +      // Member is a getter/setter that doesn't override anything, so we can't | 
| +      // infer a type for it; therefore it has no dependencies. | 
| +      return const []; | 
| } | 
| } | 
|  | 
| @@ -222,29 +225,29 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| } | 
| } | 
|  | 
| -  /// Gets the character offset of the declaration of [field] within its | 
| -  /// compilation unit. | 
| -  int getFieldOffset(KernelField field); | 
| - | 
| -  /// Retrieve the [TypeInferrer] for the given [field], which was created by | 
| +  /// Retrieve the [TypeInferrer] for the given [member], which was created by | 
| /// a previous call to [createTopLevelTypeInferrer]. | 
| -  TypeInferrerImpl getFieldTypeInferrer(KernelField field); | 
| +  TypeInferrerImpl getFieldTypeInferrer(KernelMember member); | 
|  | 
| /// Performs type inference on the given [field]. | 
| void inferField(FieldNode fieldNode) { | 
| assert(fieldNode.state == FieldState.NotInferredYet); | 
| fieldNode.state = FieldState.Inferring; | 
| -    var field = fieldNode.field; | 
| +    var member = fieldNode.member; | 
| if (strongMode) { | 
| var inferredType = tryInferFieldByInheritance(fieldNode); | 
| -      var typeInferrer = getFieldTypeInferrer(field); | 
| +      var typeInferrer = getFieldTypeInferrer(member); | 
| if (inferredType == null) { | 
| -        typeInferrer.isImmediatelyEvident = true; | 
| -        inferredType = fieldNode.isImmediatelyEvident | 
| -            ? typeInferrer.inferDeclarationType( | 
| -                typeInferrer.inferFieldTopLevel(field, null, true)) | 
| -            : const DynamicType(); | 
| -        if (!typeInferrer.isImmediatelyEvident) { | 
| +        if (member is KernelField) { | 
| +          typeInferrer.isImmediatelyEvident = true; | 
| +          inferredType = fieldNode.isImmediatelyEvident | 
| +              ? typeInferrer.inferDeclarationType( | 
| +                  typeInferrer.inferFieldTopLevel(member, null, true)) | 
| +              : const DynamicType(); | 
| +          if (!typeInferrer.isImmediatelyEvident) { | 
| +            inferredType = const DynamicType(); | 
| +          } | 
| +        } else { | 
| inferredType = const DynamicType(); | 
| } | 
| } | 
| @@ -253,12 +256,7 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| // inference for this node was completed. | 
| return; | 
| } | 
| -      instrumentation?.record( | 
| -          Uri.parse(typeInferrer.uri), | 
| -          getFieldOffset(field), | 
| -          'topType', | 
| -          new InstrumentationValueForType(inferredType)); | 
| -      field.type = inferredType; | 
| +      member.setInferredType(this, typeInferrer.uri, inferredType); | 
| } | 
| fieldNode.state = FieldState.Inferred; | 
| // TODO(paulberry): if type != null, then check that the type of the | 
| @@ -266,20 +264,25 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| // TODO(paulberry): the following is a hack so that outlines don't contain | 
| // initializers.  But it means that we rebuild the initializers when doing | 
| // a full compile.  There should be a better way. | 
| -    clearFieldInitializer(field); | 
| +    if (member is KernelField) { | 
| +      member.initializer = null; | 
| +    } | 
| } | 
|  | 
| /// Makes a note that the given [field] is part of a circularity, so its type | 
| /// can't be inferred. | 
| void inferFieldCircular(FieldNode fieldNode) { | 
| -    var field = fieldNode.field; | 
| +    var member = fieldNode.member; | 
| // TODO(paulberry): report the appropriate error. | 
| -    var uri = getFieldTypeInferrer(field).uri; | 
| -    var inferredType = const DynamicType(); | 
| -    instrumentation?.record(Uri.parse(uri), getFieldOffset(field), 'topType', | 
| -        new InstrumentationValueForType(inferredType)); | 
| +    var uri = getFieldTypeInferrer(member).uri; | 
| fieldNode.state = FieldState.Inferred; | 
| -    field.type = inferredType; | 
| +    member.setInferredType(this, uri, const DynamicType()); | 
| +    // TODO(paulberry): the following is a hack so that outlines don't contain | 
| +    // initializers.  But it means that we rebuild the initializers when doing | 
| +    // a full compile.  There should be a better way. | 
| +    if (member is KernelField) { | 
| +      member.initializer = null; | 
| +    } | 
| } | 
|  | 
| /// Performs fused type inference on the given [field]. | 
| @@ -321,13 +324,13 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| } | 
|  | 
| @override | 
| -  void recordField(KernelField field) { | 
| -    fieldNodes.add(createFieldNode(field)); | 
| +  void recordInitializingFormal(KernelVariableDeclaration formal) { | 
| +    initializingFormals.add(formal); | 
| } | 
|  | 
| @override | 
| -  void recordInitializingFormal(KernelVariableDeclaration formal) { | 
| -    initializingFormals.add(formal); | 
| +  void recordMember(KernelMember member) { | 
| +    fieldNodes.add(createFieldNode(member)); | 
| } | 
|  | 
| DartType tryInferFieldByInheritance(FieldNode fieldNode) { | 
| @@ -346,14 +349,14 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| } | 
|  | 
| DartType _computeOverriddenFieldType(Member override, FieldNode fieldNode) { | 
| +    if (fusedTopLevelInference) { | 
| +      FieldNode dependency = KernelMember.getFieldNode(override); | 
| +      if (dependency != null) { | 
| +        inferFieldFused(dependency, fieldNode); | 
| +      } | 
| +    } | 
| DartType overriddenType; | 
| if (override is Field) { | 
| -      if (fusedTopLevelInference) { | 
| -        FieldNode dependency = KernelField.getFieldNode(override); | 
| -        if (dependency != null) { | 
| -          inferFieldFused(dependency, fieldNode); | 
| -        } | 
| -      } | 
| overriddenType = override.type; | 
| } else if (override is Procedure) { | 
| // TODO(paulberry): handle the case where override needs its type | 
| @@ -369,7 +372,7 @@ abstract class TypeInferenceEngineImpl extends TypeInferenceEngine { | 
| } | 
| var superclass = override.enclosingClass; | 
| if (superclass.typeParameters.isEmpty) return overriddenType; | 
| -    var thisClass = fieldNode.field.enclosingClass; | 
| +    var thisClass = fieldNode.member.enclosingClass; | 
| var superclassInstantiation = classHierarchy | 
| .getClassAsInstanceOf(thisClass, superclass) | 
| .asInterfaceType; | 
|  |