Add top level type inference logic for integer literals.

This CL hooks up enough infrastructure for doing simple top level type
inference of variables whose initializer is an int.

Additional type inference rules will be added in follow-up CLs.

R=karlklose@google.com

Review-Url: https://codereview.chromium.org/2828253003 .
diff --git a/pkg/analysis_server/analysis_server.iml b/pkg/analysis_server/analysis_server.iml
index eeb9c7a..ea34ce5 100644
--- a/pkg/analysis_server/analysis_server.iml
+++ b/pkg/analysis_server/analysis_server.iml
@@ -57,6 +57,5 @@
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" name="Dart SDK" level="application" />
     <orderEntry type="library" name="Dart SDK" level="project" />
-    <orderEntry type="library" name="Dart Packages" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 0ac507b..3344672 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -1607,7 +1607,7 @@
         body));
   }
 
-  void endFieldInitializer(Token assignment) {
+  void endFieldInitializer(Token assignment, Token token) {
     debugEvent("FieldInitializer");
     Expression initializer = pop();
     SimpleIdentifier name = pop();
diff --git a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
index a0a470d..0d04de9 100644
--- a/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
+++ b/pkg/analyzer/lib/src/kernel/ast_from_analyzer.dart
@@ -17,7 +17,7 @@
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:front_end/src/fasta/kernel/frontend_accessors.dart';
+import 'package:kernel/frontend/accessors.dart';
 
 /// Provides reference-level access to libraries, classes, and members.
 ///
diff --git a/pkg/analyzer/lib/src/summary/fasta/summary_builder.dart b/pkg/analyzer/lib/src/summary/fasta/summary_builder.dart
index ec951f0..4d5d8a6 100644
--- a/pkg/analyzer/lib/src/summary/fasta/summary_builder.dart
+++ b/pkg/analyzer/lib/src/summary/fasta/summary_builder.dart
@@ -980,7 +980,7 @@
     // /* List<MetadataBuilder> metadata = */ pop();
   }
 
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     debugEvent("FieldInitializer $typeSeen $assignmentOperator");
     // This is a variable initializer and it's ignored for now. May also be
     // constructor initializer.
diff --git a/pkg/analyzer/tool/summary/mini_ast.dart b/pkg/analyzer/tool/summary/mini_ast.dart
index e84afa9..cc22b48 100644
--- a/pkg/analyzer/tool/summary/mini_ast.dart
+++ b/pkg/analyzer/tool/summary/mini_ast.dart
@@ -244,7 +244,7 @@
   }
 
   @override
-  void endFieldInitializer(Token assignment) {
+  void endFieldInitializer(Token assignment, Token token) {
     debugEvent("FieldInitializer");
     pop(); // Expression
   }
diff --git a/pkg/compiler/lib/src/parser/member_listener.dart b/pkg/compiler/lib/src/parser/member_listener.dart
index 2346ebf..ae963e89 100644
--- a/pkg/compiler/lib/src/parser/member_listener.dart
+++ b/pkg/compiler/lib/src/parser/member_listener.dart
@@ -133,10 +133,10 @@
   }
 
   @override
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     pushNode(null); // Super expects an expression, but
     // ClassElementParser just skips expressions.
-    super.endFieldInitializer(assignmentOperator);
+    super.endFieldInitializer(assignmentOperator, token);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/parser/node_listener.dart b/pkg/compiler/lib/src/parser/node_listener.dart
index 7ab1210..a821523 100644
--- a/pkg/compiler/lib/src/parser/node_listener.dart
+++ b/pkg/compiler/lib/src/parser/node_listener.dart
@@ -531,7 +531,7 @@
   }
 
   @override
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     endVariableInitializer(assignmentOperator);
   }
 
diff --git a/pkg/front_end/front_end.iml b/pkg/front_end/front_end.iml
index cf56171..0a216d5 100644
--- a/pkg/front_end/front_end.iml
+++ b/pkg/front_end/front_end.iml
@@ -8,7 +8,6 @@
       <excludeFolder url="file://$MODULE_DIR$/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/fasta/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/fasta/parser/packages" />
-      <excludeFolder url="file://$MODULE_DIR$/test/fasta/rasta/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/fasta/scanner/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/packages" />
       <excludeFolder url="file://$MODULE_DIR$/test/src/base/packages" />
diff --git a/pkg/front_end/lib/src/fasta/builder/ast_factory.dart b/pkg/front_end/lib/src/fasta/builder/ast_factory.dart
index 1a8a409d..2559d89 100644
--- a/pkg/front_end/lib/src/fasta/builder/ast_factory.dart
+++ b/pkg/front_end/lib/src/fasta/builder/ast_factory.dart
@@ -36,6 +36,9 @@
   /// Creates a statement block.
   Block block(List<Statement> statements, int charOffset);
 
+  /// Creates a field.
+  Field field(Name name, int charOffset, {String fileUri});
+
   /// Creates an integer literal.
   IntLiteral intLiteral(value, int charOffset);
 
@@ -52,6 +55,9 @@
   /// Creates a return statement.
   Statement returnStatement(Expression expression, int charOffset);
 
+  /// Creates a read of a static variable.
+  StaticGet staticGet(Member readTarget, int offset);
+
   /// Creates a variable declaration statement declaring one variable.
   ///
   /// TODO(paulberry): analyzer makes a distinction between a single variable
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index aab930a..940bc78 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -58,6 +58,12 @@
 
 import 'library_builder.dart' show LibraryBuilder;
 
