[dart2js] Add tracing of types through records in global inference.
Change-Id: I4abdb76caecc91c89792396ff7d3fe4060cc7bc5
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/289904
Commit-Queue: Nate Biggs <natebiggs@google.com>
Reviewed-by: Stephen Adams <sra@google.com>
diff --git a/pkg/compiler/lib/src/inferrer/engine.dart b/pkg/compiler/lib/src/inferrer/engine.dart
index 6c3d50c..29209c5 100644
--- a/pkg/compiler/lib/src/inferrer/engine.dart
+++ b/pkg/compiler/lib/src/inferrer/engine.dart
@@ -34,6 +34,7 @@
import 'locals_handler.dart';
import 'list_tracer.dart';
import 'map_tracer.dart';
+import 'record_tracer.dart';
import 'set_tracer.dart';
import 'type_graph_dump.dart';
import 'type_graph_nodes.dart';
@@ -311,6 +312,18 @@
_workQueue.add(info);
}
+ void analyzeRecordAndEnqueue(RecordTypeInformation info) {
+ if (info.analyzed) return;
+ info.analyzed = true;
+ RecordTracerVisitor tracer = RecordTracerVisitor(info, this);
+
+ bool succeeded = tracer.run();
+ if (!succeeded) return;
+
+ info.bailedOut = false;
+ _workQueue.add(info);
+ }
+
void runOverAllElements() {
metrics.time.measure(_runOverAllElements);
}
diff --git a/pkg/compiler/lib/src/inferrer/node_tracer.dart b/pkg/compiler/lib/src/inferrer/node_tracer.dart
index 534e958..5eab958 100644
--- a/pkg/compiler/lib/src/inferrer/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer/node_tracer.dart
@@ -104,30 +104,35 @@
int.fromEnvironment('dart2js.tracing.limit', defaultValue: 32);
// TODO(natebiggs): We allow null here to maintain current functionality
// but we should verify we actually need to allow it.
- final Setlet<MemberEntity?> analyzedElements = Setlet<MemberEntity?>();
+ final Setlet<MemberEntity?> analyzedElements = Setlet();
TracerVisitor(this.tracedType, this.inferrer);
/// Work list that gets populated with [TypeInformation] that could
/// contain the container.
- final List<TypeInformation> workList = <TypeInformation>[];
+ final List<TypeInformation> workList = [];
/// Work list of lists to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these
/// lists and we must check how it escapes from these lists.
- final List<ListTypeInformation> listsToAnalyze = <ListTypeInformation>[];
+ final List<ListTypeInformation> listsToAnalyze = [];
/// Work list of sets to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these sets
/// and we must check how it escapes from these sets.
- final List<SetTypeInformation> setsToAnalyze = <SetTypeInformation>[];
+ final List<SetTypeInformation> setsToAnalyze = [];
/// Work list of maps to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these
/// maps and we must check how it escapes from these maps.
- final List<MapTypeInformation> mapsToAnalyze = <MapTypeInformation>[];
+ final List<MapTypeInformation> mapsToAnalyze = [];
- final Setlet<TypeInformation> flowsInto = Setlet<TypeInformation>();
+ /// Work list of records to analyze after analyzing the users of a
+ /// [TypeInformation]. We know the [tracedType] has been stored in these
+ /// records and we must check how it escapes from these records.
+ final List<RecordTypeInformation> recordsToAnalyze = [];
+
+ final Setlet<TypeInformation> flowsInto = Setlet();
// The current [TypeInformation] in the analysis.
TypeInformation? currentUser;
@@ -175,6 +180,9 @@
while (!mapsToAnalyze.isEmpty) {
analyzeStoredIntoMap(mapsToAnalyze.removeLast());
}
+ while (!recordsToAnalyze.isEmpty) {
+ analyzeStoredIntoRecord(recordsToAnalyze.removeLast());
+ }
if (!continueAnalyzing) break;
}
}
@@ -229,9 +237,7 @@
@override
void visitRecordFieldAccessTypeInformation(
- RecordFieldAccessTypeInformation info) {
- addNewEscapeInformation(info);
- }
+ RecordFieldAccessTypeInformation info) {}
@override
void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
@@ -255,8 +261,7 @@
@override
void visitRecordTypeInformation(RecordTypeInformation info) {
- // TODO(50701): Implement better inference for records.
- bailout('Used as field of Record');
+ recordsToAnalyze.add(info);
}
@override
@@ -346,6 +351,22 @@
}
}
+ void analyzeStoredIntoRecord(RecordTypeInformation record) {
+ inferrer.analyzeRecordAndEnqueue(record);
+
+ record.flowsInto.forEach((TypeInformation flow) {
+ flow.users.forEach((TypeInformation user) {
+ if (user is RecordFieldAccessTypeInformation) {
+ final getterIndex =
+ record.recordShape.indexOfGetterName(user.getterName);
+ if (user.receiver != flow ||
+ record.fieldTypes.indexOf(currentUser!) != getterIndex) return;
+ addNewEscapeInformation(user);
+ }
+ });
+ });
+ }
+
/// Checks whether this is a call to a list adding method. The definition of
/// what list adding means has to stay in sync with
/// [isParameterOfListAddingMethod].
diff --git a/pkg/compiler/lib/src/inferrer/record_tracer.dart b/pkg/compiler/lib/src/inferrer/record_tracer.dart
new file mode 100644
index 0000000..67ac017
--- /dev/null
+++ b/pkg/compiler/lib/src/inferrer/record_tracer.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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.
+import 'node_tracer.dart';
+import 'type_graph_nodes.dart';
+
+class RecordTracerVisitor extends TracerVisitor {
+ RecordTracerVisitor(super.tracedType, super.inferrer);
+
+ bool run() {
+ analyze();
+ final record = tracedType as RecordTypeInformation;
+ if (continueAnalyzing) {
+ record.addFlowsIntoTargets(flowsInto);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
index 50c13a4..188af13 100644
--- a/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer/type_graph_nodes.dart
@@ -2052,7 +2052,7 @@
/// A [RecordTypeInformation] is the constructor for a record, used for Record
/// constants and literals.
-class RecordTypeInformation extends TypeInformation {
+class RecordTypeInformation extends TypeInformation with TracedTypeInformation {
final RecordShape recordShape;
final AbstractValue originalType;
diff --git a/pkg/compiler/lib/src/inferrer_experimental/engine.dart b/pkg/compiler/lib/src/inferrer_experimental/engine.dart
index 50a6aef..e9e3a2f 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/engine.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/engine.dart
@@ -35,6 +35,7 @@
import 'locals_handler.dart';
import 'list_tracer.dart';
import 'map_tracer.dart';
+import 'record_tracer.dart';
import 'set_tracer.dart';
import 'type_graph_dump.dart';
import 'type_graph_nodes.dart';
@@ -319,6 +320,18 @@
_workQueue.add(info);
}
+ void analyzeRecordAndEnqueue(RecordTypeInformation info) {
+ if (info.analyzed) return;
+ info.analyzed = true;
+ RecordTracerVisitor tracer = RecordTracerVisitor(info, this);
+
+ bool succeeded = tracer.run();
+ if (!succeeded) return;
+
+ info.bailedOut = false;
+ _workQueue.add(info);
+ }
+
void runOverAllElements() {
metrics.time.measure(_runOverAllElements);
}
diff --git a/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart b/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart
index c5f7340..ed1bce0 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/node_tracer.dart
@@ -104,30 +104,35 @@
int.fromEnvironment('dart2js.tracing.limit', defaultValue: 32);
// TODO(natebiggs): We allow null here to maintain current functionality
// but we should verify we actually need to allow it.
- final Setlet<MemberEntity?> analyzedElements = Setlet<MemberEntity?>();
+ final Setlet<MemberEntity?> analyzedElements = Setlet();
TracerVisitor(this.tracedType, this.inferrer);
/// Work list that gets populated with [TypeInformation] that could
/// contain the container.
- final List<TypeInformation> workList = <TypeInformation>[];
+ final List<TypeInformation> workList = [];
/// Work list of lists to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these
/// lists and we must check how it escapes from these lists.
- final List<ListTypeInformation> listsToAnalyze = <ListTypeInformation>[];
+ final List<ListTypeInformation> listsToAnalyze = [];
/// Work list of sets to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these sets
/// and we must check how it escapes from these sets.
- final List<SetTypeInformation> setsToAnalyze = <SetTypeInformation>[];
+ final List<SetTypeInformation> setsToAnalyze = [];
/// Work list of maps to analyze after analyzing the users of a
/// [TypeInformation]. We know the [tracedType] has been stored in these
/// maps and we must check how it escapes from these maps.
- final List<MapTypeInformation> mapsToAnalyze = <MapTypeInformation>[];
+ final List<MapTypeInformation> mapsToAnalyze = [];
- final Setlet<TypeInformation> flowsInto = Setlet<TypeInformation>();
+ /// Work list of records to analyze after analyzing the users of a
+ /// [TypeInformation]. We know the [tracedType] has been stored in these
+ /// records and we must check how it escapes from these records.
+ final List<RecordTypeInformation> recordsToAnalyze = [];
+
+ final Setlet<TypeInformation> flowsInto = Setlet();
// The current [TypeInformation] in the analysis.
TypeInformation? currentUser;
@@ -175,6 +180,9 @@
while (!mapsToAnalyze.isEmpty) {
analyzeStoredIntoMap(mapsToAnalyze.removeLast());
}
+ while (!recordsToAnalyze.isEmpty) {
+ analyzeStoredIntoRecord(recordsToAnalyze.removeLast());
+ }
if (!continueAnalyzing) break;
}
}
@@ -229,9 +237,7 @@
@override
void visitRecordFieldAccessTypeInformation(
- RecordFieldAccessTypeInformation info) {
- addNewEscapeInformation(info);
- }
+ RecordFieldAccessTypeInformation info) {}
@override
void visitValueInMapTypeInformation(ValueInMapTypeInformation info) {
@@ -255,8 +261,7 @@
@override
void visitRecordTypeInformation(RecordTypeInformation info) {
- // TODO(50701): Implement better inference for records.
- bailout('Used as field of Record');
+ recordsToAnalyze.add(info);
}
@override
@@ -346,6 +351,22 @@
}
}
+ void analyzeStoredIntoRecord(RecordTypeInformation record) {
+ inferrer.analyzeRecordAndEnqueue(record);
+
+ record.flowsInto.forEach((TypeInformation flow) {
+ flow.users.forEach((TypeInformation user) {
+ if (user is RecordFieldAccessTypeInformation) {
+ final getterIndex =
+ record.recordShape.indexOfGetterName(user.getterName);
+ if (user.receiver != flow ||
+ record.fieldTypes.indexOf(currentUser!) != getterIndex) return;
+ addNewEscapeInformation(user);
+ }
+ });
+ });
+ }
+
/// Checks whether this is a call to a list adding method. The definition of
/// what list adding means has to stay in sync with
/// [isParameterOfListAddingMethod].
diff --git a/pkg/compiler/lib/src/inferrer_experimental/record_tracer.dart b/pkg/compiler/lib/src/inferrer_experimental/record_tracer.dart
new file mode 100644
index 0000000..67ac017
--- /dev/null
+++ b/pkg/compiler/lib/src/inferrer_experimental/record_tracer.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2023, 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.
+import 'node_tracer.dart';
+import 'type_graph_nodes.dart';
+
+class RecordTracerVisitor extends TracerVisitor {
+ RecordTracerVisitor(super.tracedType, super.inferrer);
+
+ bool run() {
+ analyze();
+ final record = tracedType as RecordTypeInformation;
+ if (continueAnalyzing) {
+ record.addFlowsIntoTargets(flowsInto);
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart b/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
index 7f9b41a..7633f2f 100644
--- a/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
+++ b/pkg/compiler/lib/src/inferrer_experimental/type_graph_nodes.dart
@@ -2058,7 +2058,7 @@
/// A [RecordTypeInformation] is the constructor for a record, used for Record
/// constants and literals.
-class RecordTypeInformation extends TypeInformation {
+class RecordTypeInformation extends TypeInformation with TracedTypeInformation {
final RecordShape recordShape;
final AbstractValue originalType;
diff --git a/pkg/compiler/test/analysis_options.yaml b/pkg/compiler/test/analysis_options.yaml
index 7d40a1a..03a6cbc 100644
--- a/pkg/compiler/test/analysis_options.yaml
+++ b/pkg/compiler/test/analysis_options.yaml
@@ -10,6 +10,7 @@
exclude:
- '**/data/*'
+ - '**/inference_data/*'
- 'rti/emission/*'
- '**/model_data/*'
- 'deferred_loading/libs/*'
diff --git a/pkg/compiler/test/inference/data/closure_tracer.dart b/pkg/compiler/test/inference/data/closure_tracer.dart
index 2c85938..136ab44 100644
--- a/pkg/compiler/test/inference/data/closure_tracer.dart
+++ b/pkg/compiler/test/inference/data/closure_tracer.dart
@@ -57,11 +57,11 @@
dynamic b = <dynamic, dynamic>{'foo': 1};
b
- /*update: Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+ /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
['bar'] = a;
b
- /*Dictionary([exact=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union(null, [exact=JSExtendableArray], [exact=JSUInt31]), map: {foo: [exact=JSUInt31], bar: Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)})*/
['bar']
/*Container([null|exact=JSExtendableArray], element: [subclass=Closure], length: 1)*/
@@ -127,10 +127,10 @@
return res;
}
-/*member: testStoredInRecord:[null|subclass=Object]*/
+/*member: testStoredInRecord:[null|exact=JSUInt31]*/
testStoredInRecord() {
var res;
- /*[null|subclass=Object]*/ closure(/*[null|subclass=Object]*/ a) => res = a;
+ /*[exact=JSUInt31]*/ closure(/*[exact=JSUInt31]*/ a) => res = a;
final a = (3, closure);
a. /*[Record(RecordShape(2), [[exact=JSUInt31], [subclass=Closure]])]*/ $2(
@@ -203,6 +203,41 @@
return topLevel4;
}
+/*member: bar1:[subclass=Closure]*/
+int Function(int, [int]) bar1(
+ int /*[exact=JSUInt31]*/ a) => /*[subclass=JSInt]*/
+ (int /*spec.[null|subclass=Object]*/ /*prod.[null|subclass=JSInt]*/ b,
+ [int /*spec.[null|subclass=Object]*/ /*prod.[null|subclass=JSInt]*/
+ c = 17]) =>
+ a /*invoke: [exact=JSUInt31]*/ + b /*invoke: [subclass=JSInt]*/ + c;
+/*member: bar2:[subclass=Closure]*/
+int Function(int, [int]) bar2(
+ int /*[exact=JSUInt31]*/ a) => /*[subclass=JSInt]*/
+ (int /*spec.[null|subclass=Object]*/ /*prod.[null|subclass=JSInt]*/ b,
+ [int /*spec.[null|subclass=Object]*/ /*prod.[null|subclass=JSInt]*/
+ c = 17]) =>
+ a /*invoke: [exact=JSUInt31]*/ + b /*invoke: [subclass=JSInt]*/ + c;
+/*member: bar3:[subclass=Closure]*/
+int Function(int, [int]) bar3(
+ int /*[exact=JSUInt31]*/ a) => /*[subclass=JSPositiveInt]*/
+ (int /*[exact=JSUInt31]*/ b, [int /*[exact=JSUInt31]*/ c = 17]) =>
+ a /*invoke: [exact=JSUInt31]*/ + b /*invoke: [subclass=JSUInt32]*/ + c;
+
+/*member: testFunctionApply:[null|subclass=Object]*/
+testFunctionApply() {
+ return Function.apply(bar1(10), [20]);
+}
+
+/*member: testRecordFunctionApply:[null|subclass=Object]*/
+testRecordFunctionApply() {
+ final rec = (bar2(10), bar3(10));
+ (rec. /*[Record(RecordShape(2), [[subclass=Closure], [subclass=Closure]])]*/ $2)(
+ 2, 3);
+ return Function.apply(
+ rec. /*[Record(RecordShape(2), [[subclass=Closure], [subclass=Closure]])]*/ $1,
+ [20]);
+}
+
/*member: main:[null]*/
main() {
testFunctionStatement();
@@ -219,4 +254,6 @@
testStaticClosure2();
testStaticClosure3();
testStaticClosure4();
+ testFunctionApply();
+ testRecordFunctionApply();
}
diff --git a/pkg/compiler/test/inference/data/record_4.dart b/pkg/compiler/test/inference/data/record_4.dart
index d61e074..a6a3fa9 100644
--- a/pkg/compiler/test/inference/data/record_4.dart
+++ b/pkg/compiler/test/inference/data/record_4.dart
@@ -4,25 +4,25 @@
testClosure1();
}
-/*member: testList:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+/*member: testList:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: null)*/
testList() {
dynamic list = [];
final rec = (list, 3);
final myList = rec
- . /*[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), [exact=JSUInt31]])]*/ $1;
+ . /*[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: null), [exact=JSUInt31]])]*/ $1;
myList
- . /*invoke: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ add(
+ . /*invoke: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: null)*/ add(
1);
return list;
}
-/*member: testClosure1:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+/*member: testClosure1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
testClosure1() {
return getRecord()
- . /*[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), [exact=JSUInt31]])]*/ $1;
+ . /*[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2), [exact=JSUInt31]])]*/ $1;
}
-/*member: getRecord:[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), [exact=JSUInt31]])]*/
+/*member: getRecord:[Record(RecordShape(2), [Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2), [exact=JSUInt31]])]*/
getRecord() {
return ([1, 2], 3);
}
diff --git a/pkg/compiler/test/inference/inference_data/function_apply_record.dart b/pkg/compiler/test/inference/inference_data/function_apply_record.dart
new file mode 100644
index 0000000..58c79d9
--- /dev/null
+++ b/pkg/compiler/test/inference/inference_data/function_apply_record.dart
@@ -0,0 +1,52 @@
+// Copyright (c) 2023, 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.
+
+main() {
+ directUnusedTest();
+ recordUnusedTest();
+ directCalledTest();
+ directAppliedTest();
+ recordCalledTest();
+ recordAppliedTest();
+}
+
+int Function(int, [int]) _recordUnused(int a) =>
+ (int b, [int c = 17]) => a + b + c;
+int Function(int, [int]) _recordCalled(int a) =>
+ (int b, [int c = 17]) => a + b + c;
+int Function(int, [int]) _recordApplied(int a) =>
+ /*apply*/ (int b, [int c = 17]) => a + b + c;
+int Function(int, [int]) _directUnused(int a) =>
+ (int b, [int c = 17]) => a + b + c;
+int Function(int, [int]) _directCalled(int a) =>
+ (int b, [int c = 17]) => a + b + c;
+int Function(int, [int]) _directApplied(int a) =>
+ /*apply*/ (int b, [int c = 17]) => a + b + c;
+
+directUnusedTest() {
+ return _directUnused(10);
+}
+
+recordUnusedTest() {
+ final rec = (_recordUnused(10), 4);
+ return rec.$1;
+}
+
+directCalledTest() {
+ return _directCalled(10)(20);
+}
+
+directAppliedTest() {
+ return Function.apply(_directApplied(10), [20]);
+}
+
+recordCalledTest() {
+ final rec = (4, _recordCalled(10));
+ return (rec.$2)(20);
+}
+
+recordAppliedTest() {
+ final rec = (_recordApplied(10), 4);
+ return Function.apply(rec.$1, [20]);
+}
diff --git a/pkg/compiler/test/inference/list_tracer_test.dart b/pkg/compiler/test/inference/list_tracer_test.dart
index ee901cf..39c62eb 100644
--- a/pkg/compiler/test/inference/list_tracer_test.dart
+++ b/pkg/compiler/test/inference/list_tracer_test.dart
@@ -265,10 +265,10 @@
checkType('listPassedAsNamedParameter', commonMasks.numType);
checkType('listStoredInList', commonMasks.uint31Type);
checkType('listStoredInListButEscapes', commonMasks.dynamicType);
- checkType('listStoredInRecordWithIndexAccess', commonMasks.dynamicType);
- checkType('listStoredInRecordWithNameAccess', commonMasks.dynamicType);
- checkType('listStoredInRecordWithDynamicAccess', commonMasks.dynamicType);
- checkType('listStoredInRecordWithoutAccess', commonMasks.dynamicType);
+ checkType('listStoredInRecordWithIndexAccess', commonMasks.numType);
+ checkType('listStoredInRecordWithNameAccess', commonMasks.numType);
+ checkType('listStoredInRecordWithDynamicAccess', commonMasks.numType);
+ checkType('listStoredInRecordWithoutAccess', commonMasks.uint31Type);
if (!allocation.contains('filled')) {
checkType('listUnset', TypeMask.nonNullEmpty());
diff --git a/pkg/compiler/test/inference/map_tracer_test.dart b/pkg/compiler/test/inference/map_tracer_test.dart
index 348a7fb..83b8b2e 100644
--- a/pkg/compiler/test/inference/map_tracer_test.dart
+++ b/pkg/compiler/test/inference/map_tracer_test.dart
@@ -313,14 +313,14 @@
checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
V(commonMasks.dynamicType));
- checkType('mapStoredInRecordWithIndexAccess', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapStoredInRecordWithNameAccess', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapStoredInRecordWithDynamicAccess', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapStoredInRecordWithoutAccess', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
+ checkType(
+ 'mapStoredInRecordWithIndexAccess', K(aKeyType), V(commonMasks.numType));
+ checkType(
+ 'mapStoredInRecordWithNameAccess', K(aKeyType), V(commonMasks.numType));
+ checkType('mapStoredInRecordWithDynamicAccess', K(aKeyType),
+ V(commonMasks.numType));
+ checkType('mapStoredInRecordWithoutAccess', K(aKeyType),
+ V(commonMasks.positiveIntType));
checkType('mapUnset', K(emptyType), V(emptyType));
checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
diff --git a/pkg/compiler/test/testing.json b/pkg/compiler/test/testing.json
index dde9e2a..9d1100b 100644
--- a/pkg/compiler/test/testing.json
+++ b/pkg/compiler/test/testing.json
@@ -9,6 +9,7 @@
"."
],
"exclude": [
+ "^pkg/compiler/test/.*/inference_data/.*",
"^pkg/compiler/test/.*/data/.*",
"^pkg/compiler/test/.*/data_2/.*",
"^pkg/compiler/test/.*/emission/.*",