[dart2js] Small improvements to record type inference.

Change-Id: Iec3bf6f639e5047327866810e3847ce1925e8d8f
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/304580
Reviewed-by: Mayank Patke <fishythefish@google.com>
Commit-Queue: Nate Biggs <natebiggs@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart
index 932c822..2356ffd 100644
--- a/pkg/compiler/lib/src/inferrer/engine.dart
+++ b/pkg/compiler/lib/src/inferrer/engine.dart
@@ -804,7 +804,6 @@
     _workQueue.addAll(types.allocatedTypes);
     _workQueue.addAll(types.allocatedClosures);
     _workQueue.addAll(types.allocatedCalls);
-    _workQueue.addAll(types.allocatedRecords.values);
   }
 
   /// Update the inputs to parameters in the graph. [remove] tells whether
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 21f0970..058042c 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -359,9 +359,12 @@
         if (user is RecordFieldAccessTypeInformation) {
           final getterIndex =
               record.recordShape.indexOfGetterName(user.getterName);
-          if (user.receiver != flow ||
-              record.fieldTypes.indexOf(currentUser!) != getterIndex) return;
-          addNewEscapeInformation(user);
+          if (user.receiver == flow &&
+              getterIndex >= 0 &&
+              getterIndex < record.fieldTypes.length &&
+              record.fieldTypes[getterIndex] == currentUser) {
+            addNewEscapeInformation(user);
+          }
         }
       });
     });
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 0455a8c..b2e4764 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -2104,13 +2104,11 @@
 /// constants and literals.
 class RecordTypeInformation extends TypeInformation with TracedTypeInformation {
   final RecordShape recordShape;
-  final AbstractValue originalType;
-
   final List<TypeInformation> fieldTypes;
 
-  RecordTypeInformation(MemberTypeInformation? context, this.originalType,
-      this.recordShape, this.fieldTypes)
-      : super(originalType, context) {
+  RecordTypeInformation(
+      super.type, super.context, this.recordShape, this.fieldTypes)
+      : super.noInputs() {
     for (final fieldType in fieldTypes) {
       fieldType.addUser(this);
     }
@@ -2137,8 +2135,14 @@
   }
 
   @override
-  // TODO(50701): This could be a top type of the record shape.
-  AbstractValue safeType(InferrerEngine inferrer) => originalType;
+  AbstractValue safeType(InferrerEngine inferrer) {
+    final shapeClass = inferrer.closedWorld.recordData
+        .representationForShape(recordShape)
+        ?.cls;
+    return shapeClass != null
+        ? inferrer.abstractValueDomain.createNonNullSubtype(shapeClass)
+        : inferrer.abstractValueDomain.recordType;
+  }
 
   @override
   bool hasStableType(InferrerEngine inferrer) {
@@ -2188,7 +2192,11 @@
   @override
   AbstractValue computeType(InferrerEngine inferrer) {
     final recordType = receiver.type;
-    if (!inferrer.abstractValueDomain.isRecord(recordType)) {
+    if (inferrer.abstractValueDomain.isEmpty(recordType).isDefinitelyTrue) {
+      // These field accesses should begin at empty until we have a type for the
+      // receiver.
+      return inferrer.abstractValueDomain.emptyType;
+    } else if (!inferrer.abstractValueDomain.isRecord(recordType)) {
       return safeType(inferrer);
     }
     final getterType = inferrer.abstractValueDomain
diff --git a/pkg/compiler/lib/src/inferrer/type_system.dart b/pkg/compiler/lib/src/inferrer/type_system.dart
index dfa591e..447ca18 100644
--- a/pkg/compiler/lib/src/inferrer/type_system.dart
+++ b/pkg/compiler/lib/src/inferrer/type_system.dart
@@ -539,9 +539,10 @@
       allocatedTypes.add(getterType);
     }
 
-    final record = RecordTypeInformation(currentMember,
-        _abstractValueDomain.recordType, recordType.shape, fieldTypes);
+    final record = RecordTypeInformation(_abstractValueDomain.recordType,
+        currentMember, recordType.shape, fieldTypes);
     allocatedRecords[node] = record;
+    allocatedTypes.add(record);
     return record;
   }