+import 'package:front_end/src/fasta/builder/class_builder.dart'
+    show ClassBuilder;
+
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
+    show TypeInferrer;
+
 abstract class Builder {
   /// Used when multiple things with the same name are declared within the same
   /// parent. Only used for declarations, not for scopes.
@@ -132,4 +138,7 @@
     } while (builder != null);
     return internalError("No library parent.");
   }
+
+  void prepareInitializerInference(TypeInferrer typeInferrer,
+      LibraryBuilder library, ClassBuilder currentClass) {}
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
index 3260985..cc38703 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -14,10 +14,10 @@
 import 'package:front_end/src/fasta/builder/ast_factory.dart' show AstFactory;
 
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
-    show KernelVariableDeclaration;
+    show KernelField, KernelVariableDeclaration;
 
 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
-    show TypeInferrer;
+    show FieldNode, TypeInferrer;
 
 import 'package:kernel/ast.dart';
 
@@ -87,11 +87,16 @@
   @override
   final Uri uri;
 
-  final TypeInferrer<Statement, Expression, KernelVariableDeclaration, Field>
-      _typeInferrer;
+  final TypeInferrer<Statement, Expression, KernelVariableDeclaration,
+      KernelField> _typeInferrer;
 
   final AstFactory astFactory;
 
+  /// If not `null`, dependencies on fields are accumulated into this list.
+  ///
+  /// If `null`, no dependency information is recorded.
+  final List<FieldNode<KernelField>> fieldDependencies;
+
   /// Only used when [member] is a constructor. It tracks if an implicit super
   /// initializer is needed.
   ///
@@ -141,7 +146,8 @@
       this.isInstanceMember,
       this.uri,
       this._typeInferrer,
-      this.astFactory)
+      this.astFactory,
+      {this.fieldDependencies})
       : enclosingScope = scope,
         library = library,
         isDartLibrary = library.uri.scheme == "dart",
@@ -1070,7 +1076,7 @@
   }
 
   @override
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     debugEvent("FieldInitializer");
     assert(assignmentOperator.stringValue == "=");
     push(popForValue());
@@ -2611,6 +2617,19 @@
   void debugEvent(String name) {
     // printEvent(name);
   }
+
+  @override
+  StaticGet makeStaticGet(Member readTarget, int offset) {
+    // TODO(paulberry): only record the dependencies mandated by the top level
+    // type inference spec.
+    if (fieldDependencies != null && readTarget is KernelField) {
+      var fieldNode = _typeInferrer.getFieldNodeForReadTarget(readTarget);
+      if (fieldNode != null) {
+        fieldDependencies.add(fieldNode);
+      }
+    }
+    return astFactory.staticGet(readTarget, offset);
+  }
 }
 
 // TODO(ahe): Shouldn't need to be an expression.
diff --git a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
index 018e27b..8d17a8a 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fasta_accessors.dart
@@ -70,6 +70,8 @@
 
   bool checkArguments(FunctionNode function, Arguments arguments,
       List<TypeParameter> typeParameters);
