Use promoted type to infer for-each iterables.

Fixes #42653.

Change-Id: I90319b775207e6cc1c6b7a79d29b2c237b750845
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162625
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Paul Berry <paulberry@google.com>
diff --git a/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart
new file mode 100644
index 0000000..45304e0
--- /dev/null
+++ b/pkg/_fe_analyzer_shared/test/flow_analysis/type_promotion/data/bug42653.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2020, 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.
+
+void forEachStatement(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    for (x in [0]) {
+      /*int*/ x;
+    }
+  }
+}
+
+forEachElementInListLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return [
+      for (x in [0]) /*int*/ x
+    ];
+  }
+}
+
+forEachElementInMapLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return {
+      for (x in [0]) /*int*/ x: /*int*/ x
+    };
+  }
+}
+
+forEachElementInSetLiteral(Object x) {
+  if (x is int) {
+    /*int*/ x;
+    return {
+      for (x in [0]) /*int*/ x
+    };
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
index 454eeef..8946ab4 100644
--- a/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/for_resolver.dart
@@ -100,7 +100,7 @@
     if (identifier != null) {
       identifierElement = identifier.staticElement;
       if (identifierElement is VariableElement) {
-        valueType = identifierElement.type;
+        valueType = _resolver.localVariableTypeProvider.getType(identifier);
       } else if (identifierElement is PropertyAccessorElement) {
         var parameters = identifierElement.parameters;
         if (parameters.isNotEmpty) {
diff --git a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
index a956473..f823190 100644
--- a/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/inference_visitor.dart
@@ -6061,8 +6061,14 @@
 
   LocalForInVariable(this.variableSet);
 
-  DartType computeElementType(TypeInferrerImpl inferrer) =>
-      variableSet.variable.type;
+  DartType computeElementType(TypeInferrerImpl inferrer) {
+    VariableDeclaration variable = variableSet.variable;
+    DartType promotedType;
+    if (inferrer.isNonNullableByDefault) {
+      promotedType = inferrer.flowAnalysis.promotedType(variable);
+    }
+    return promotedType ?? variable.type;
+  }
 
   Expression inferAssignment(TypeInferrerImpl inferrer, DartType rhsType) {
     Expression rhs = inferrer.ensureAssignable(