Avoid a crash when an invalid assignment is detected during top level inference.

Change-Id: I382a4fdcd25bca529ca424ccdb7fd313d6a95066
Reviewed-on: https://dart-review.googlesource.com/18143
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
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 e131c6a..3f75cb2 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -556,6 +556,7 @@
     // inference info?
     typeInferenceEngine.classHierarchy =
         hierarchy = new IncrementalClassHierarchy();
+    typeInferenceEngine.isTopLevelInferenceComplete = true;
     ticker.logMs("Performed top level inference");
   }
 
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 bd82f5c..bf449b3 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
@@ -189,6 +189,9 @@
 
   CoreTypes get coreTypes;
 
+  /// Indicates when top level type inference is fully completed.
+  void set isTopLevelInferenceComplete(bool value);
+
   /// Indicates whether the "prepare" phase of type inference is complete.
   void set isTypeInferencePrepared(bool value);
 
@@ -256,6 +259,9 @@
   @override
   bool isTypeInferencePrepared = false;
 
+  @override
+  bool isTopLevelInferenceComplete = false;
+
   TypeInferenceEngineImpl(this.instrumentation, this.strongMode);
 
   @override
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 753f8cf..22f63aa 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
@@ -345,7 +345,8 @@
     } else {
       // Insert an implicit downcast.
       if (strongMode) {
-        if (!typeSchemaEnvironment.isSubtypeOf(expectedType, actualType)) {
+        if (engine.isTopLevelInferenceComplete &&
+            !typeSchemaEnvironment.isSubtypeOf(expectedType, actualType)) {
           // Error: not assignable.
           library.addWarning(
               templateInvalidAssignment.withArguments(actualType, expectedType),
diff --git a/pkg/front_end/testcases/ast_builder.status b/pkg/front_end/testcases/ast_builder.status
index 2eb6df6..5e9d7fe 100644
--- a/pkg/front_end/testcases/ast_builder.status
+++ b/pkg/front_end/testcases/ast_builder.status
@@ -362,6 +362,7 @@
 inference_new/infer_instance_field_ref: Crash
 inference_new/infer_instance_field_ref_circular: Crash
 inference_new/infer_logical: Crash
+inference_new/invalid_assignment_during_toplevel_inference: Crash
 inference_new/property_assign_combiner: Crash
 inference_new/property_get_toplevel: Crash
 inference_new/static_assign_combiner: Crash
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart
new file mode 100644
index 0000000..6a6a8ff
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart
@@ -0,0 +1,11 @@
+// Copyright (c) 2017, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*@testedFeatures=warning,inference*/
+
+int i;
+String s;
+var /*@topType=int*/ x = /*@warning=InvalidAssignment*/ i = s;
+
+main() {}
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.expect b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.expect
new file mode 100644
index 0000000..321c94e
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.direct.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::int i;
+static field core::String s;
+static field dynamic x = self::i = self::s;
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.outline.expect b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.outline.expect
new file mode 100644
index 0000000..52eb53b
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.outline.expect
@@ -0,0 +1,9 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::int i;
+static field core::String s;
+static field dynamic x;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.strong.expect b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.strong.expect
new file mode 100644
index 0000000..392bdaf
--- /dev/null
+++ b/pkg/front_end/testcases/inference_new/invalid_assignment_during_toplevel_inference.dart.strong.expect
@@ -0,0 +1,8 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static field core::int i;
+static field core::String s;
+static field core::int x = self::i = self::s as{TypeError} core::int;
+static method main() → dynamic {}