+
+  StaticGet makeStaticGet(Member readTarget, int offset);
 }
 
 abstract class FastaAccessor implements Accessor {
@@ -661,10 +663,9 @@
 }
 
 class StaticAccessor extends kernel.StaticAccessor with FastaAccessor {
-  final BuilderHelper helper;
-
-  StaticAccessor(this.helper, int offset, Member readTarget, Member writeTarget)
-      : super(readTarget, writeTarget, offset) {
+  StaticAccessor(
+      BuilderHelper helper, int offset, Member readTarget, Member writeTarget)
+      : super(helper, readTarget, writeTarget, offset) {
     assert(readTarget != null || writeTarget != null);
   }
 
diff --git a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
index aae1d08..54c6d364 100644
--- a/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/frontend_accessors.dart
@@ -5,6 +5,9 @@
 /// A library to help transform compounds and null-aware accessors into
 /// let expressions.
 
+import 'package:front_end/src/fasta/kernel/fasta_accessors.dart'
+    show BuilderHelper;
+
 import 'package:kernel/ast.dart';
 
 final Name indexGetName = new Name("[]");
@@ -448,14 +451,16 @@
 }
 
 class StaticAccessor extends Accessor {
+  final BuilderHelper helper;
   Member readTarget;
   Member writeTarget;
 
-  StaticAccessor(this.readTarget, this.writeTarget, int offset) : super(offset);
+  StaticAccessor(this.helper, this.readTarget, this.writeTarget, int offset)
+      : super(offset);
 
-  Expression _makeRead() => builtGetter =
-      readTarget == null ? makeInvalidRead() : new StaticGet(readTarget)
-        ..fileOffset = offset;
+  Expression _makeRead() => builtGetter = readTarget == null
+      ? makeInvalidRead()
+      : helper.makeStaticGet(readTarget, offset);
 
   Expression _makeWrite(Expression value, bool voidContext) {
     return writeTarget == null
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_factory.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_factory.dart
index c139a05..d8fb64f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_ast_factory.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_ast_factory.dart
@@ -15,6 +15,11 @@
   }
 
   @override
+  Field field(Name name, int charOffset, {String fileUri}) {
+    return new KernelField(name, fileUri: fileUri)..fileOffset = charOffset;
+  }
+
+  @override
   KernelIntLiteral intLiteral(value, int charOffset) {
     return new KernelIntLiteral(value)..fileOffset = charOffset;
   }
@@ -38,6 +43,11 @@
   }
 
   @override
+  StaticGet staticGet(Member readTarget, int offset) {
+    return new KernelStaticGet(readTarget)..fileOffset = offset;
+  }
+
+  @override
   KernelVariableDeclaration variableDeclaration(String name, int charOffset,
       {DartType type,
       Expression initializer,
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
index 62c03a6..d0bf021 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_enum_builder.dart
@@ -4,6 +4,8 @@
 
 library fasta.kernel_enum_builder;
 
+import 'package:front_end/src/fasta/builder/ast_factory.dart' show AstFactory;
+
 import 'package:kernel/ast.dart'
     show
         Arguments,
@@ -87,6 +89,7 @@
             null, charOffset, cls);
 
   factory KernelEnumBuilder(
+      AstFactory astFactory,
       List<MetadataBuilder> metadata,
       String name,
       List<Object> constantNamesAndOffsets,
@@ -121,7 +124,15 @@
     ///       String toString() => { 0: ‘E.id0’, . . ., n-1: ‘E.idn-1’}[index]
     ///     }
     members["index"] = new KernelFieldBuilder(
-        null, intType, "index", finalMask, parent, charOffset);
+        astFactory,
+        parent.loader.topLevelTypeInferrer,
+        null,
+        intType,
+        "index",
+        finalMask,
+        parent,
+        charOffset,
+        null);
     KernelConstructorBuilder constructorBuilder = new KernelConstructorBuilder(
         null,
         constMask,
@@ -140,7 +151,15 @@
     int index = 0;
     List<MapEntry> toStringEntries = <MapEntry>[];
     KernelFieldBuilder valuesBuilder = new KernelFieldBuilder(
-        null, listType, "values", constMask | staticMask, parent, charOffset);
+        astFactory,
+        parent.loader.topLevelTypeInferrer,
+        null,
+        listType,
+        "values",
+        constMask | staticMask,
+        parent,
+        charOffset,
+        null);
     members["values"] = valuesBuilder;
     KernelProcedureBuilder toStringBuilder = new KernelProcedureBuilder(
         null,
@@ -165,7 +184,15 @@
         continue;
       }
       KernelFieldBuilder fieldBuilder = new KernelFieldBuilder(
-          null, selfType, name, constMask | staticMask, parent, charOffset);
+          astFactory,
+          parent.loader.topLevelTypeInferrer,
+          null,
+          selfType,
+          name,
+          constMask | staticMask,
+          parent,
+          charOffset,
+          null);
       members[name] = fieldBuilder;
       toStringEntries.add(new MapEntry(
           new IntLiteral(index), new StringLiteral("$className.$name")));
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
index 8cb5a8d..40cbe80 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_field_builder.dart
@@ -4,6 +4,20 @@
 
 library fasta.kernel_field_builder;
 
+import 'package:front_end/src/fasta/builder/ast_factory.dart' show AstFactory;
+
+import 'package:front_end/src/fasta/kernel/body_builder.dart' show BodyBuilder;
+
+import 'package:front_end/src/fasta/parser/parser.dart' show Parser;
+
+import 'package:front_end/src/fasta/scanner/token.dart' show Token;
+
+import 'package:front_end/src/fasta/builder/class_builder.dart'
+    show ClassBuilder;
+
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
+    show TypeInferrer;
+
 import 'package:kernel/ast.dart' show Expression, Field, Name;
 
 import 'kernel_builder.dart'
@@ -15,14 +29,25 @@
         MetadataBuilder;
 
 class KernelFieldBuilder extends FieldBuilder<Expression> {
+  final AstFactory astFactory;
+  final TypeInferrer typeInferrer;
   final Field field;
   final List<MetadataBuilder> metadata;
   final KernelTypeBuilder type;
+  final Token initializerToken;
 
-  KernelFieldBuilder(this.metadata, this.type, String name, int modifiers,
-      Builder compilationUnit, int charOffset)
-      : field = new Field(null, fileUri: compilationUnit?.relativeFileUri)
-          ..fileOffset = charOffset,
+  KernelFieldBuilder(
+      this.astFactory,
+      this.typeInferrer,
+      this.metadata,
+      this.type,
+      String name,
+      int modifiers,
+      Builder compilationUnit,
+      int charOffset,
+      this.initializerToken)
+      : field = astFactory.field(null, charOffset,
+            fileUri: compilationUnit?.relativeFileUri),
         super(name, modifiers, compilationUnit, charOffset);
 
   void set initializer(Expression value) {
@@ -35,13 +60,44 @@
       field.type = type.build(library);
     }
     bool isInstanceMember = !isStatic && !isTopLevel;
-    return field
+    field
       ..isFinal = isFinal
       ..isConst = isConst
       ..hasImplicitGetter = isInstanceMember
       ..hasImplicitSetter = isInstanceMember && !isConst && !isFinal
       ..isStatic = !isInstanceMember;
+    if (initializerToken != null) {
+      typeInferrer.recordField(field);
+    }
+    return field;
   }
 
   Field get target => field;
+
+  @override
+  void prepareInitializerInference(TypeInferrer typeInferrer,
+      LibraryBuilder library, ClassBuilder currentClass) {
+    if (initializerToken != null) {
+      var memberScope =
+          currentClass == null ? library.scope : currentClass.scope;
+      var bodyBuilder = new BodyBuilder(
+          library,
+          this,
+          memberScope,
+          null,
+          typeInferrer.classHierarchy,
+          typeInferrer.coreTypes,
+          currentClass,
+          isInstanceMember,
+          library.uri,
+          typeInferrer,
+          astFactory,
+          fieldDependencies: typeInferrer.getFieldDependencies(field));
+      Parser parser = new Parser(bodyBuilder);
+      Token token = parser.parseExpression(initializerToken);
+      Expression expression = bodyBuilder.popForValue();
+      bodyBuilder.checkEmpty(token.charOffset);
+      initializer = expression;
+    }
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index 0f87d31..ba5c121 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
@@ -4,6 +4,8 @@
 
 library fasta.kernel_library_builder;
 
+import 'package:front_end/src/fasta/scanner/token.dart' show Token;
+
 import 'package:kernel/ast.dart';
 
 import 'package:kernel/clone.dart' show CloneVisitor;
@@ -160,11 +162,11 @@
   }
 
   void addField(List<MetadataBuilder> metadata, int modifiers,
-      KernelTypeBuilder type, String name, int charOffset) {
+      KernelTypeBuilder type, String name, int charOffset, Token initializer) {
     addBuilder(
         name,
-        new KernelFieldBuilder(
-            metadata, type, name, modifiers, this, charOffset),
+        new KernelFieldBuilder(loader.astFactory, loader.topLevelTypeInferrer,
+            metadata, type, name, modifiers, this, charOffset, initializer),
         charOffset);
   }
 
@@ -295,8 +297,8 @@
       List<Object> constantNamesAndOffsets, int charOffset, int charEndOffset) {
     addBuilder(
         name,
-        new KernelEnumBuilder(metadata, name, constantNamesAndOffsets, this,
-            charOffset, charEndOffset),
+        new KernelEnumBuilder(loader.astFactory, metadata, name,
+            constantNamesAndOffsets, this, charOffset, charEndOffset),
         charOffset);
   }
 
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 38e4483..a761ab2 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
@@ -20,8 +20,6 @@
 import 'package:front_end/src/base/instrumentation.dart';
 import 'package:front_end/src/fasta/type_inference/type_inferrer.dart';
 import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/core_types.dart';
 
 /// Concrete shadow object representing a statement block in kernel form.
 class KernelBlock extends Block implements KernelStatement {
@@ -44,6 +42,36 @@
       KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded);
 }
 
