Convert ShadowMapLiteral to MapLiteralJudgment

Change-Id: I06ee11f873a00d119b07a4cf7aca50257a315000
Reviewed-on: https://dart-review.googlesource.com/61562
Commit-Queue: Dmitry Stefantsov <dmitryas@google.com>
Reviewed-by: Paul Berry <paulberry@google.com>
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Reviewed-by: Kevin Millikin <kmillikin@google.com>
diff --git a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
index ac59351..b091616 100644
--- a/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/fangorn.dart
@@ -81,32 +81,33 @@
         DoJudgment,
         DoubleJudgment,
         EmptyStatementJudgment,
+        ExpressionStatementJudgment,
+        ForJudgment,
+        IfJudgment,
         IntJudgment,
         IsJudgment,
         IsNotJudgment,
         LabeledStatementJudgment,
-        LoadLibraryJudgment,
-        NullJudgment,
-        ExpressionStatementJudgment,
-        ForJudgment,
-        IfJudgment,
         ListLiteralJudgment,
+        LoadLibraryJudgment,
         LogicalJudgment,
-        ShadowMapLiteral,
+        MapEntryJudgment,
+        MapLiteralJudgment,
         NotJudgment,
+        NullJudgment,
         RethrowJudgment,
         ReturnJudgment,
         StringConcatenationJudgment,
         StringLiteralJudgment,
         SymbolLiteralJudgment,
         SyntheticExpressionJudgment,
-        TryCatchJudgment,
-        TryFinallyJudgment,
-        WhileJudgment,
-        YieldJudgment,
         ThisJudgment,
         ThrowJudgment,
-        TypeLiteralJudgment;
+        TryCatchJudgment,
+        TryFinallyJudgment,
+        TypeLiteralJudgment,
+        WhileJudgment,
+        YieldJudgment;
 
 import 'forest.dart'
     show
@@ -190,7 +191,7 @@
   }
 
   @override
-  ShadowMapLiteral literalMap(
+  MapLiteralJudgment literalMap(
       Token constKeyword,
       bool isConst,
       DartType keyType,
@@ -201,7 +202,7 @@
       Token rightBracket) {
     // TODO(brianwilkerson): The file offset computed below will not be correct
     // if there are type arguments but no `const` keyword.
-    return new ShadowMapLiteral(
+    return new MapLiteralJudgment(
         constKeyword, leftBracket, entries, rightBracket,
         keyType: keyType, valueType: valueType, isConst: isConst)
       ..fileOffset = offsetForToken(constKeyword ?? leftBracket);
@@ -235,12 +236,12 @@
 
   @override
   MapEntry mapEntry(Expression key, Token colon, Expression value) {
-    return new MapEntry(key, value)..fileOffset = offsetForToken(colon);
+    return new MapEntryJudgment(key, value)..fileOffset = offsetForToken(colon);
   }
 
   @override
   List<MapEntry> mapEntryList(int length) {
-    return new List<MapEntry>.filled(length, null, growable: true);
+    return new List<MapEntryJudgment>.filled(length, null, growable: true);
   }
 
   @override
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 bad7b08..c4b13df 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
@@ -2002,23 +2002,55 @@
   }
 }
 
-/// Shadow object for [MapLiteral].
-class ShadowMapLiteral extends MapLiteral implements ExpressionJudgment {
+/// Type inference derivation for [MapEntry].
+///
+/// This derivation is needed for uniformity.
+class MapEntryJudgment extends MapEntry {
+  DartType inferredKeyType;
+  DartType inferredValueType;
+
+  ExpressionJudgment get keyJudgment => key;
+
+  ExpressionJudgment get valueJudgment => value;
+
+  MapEntryJudgment(Expression key, Expression value) : super(key, value);
+
+  MapEntry infer<Expression, Statement, Initializer, Type>(
+      ShadowTypeInferrer inferrer,
+      Factory<Expression, Statement, Initializer, Type> factory,
+      DartType keyTypeContext,
+      DartType valueTypeContext) {
+    ExpressionJudgment keyJudgment = this.keyJudgment;
+    inferrer.inferExpression(factory, keyJudgment, keyTypeContext, true);
+    inferredKeyType = keyJudgment.inferredType;
+
+    ExpressionJudgment valueJudgment = this.valueJudgment;
+    inferrer.inferExpression(factory, valueJudgment, valueTypeContext, true);
+    inferredValueType = valueJudgment.inferredType;
+
+    return null;
+  }
+}
+
+/// Type inference derivation for [MapLiteral].
+class MapLiteralJudgment extends MapLiteral implements ExpressionJudgment {
   final Token constKeyword;
   final Token leftBracket;
   final Token rightBracket;
 
   DartType inferredType;
 
+  List<MapEntryJudgment> get judgments => entries;
+
   final DartType _declaredKeyType;
   final DartType _declaredValueType;
 
-  ShadowMapLiteral(this.constKeyword, this.leftBracket, List<MapEntry> entries,
-      this.rightBracket,
+  MapLiteralJudgment(this.constKeyword, this.leftBracket,
+      List<MapEntryJudgment> judgments, this.rightBracket,
       {DartType keyType, DartType valueType, bool isConst: false})
       : _declaredKeyType = keyType,
         _declaredValueType = valueType,
-        super(entries,
+        super(judgments,
             keyType: keyType ?? const DynamicType(),
             valueType: valueType ?? const DynamicType(),
             isConst: isConst);
@@ -2053,17 +2085,18 @@
       inferredKeyType = _declaredKeyType ?? const DynamicType();
       inferredValueType = _declaredValueType ?? const DynamicType();
     }
+    List<ExpressionJudgment> cachedKeyJudgments =
+        judgments.map((j) => j.keyJudgment).toList();
+    List<ExpressionJudgment> cachedValueJudgments =
+        judgments.map((j) => j.valueJudgment).toList();
     if (inferenceNeeded || typeChecksNeeded) {
-      for (var entry in entries) {
-        var keyType = inferrer.inferExpression(factory, entry.key,
-            inferredKeyType, inferenceNeeded || typeChecksNeeded);
-        var valueType = inferrer.inferExpression(factory, entry.value,
-            inferredValueType, inferenceNeeded || typeChecksNeeded);
+      for (MapEntryJudgment judgment in judgments) {
+        judgment.infer(inferrer, factory, inferredKeyType, inferredValueType);
         if (inferenceNeeded) {
           formalTypes.addAll(mapType.typeArguments);
         }
-        actualTypes.add(keyType);
-        actualTypes.add(valueType);
+        actualTypes.add(judgment.inferredKeyType);
+        actualTypes.add(judgment.inferredValueType);
       }
     }
     if (inferenceNeeded) {
@@ -2086,14 +2119,14 @@
       valueType = inferredValueType;
     }
     if (typeChecksNeeded) {
-      for (int i = 0; i < entries.length; i++) {
-        var entry = entries[i];
-        var key = entry.key;
+      for (int i = 0; i < judgments.length; ++i) {
+        ExpressionJudgment keyJudgment = cachedKeyJudgments[i];
         inferrer.ensureAssignable(
-            keyType, actualTypes[2 * i], key, key.fileOffset);
-        var value = entry.value;
-        inferrer.ensureAssignable(
-            valueType, actualTypes[2 * i + 1], value, value.fileOffset);
+            keyType, actualTypes[2 * i], keyJudgment, keyJudgment.fileOffset);
+
+        ExpressionJudgment valueJudgment = cachedValueJudgments[i];
+        inferrer.ensureAssignable(valueType, actualTypes[2 * i + 1],
+            valueJudgment, valueJudgment.fileOffset);
       }
     }
     inferredType =