+/// Concrete shadow object representing a field in kernel form.
+class KernelField extends Field {
+  bool _implicitlyTyped = true;
+
+  FieldNode<KernelField> _fieldNode;
+
+  bool _isInferred = false;
+
+  KernelField(Name name, {String fileUri}) : super(name, fileUri: fileUri) {}
+
+  @override
+  void set type(DartType value) {
+    _implicitlyTyped = false;
+    super.type = value;
+  }
+
+  String get _fileUri {
+    // TODO(paulberry): This is a hack.  We should use this.fileUri, because we
+    // want the URI of the compilation unit.  But that gives a relative URI,
+    // and I don't know what it's relative to or how to convert it to an
+    // absolute URI.
+    return enclosingLibrary.importUri.toString();
+  }
+
+  void _setInferredType(DartType inferredType) {
+    _isInferred = true;
+    super.type = inferredType;
+  }
+}
+
 /// Concrete shadow object representing a function expression in kernel form.
 class KernelFunctionExpression extends FunctionExpression
     implements KernelExpression {
@@ -110,13 +138,70 @@
   void _inferStatement(KernelTypeInferrer inferrer);
 }
 
+/// Concrete shadow object representing a read of a static variable in kernel
+/// form.
+class KernelStaticGet extends StaticGet implements KernelExpression {
+  KernelStaticGet(Member target) : super(target);
+
+  @override
+  DartType _inferExpression(
+      KernelTypeInferrer inferrer, DartType typeContext, bool typeNeeded) {
+    return inferrer.inferStaticGet(typeContext, typeNeeded, target.getterType);
+  }
+}
+
 /// Concrete implementation of [TypeInferrer] specialized to work with kernel
 /// objects.
 class KernelTypeInferrer extends TypeInferrer<Statement, Expression,
-    KernelVariableDeclaration, Field> {
-  KernelTypeInferrer(CoreTypes coreTypes, ClassHierarchy classHierarchy,
-      Instrumentation instrumentation, bool strongMode)
-      : super(coreTypes, classHierarchy, instrumentation, strongMode);
+    KernelVariableDeclaration, KernelField> {
+  KernelTypeInferrer(Instrumentation instrumentation, bool strongMode)
+      : super(instrumentation, strongMode);
+
+  @override
+  void clearFieldInitializer(KernelField field) {
+    field.initializer = null;
+  }
+
+  @override
+  FieldNode<KernelField> createFieldNode(KernelField field) {
+    FieldNode<KernelField> fieldNode = new FieldNode<KernelField>(this, field);
+    field._fieldNode = fieldNode;
+    return fieldNode;
+  }
+
+  @override
+  DartType getFieldDeclaredType(KernelField field) {
+    return field._implicitlyTyped ? null : field.type;
+  }
+
+  @override
+  List<FieldNode<KernelField>> getFieldDependencies(KernelField field) {
+    return field._fieldNode?.dependencies;
+  }
+
+  @override
+  Expression getFieldInitializer(KernelField field) {
+    return field.initializer;
+  }
+
+  @override
+  FieldNode<KernelField> getFieldNodeForReadTarget(Member readTarget) {
+    if (readTarget is KernelField) {
+      return readTarget._fieldNode;
+    } else {
+      return null;
+    }
+  }
+
+  @override
+  int getFieldOffset(KernelField field) {
+    return field.fileOffset;
+  }
+
+  @override
+  String getFieldUri(KernelField field) {
+    return field._fileUri;
+  }
 
   @override
   DartType inferExpression(
@@ -153,6 +238,16 @@
       // everything, this case should no longer be needed.
     }
   }
+
+  @override
+  bool isFieldInferred(KernelField field) {
+    return field._isInferred;
+  }
+
+  @override
+  void setFieldInferredType(KernelField field, DartType inferredType) {
+    field._setInferredType(inferredType);
+  }
 }
 
 /// Concrete shadow object representing a variable declaration in kernel form.
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
index 4c1a56b..80c5d37 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -230,6 +230,7 @@
   Future<Program> writeOutline(Uri uri) async {
     if (loader.first == null) return null;
     try {
+      loader.createTopLevelTypeInferrer();
       await loader.buildOutlines();
       loader.coreLibrary
           .becomeCoreLibrary(const DynamicType(), const VoidType());
@@ -247,6 +248,8 @@
       program = link(new List<Library>.from(loader.libraries));
       loader.computeHierarchy(program);
       loader.checkOverrides(sourceClasses);
+      loader.prepareInitializerInference();
+      loader.performInitializerInference();
       if (uri == null) return program;
       return await writeLinkedProgram(uri, program, isFullProgram: false);
     } on InputError catch (e) {
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index bff471f..1649d78 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -415,7 +415,7 @@
 
   /// Handle the end of a field initializer.  Substructures:
   /// - Initializer expression
-  void endFieldInitializer(Token assignment) {
+  void endFieldInitializer(Token assignment, Token token) {
     logEvent("FieldInitializer");
   }
 
diff --git a/pkg/front_end/lib/src/fasta/parser/parser.dart b/pkg/front_end/lib/src/fasta/parser/parser.dart
index 9f0a11a..e58160a 100644
--- a/pkg/front_end/lib/src/fasta/parser/parser.dart
+++ b/pkg/front_end/lib/src/fasta/parser/parser.dart
@@ -1619,7 +1619,7 @@
       Token assignment = token;
       listener.beginFieldInitializer(token);
       token = parseExpression(token.next);
-      listener.endFieldInitializer(assignment);
+      listener.endFieldInitializer(assignment, token);
     } else {
       listener.handleNoFieldInitializer(token);
     }
diff --git a/pkg/front_end/lib/src/fasta/source/diet_listener.dart b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
index ad185de..3929431 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -135,7 +135,7 @@
   }
 
   @override
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     debugEvent("FieldInitializer");
   }
 
@@ -421,6 +421,8 @@
   }
 
   void buildFields(Token token, bool isTopLevel, MemberBuilder builder) {
+    // TODO(paulberry): don't re-parse the field if we've already parsed it
+    // for type inference.
     parseFields(createListener(builder, memberScope, builder.isInstanceMember),
         token, isTopLevel);
   }
diff --git a/pkg/front_end/lib/src/fasta/source/outline_builder.dart b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
index 20d3289..12ef5d5 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -653,11 +653,11 @@
   @override
   void endTopLevelFields(int count, Token beginToken, Token endToken) {
     debugEvent("endTopLevelFields");
-    List namesAndOffsets = popList(count * 2);
+    List namesOffsetsAndInitializers = popList(count * 4);
     TypeBuilder type = pop();
     int modifiers = Modifier.validate(pop());
     List<MetadataBuilder> metadata = pop();
-    library.addFields(metadata, modifiers, type, namesAndOffsets);
+    library.addFields(metadata, modifiers, type, namesOffsetsAndInitializers);
     checkEmpty(beginToken.charOffset);
   }
 
@@ -665,11 +665,11 @@
   void endFields(
       int count, Token covariantToken, Token beginToken, Token endToken) {
     debugEvent("Fields");
-    List namesAndOffsets = popList(count * 2);
+    List namesOffsetsAndInitializers = popList(count * 4);
     TypeBuilder type = pop();
     int modifiers = Modifier.validate(pop());
     List<MetadataBuilder> metadata = pop();
-    library.addFields(metadata, modifiers, type, namesAndOffsets);
+    library.addFields(metadata, modifiers, type, namesOffsetsAndInitializers);
   }
 
   @override
@@ -751,14 +751,17 @@
   }
 
   @override
-  void endFieldInitializer(Token assignmentOperator) {
+  void endFieldInitializer(Token assignmentOperator, Token token) {
     debugEvent("FieldInitializer");
-    // Ignoring field initializers for now.
+    push(assignmentOperator.next);
+    push(token);
   }
 
   @override
   void handleNoFieldInitializer(Token token) {
     debugEvent("NoFieldInitializer");
+    push(NullValue.FieldInitializer);
+    push(NullValue.FieldInitializer);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
index ab99c7e..475af67 100644
--- a/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_class_builder.dart
@@ -4,6 +4,12 @@
 
 library fasta.source_class_builder;
 
+import 'package:front_end/src/fasta/builder/class_builder.dart'
+    show ClassBuilder;
+
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
+    show TypeInferrer;
+
 import 'package:kernel/ast.dart'
     show Class, Constructor, Supertype, TreeNode, setParents;
 
@@ -147,4 +153,12 @@
     memberBuilder.next = constructorScopeBuilder[name];
     constructorScopeBuilder.addMember(name, memberBuilder);
   }
+
+  @override
+  void prepareInitializerInference(TypeInferrer typeInferrer,
+      LibraryBuilder library, ClassBuilder currentClass) {
+    scope.forEach((name, builder) {
+      builder.prepareInitializerInference(typeInferrer, library, this);
+    });
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
index 8c552e4..3a0985f 100644
--- a/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_library_builder.dart
@@ -4,6 +4,11 @@
 
 library fasta.source_library_builder;
 
+import 'package:front_end/src/fasta/scanner/token.dart' show SymbolToken, Token;
+
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
+    show TypeInferrer;
+
 import 'package:kernel/ast.dart' show AsyncMarker, ProcedureKind;
 
 import '../combinator.dart' show Combinator;
@@ -171,14 +176,23 @@
       int charOffset);
 
   void addField(List<MetadataBuilder> metadata, int modifiers, T type,
-      String name, int charOffset);
+      String name, int charOffset, Token initializer);
 
   void addFields(List<MetadataBuilder> metadata, int modifiers, T type,
-      List<Object> namesAndOffsets) {
-    for (int i = 0; i < namesAndOffsets.length; i += 2) {
-      String name = namesAndOffsets[i];
-      int charOffset = namesAndOffsets[i + 1];
-      addField(metadata, modifiers, type, name, charOffset);
+      List<Object> namesOffsetsAndInitializers) {
+    for (int i = 0; i < namesOffsetsAndInitializers.length; i += 4) {
+      String name = namesOffsetsAndInitializers[i];
+      int charOffset = namesOffsetsAndInitializers[i + 1];
+      Token initializer;
+      if (type == null) {
+        initializer = namesOffsetsAndInitializers[i + 2];
+        Token afterInitializer = namesOffsetsAndInitializers[i + 3];
+        // TODO(paulberry): figure out a way to do this without using
+        // Token.previous.
+        afterInitializer?.previous
+            ?.setNext(new SymbolToken.eof(afterInitializer.offset));
+      }
+      addField(metadata, modifiers, type, name, charOffset, initializer);
     }
   }
 
@@ -469,6 +483,14 @@
 
   @override
   String get fullNameForErrors => name ?? "<library '$relativeFileUri'>";
+
+  @override
+  void prepareInitializerInference(TypeInferrer typeInferrer,
+      LibraryBuilder library, ClassBuilder currentClass) {
+    forEach((String name, Builder member) {
+      member.prepareInitializerInference(typeInferrer, library, currentClass);
+    });
+  }
 }
 
 /// Unlike [Scope], this scope is used during construction of builders to
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 7799c30..4211963 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -10,12 +10,20 @@
 
 import 'package:front_end/src/base/instrumentation.dart' show Instrumentation;
 
+import 'package:front_end/src/fasta/builder/ast_factory.dart' show AstFactory;
+
+import 'package:front_end/src/fasta/kernel/kernel_ast_factory.dart'
+    show KernelAstFactory;
+
 import 'package:front_end/src/fasta/kernel/kernel_shadow_ast.dart'
     show KernelTypeInferrer;
 
 import 'package:front_end/src/fasta/kernel/kernel_target.dart'
     show KernelTarget;
 
+import 'package:front_end/src/fasta/type_inference/type_inferrer.dart'
+    show TypeInferrer;
+
 import 'package:kernel/ast.dart' show Program;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
@@ -56,6 +64,10 @@
   ClassHierarchy hierarchy;
   CoreTypes coreTypes;
 
+  final AstFactory astFactory = new KernelAstFactory();
+
+  TypeInferrer topLevelTypeInferrer;
+
   Instrumentation instrumentation;
 
   SourceLoader(KernelTarget target) : super(target);
@@ -129,9 +141,8 @@
   KernelTarget get target => super.target;
 
   DietListener createDietListener(LibraryBuilder library) {
-    var typeInferrer = new KernelTypeInferrer(
-        coreTypes, hierarchy, instrumentation, target.strongMode);
-    return new DietListener(library, hierarchy, coreTypes, typeInferrer);
+    return new DietListener(
+        library, hierarchy, coreTypes, createLocalTypeInferrer());
   }
 
   void resolveParts() {
@@ -368,5 +379,40 @@
     ticker.logMs("Checked overrides");
   }
 
+  void createTopLevelTypeInferrer() {
+    topLevelTypeInferrer =
+        new KernelTypeInferrer(instrumentation, target.strongMode);
+  }
+
+  /// Performs the first phase of top level initializer inference, which
+  /// consists of creating kernel objects for all fields and top level variables
+  /// that might be subject to type inference, and records dependencies between
+  /// them.
+  void prepareInitializerInference() {
+    topLevelTypeInferrer.coreTypes = coreTypes;
+    topLevelTypeInferrer.classHierarchy = hierarchy;
+    builders.forEach((Uri uri, LibraryBuilder library) {
+      if (library is SourceLibraryBuilder) {
+        library.prepareInitializerInference(
+            topLevelTypeInferrer, library, null);
+      }
+    });
+    ticker.logMs("Prepared initializer inference");
+  }
+
+  /// Performs the second phase of top level initializer inference, which is to
+  /// visit fields and top level variables in topologically-sorted order and
+  /// assign their types.
+  void performInitializerInference() {
+    topLevelTypeInferrer.performInitializerInference();
+    ticker.logMs("Performed initializer inference");
+  }
+
+  /// Creates the type inferrer that should be used inside of method bodies.
+  TypeInferrer createLocalTypeInferrer() {
+    // For kernel, the top level and local type inferrers are the same.
+    return topLevelTypeInferrer;
+  }
+
   List<Uri> getDependencies() => sourceBytes.keys.toList();
 }
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 b7fc206..e328500 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
@@ -3,10 +3,35 @@
 // BSD-style license that can be found in the LICENSE.md file.
 
 import 'package:front_end/src/base/instrumentation.dart';
-import 'package:kernel/ast.dart' show DartType;
+import 'package:front_end/src/dependency_walker.dart' as dependencyWalker;
+import 'package:kernel/ast.dart' show DartType, DynamicType, Member;
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/core_types.dart';
 
+/// Data structure for tracking dependencies between fields 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().
+/// (This should allow us to drop the _typeInferrer field).
+class FieldNode<F> extends dependencyWalker.Node<FieldNode<F>> {
+  final TypeInferrer _typeInferrer;
+
+  final F _field;
+
+  final dependencies = <FieldNode<F>>[];
+
+  FieldNode(this._typeInferrer, this._field);
+
+  @override
+  bool get isEvaluated => _typeInferrer.isFieldInferred(_field);
+
+  @override
+  List<FieldNode<F>> computeDependencies() {
+    return dependencies;
+  }
+}
+
 /// Abstract implementation of type inference which is independent of the
 /// underlying AST representation (but still uses DartType from kernel).
 ///
@@ -17,27 +42,59 @@
 /// statements, expressions, variable declarations, and field declarations,
 /// respectively.
 abstract class TypeInferrer<S, E, V, F> {
-  final CoreTypes coreTypes;
-
-  final ClassHierarchy classHierarchy;
-
   final Instrumentation instrumentation;
 
   final bool strongMode;
 
+  final fieldNodes = <FieldNode<F>>[];
+
+  CoreTypes coreTypes;
+
+  ClassHierarchy classHierarchy;
+
   /// The URI of the code for which type inference is currently being
   /// performed--this is used for testing.
-  Uri uri;
+  String uri;
 
-  TypeInferrer(this.coreTypes, this.classHierarchy, this.instrumentation,
-      this.strongMode);
+  /// Indicates whether we are currently performing top level inference.
+  bool isTopLevel = false;
+
+  TypeInferrer(this.instrumentation, this.strongMode);
+
+  /// Cleares the initializer of [field].
+  void clearFieldInitializer(F field);
+
+  /// Creates a [FieldNode] to track dependencies of the given [field].
+  FieldNode<F> createFieldNode(F field);
+
+  /// Gets the declared type of the given [field], or `null` if the type is
+  /// implicit.
+  DartType getFieldDeclaredType(F field);
+
+  /// Gets the list of top level type inference dependencies of the given
+  /// [field].
+  List<FieldNode<F>> getFieldDependencies(F field);
+
+  /// Gets the initializer for the given [field], or `null` if there is no
+  /// initializer.
+  E getFieldInitializer(F field);
+
+  /// Gets the [FieldNode] corresponding to the given [readTarget], if any.
+  FieldNode<F> getFieldNodeForReadTarget(Member readTarget);
+
+  /// Gets the character offset of the declaration of [field] within its
+  /// compilation unit.
+  int getFieldOffset(F field);
+
+  /// Gets the URI of the compilation unit the [field] is declared in.
+  String getFieldUri(F field);
 
   /// Performs type inference on a method with the given method [body].
   ///
   /// [uri] is the URI of the file the method is contained in--this is used for
   /// testing.
   void inferBody(S body, Uri uri) {
-    this.uri = uri;
+    this.uri = uri.toString();
     inferStatement(body);
   }
 
@@ -52,6 +109,43 @@
   /// the expression type and calls the appropriate specialized "infer" method.
   DartType inferExpression(E expression, DartType typeContext, bool typeNeeded);
 
+  /// Performs type inference on the given [field].
+  void inferField(F field) {
+    var initializer = getFieldInitializer(field);
+    if (initializer != null) {
+      var type = getFieldDeclaredType(field);
+      uri = getFieldUri(field);
+      isTopLevel = true;
+      var inferredType = inferExpression(initializer, type, type == null);
+      if (type == null && strongMode) {
+        instrumentation?.record(
+            'topType',
+            Uri.parse(uri),
+            getFieldOffset(field),
+            new InstrumentationValueForType(inferredType));
+        setFieldInferredType(field, inferredType);
+      }
+      // TODO(paulberry): if type != null, then check that the type of the
+      // initializer is assignable to it.
+      // 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);
+    }
+  }
+
+  /// Makes a note that the given [field] is part of a circularity, so its type
+  /// can't be inferred.
+  void inferFieldCircular(F field) {
+    // TODO(paulberry): report the appropriate error.
+    if (getFieldDeclaredType(field) == null) {
+      var uri = getFieldUri(field);
+      instrumentation?.record('topType', Uri.parse(uri), getFieldOffset(field),
+          const InstrumentationValueLiteral('circular'));
+      setFieldInferredType(field, const DynamicType());
+    }
+  }
+
   /// Performs the core type inference algorithm for integer literals.
   ///
   /// [typeContext], [typeNeeded], and the return value behave as described in
@@ -66,6 +160,18 @@
   /// the statement type and calls the appropriate specialized "infer" method.
   void inferStatement(S statement);
 
+  /// Performs the core type inference algorithm for static variable getters.
+  ///
+  /// [typeContext], [typeNeeded], and the return value behave as described in
+  /// [inferExpression].
+  ///
+  /// [getterType] is the type of the field being referenced, or the return type
+  /// of the getter.
+  DartType inferStaticGet(
+      DartType typeContext, bool typeNeeded, DartType getterType) {
+    return typeNeeded ? getterType : null;
+  }
+
   /// Performs the core type inference algorithm for variable declarations.
   ///
   /// [declaredType] is the declared type of the variable, or `null` if the type
@@ -79,9 +185,50 @@
     var inferredType =
         inferExpression(initializer, declaredType, declaredType == null);
     if (strongMode && declaredType == null) {
-      instrumentation?.record(
-          'type', uri, offset, new InstrumentationValueForType(inferredType));
+      instrumentation?.record('type', Uri.parse(uri), offset,
+          new InstrumentationValueForType(inferredType));
       setType(inferredType);
     }
   }
+
+  /// Determines if top level type inference has been completed for [field].
+  bool isFieldInferred(F field);
+
+  /// Performs top level type inference for all fields that have been passed to
+  /// [recordField].
+  void performInitializerInference() {
+    for (var fieldNode in fieldNodes) {
+      if (fieldNode.isEvaluated) continue;
+      new _FieldWalker<F>().walk(fieldNode);
+    }
+  }
+
+  /// Records that the given [field] will need top level type inference.
+  void recordField(F field) {
+    fieldNodes.add(createFieldNode(field));
+  }
+
+  /// Stores [inferredType] as the inferred type of [field].
+  void setFieldInferredType(F field, DartType inferredType);
+}
+
+/// Subtype of [dependencyWalker.DependencyWalker] which is specialized to
+/// perform top level type inference.
+class _FieldWalker<F> extends dependencyWalker.DependencyWalker<FieldNode<F>> {
+  _FieldWalker();
+
+  @override
+  void evaluate(FieldNode<F> f) {
+    f._typeInferrer.inferField(f._field);
+  }
+
+  @override
+  void evaluateScc(List<FieldNode<F>> scc) {
+    for (var f in scc) {
+      f._typeInferrer.inferFieldCircular(f._field);
+    }
+    for (var f in scc) {
+      f._typeInferrer.inferField(f._field);
+    }
+  }
 }
diff --git a/pkg/front_end/test/fasta/kompile.status b/pkg/front_end/test/fasta/kompile.status
index bd47ede..ca6751c 100644
--- a/pkg/front_end/test/fasta/kompile.status
+++ b/pkg/front_end/test/fasta/kompile.status
@@ -48,6 +48,7 @@
 stringliteral: Crash
 super_rasta_copy: Crash
 top_level_accessors: Crash
+inference/toplevel_inference_toplevel_var: Crash
 type_variable_as_super: Fail
 typedef: Crash
 uninitialized_fields: Crash
diff --git a/pkg/front_end/test/subpackage_relationships_test.dart b/pkg/front_end/test/subpackage_relationships_test.dart
index 05209e8..514136d 100644
--- a/pkg/front_end/test/subpackage_relationships_test.dart
+++ b/pkg/front_end/test/subpackage_relationships_test.dart
@@ -58,6 +58,7 @@
     'lib/src/fasta',
     'lib/src/fasta/parser',
     'lib/src/fasta/source',
+    'lib/src/fasta/type_inference',
     'lib/src/fasta/util',
   ]),
   'lib/src/fasta/dill': new SubpackageRules(allowedDependencies: [
@@ -108,6 +109,7 @@
     'lib/src/fasta/scanner',
   ]),
   'lib/src/fasta/type_inference': new SubpackageRules(allowedDependencies: [
+    'lib/src',
     'lib/src/base',
   ]),
   'lib/src/fasta/util': new SubpackageRules(),
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart
new file mode 100644
index 0000000..a2056d4
--- /dev/null
+++ b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart
@@ -0,0 +1,6 @@
+/*@testedFeatures=inference*/
+var /*@topType=dart.core::int*/ i = 0;
+
+main() {
+  var /*@type=dart.core::int*/ j = i;
+}
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.expect b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.expect
new file mode 100644
index 0000000..6996828
--- /dev/null
+++ b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.direct.expect
@@ -0,0 +1,7 @@
+library;
+import self as self;
+
+static field dynamic i = 0;
+static method main() → dynamic {
+  dynamic j = self::i;
+}
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.outline.expect b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.outline.expect
new file mode 100644
index 0000000..1ac6116
--- /dev/null
+++ b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.outline.expect
@@ -0,0 +1,6 @@
+library;
+import self as self;
+
+static field dynamic i;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.strong.expect b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.strong.expect
new file mode 100644
index 0000000..48c5648
--- /dev/null
+++ b/pkg/front_end/testcases/inference/toplevel_inference_toplevel_var.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::int i = 0;
+static method main() → dynamic {
+  core::int j = self::i;
+}