Port inference tests, #5 of 5
Change-Id: I384056289dfa99991aa42fbe0baadedc6c208b6f
Reviewed-on: https://dart-review.googlesource.com/34586
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index dfe9783..d43c8c0 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -542,6 +542,12 @@
if (id is NodeId) {
return new SourceSpan(mainUri, id.value, id.value + 1);
} else if (id is ElementId) {
+ String memberName = id.memberName;
+ bool isSetter = false;
+ if (memberName != '[]=' && memberName.endsWith('=')) {
+ isSetter = true;
+ memberName = memberName.substring(0, memberName.length - 1);
+ }
LibraryEntity library = elementEnvironment.lookupLibrary(mainUri);
if (id.className != null) {
ClassEntity cls =
@@ -549,23 +555,22 @@
if (cls == null) {
throw new ArgumentError("No class '${id.className}' in $mainUri.");
}
- MemberEntity member =
- elementEnvironment.lookupClassMember(cls, id.memberName);
+ MemberEntity member = elementEnvironment
+ .lookupClassMember(cls, memberName, setter: isSetter);
if (member == null) {
ConstructorEntity constructor =
- elementEnvironment.lookupConstructor(cls, id.memberName);
+ elementEnvironment.lookupConstructor(cls, memberName);
if (constructor == null) {
- throw new ArgumentError(
- "No class member '${id.memberName}' in $cls.");
+ throw new ArgumentError("No class member '${memberName}' in $cls.");
}
return constructor;
}
return member;
} else {
- MemberEntity member =
- elementEnvironment.lookupLibraryMember(library, id.memberName);
+ MemberEntity member = elementEnvironment
+ .lookupLibraryMember(library, memberName, setter: isSetter);
if (member == null) {
- throw new ArgumentError("No member '${id.memberName}' in $mainUri.");
+ throw new ArgumentError("No member '${memberName}' in $mainUri.");
}
return member;
}
diff --git a/tests/compiler/dart2js/equivalence/show_helper.dart b/tests/compiler/dart2js/equivalence/show_helper.dart
index d37f502..bb72432 100644
--- a/tests/compiler/dart2js/equivalence/show_helper.dart
+++ b/tests/compiler/dart2js/equivalence/show_helper.dart
@@ -8,37 +8,40 @@
import 'package:args/args.dart';
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/filenames.dart';
-import 'package:compiler/src/inferrer/inferrer_engine.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/source_file_provider.dart';
import '../kernel/test_helpers.dart';
import 'id_equivalence_helper.dart';
-show(List<String> args, ComputeMemberDataFunction computeAstData,
- ComputeMemberDataFunction computeKernelData) async {
+ArgParser createArgParser() {
ArgParser argParser = new ArgParser(allowTrailingOptions: true);
argParser.addFlag('verbose', negatable: true, defaultsTo: false);
argParser.addFlag('colors', negatable: true);
argParser.addFlag('all', negatable: false, defaultsTo: false);
argParser.addFlag('use-kernel', negatable: false, defaultsTo: false);
- ArgResults argResults = argParser.parse(args);
+ return argParser;
+}
+
+show(ArgResults argResults, ComputeMemberDataFunction computeAstData,
+ ComputeMemberDataFunction computeKernelData) async {
if (argResults.wasParsed('colors')) {
useColors = argResults['colors'];
}
bool verbose = argResults['verbose'];
bool useKernel = argResults['use-kernel'];
- InferrerEngineImpl.useSorterForTesting = true;
String file = argResults.rest.first;
Uri entryPoint = Uri.base.resolve(nativeToUriPath(file));
List<String> show;
- if (argResults.rest.length > 1) {
+ if (argResults['all']) {
+ show = null;
+ } else if (argResults.rest.length > 1) {
show = argResults.rest.skip(1).toList();
} else {
show = [entryPoint.pathSegments.last];
}
- List<String> options = <String>[];
+ List<String> options = <String>[stopAfterTypeInference];
if (useKernel) {
options.add(Flags.useKernel);
}
diff --git a/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart b/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart
deleted file mode 100644
index 4047641..0000000
--- a/tests/compiler/dart2js/inference/call_site_simple_type_inferer_test.dart
+++ /dev/null
@@ -1,297 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/elements/elements.dart';
-import 'package:compiler/src/types/masks.dart';
-import 'package:expect/expect.dart';
-
-import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
-
-void compileAndFind(String code, String className, String memberName,
- bool disableInlining, check(compiler, element)) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
- asyncTest(() => compiler.run(uri).then((_) {
- ClassElement cls = findElement(compiler, className);
- var member = cls.lookupLocalMember(memberName);
- return check(compiler, member);
- }));
-}
-
-const String TEST_1 = r"""
- class A {
- x(p) => p;
- }
- main() { new A().x("s"); }
-""";
-
-const String TEST_2 = r"""
- class A {
- x(p) => p;
- }
- main() { new A().x(1); }
-""";
-
-const String TEST_3 = r"""
- class A {
- x(p) => x(p - 1);
- }
- main() { new A().x(1); }
-""";
-
-const String TEST_4 = r"""
- class A {
- x(p) => x(p - 1);
- }
- main() { new A().x(1.5); }
-""";
-
-const String TEST_5 = r"""
- class A {
- x(p) => p;
- }
- main() {
- new A().x(1);
- new A().x(1.5);
- }
-""";
-
-const String TEST_6 = r"""
- class A {
- x(p) => p;
- }
- main() {
- new A().x(1.5);
- new A().x(1);
- }
-""";
-
-const String TEST_7a = r"""
- class A {
- x(p) => x("x");
- }
- main() {
- new A().x(1);
- }
-""";
-
-const String TEST_7b = r"""
- class A {
- x(p) => x("x");
- }
- main() {
- new A().x({});
- }
-""";
-
-const String TEST_8 = r"""
- class A {
- x(p1, p2, p3) => x(p1, "x", {});
- }
- main() {
- new A().x(1, 2, 3);
- }
-""";
-
-const String TEST_9 = r"""
- class A {
- x(p1, p2) => x(p1, p2);
- }
- main() {
- new A().x(1, 2);
- }
-""";
-
-const String TEST_10 = r"""
- class A {
- x(p1, p2) => x(p1, p2);
- }
- void f(p) {
- p.x("x", "y");
- }
- main() {
- f(null);
- new A().x(1, 2);
- }
-""";
-
-const String TEST_11 = r"""
- class A {
- x(p1, p2) => x(1, 2);
- }
- main() {
- new A().x("x", "y");
- }
-""";
-
-const String TEST_12 = r"""
- class A {
- x(p1, [p2 = 1]) => 1;
- }
- main() {
- new A().x("x", 1);
- new A().x("x");
- }
-""";
-
-const String TEST_13 = r"""
- class A {
- x(p) => 1;
- }
- f(p) => p.x(2.2);
- main() {
- new A().x(1);
- f(new A());
- }
-""";
-
-const String TEST_14 = r"""
- class A {
- x(p1, [p2 = "s"]) => 1;
- }
- main() {
- new A().x(1);
- }
-""";
-
-const String TEST_15 = r"""
- class A {
- x(p1, [p2 = true]) => 1;
- }
- f(p) => p.a("x");
- main() {
- new A().x("x");
- new A().x("x", false);
- f(null);
- }
-""";
-
-const String TEST_16 = r"""
- class A {
- x(p1, [p2 = 1, p3 = "s"]) => 1;
- }
- main() {
- new A().x(1);
- new A().x(1, 2);
- new A().x(1, 2, "x");
- new A().x(1, p2: 2);
- new A().x(1, p3: "x");
- new A().x(1, p3: "x", p2: 2);
- new A().x(1, p2: 2, p3: "x");
- }
-""";
-
-const String TEST_17 = r"""
- class A {
- x(p1, [p2 = 1, p3 = "s"]) => 1;
- }
- main() {
- new A().x(1, true, 1.1);
- new A().x(1, false, 2.2);
- new A().x(1, p3: 3.3, p2: true);
- new A().x(1, p2: false, p3: 4.4);
- }
-""";
-
-const String TEST_18 = r"""
- class A {
- x(p1, p2) => x(p1, p2);
- }
- class B extends A {
- }
- main() {
- new B().x("a", "b");
- new A().x(1, 2);
- }
-""";
-
-typedef List<TypeMask> TestCallback(CommonMasks masks);
-
-void doTest(String test, bool enableInlining, TestCallback f) {
- compileAndFind(test, 'A', 'x', enableInlining, (compiler, element) {
- var inferrer = compiler.globalInference.typesInferrerInternal;
- var closedWorld = inferrer.closedWorld;
- var expectedTypes = f(closedWorld.commonMasks);
- var signature = element.functionSignature;
- int index = 0;
- signature.forEachParameter((Element element) {
- Expect.equals(expectedTypes[index++],
- simplify(inferrer.getTypeOfParameter(element), closedWorld), test);
- });
- Expect.equals(index, expectedTypes.length);
- });
-}
-
-void runTest(String test, TestCallback f) {
- doTest(test, false, f);
- doTest(test, true, f);
-}
-
-void test() {
- runTest(TEST_1, (commonMasks) => [commonMasks.stringType]);
- runTest(TEST_2, (commonMasks) => [commonMasks.uint31Type]);
- runTest(TEST_3, (commonMasks) => [commonMasks.intType]);
- runTest(TEST_4, (commonMasks) => [commonMasks.numType]);
- runTest(TEST_5, (commonMasks) => [commonMasks.numType]);
- runTest(TEST_6, (commonMasks) => [commonMasks.numType]);
- runTest(TEST_7a, (commonMasks) => [commonMasks.interceptorType]);
- runTest(TEST_7b, (commonMasks) => [commonMasks.dynamicType.nonNullable()]);
-
- runTest(
- TEST_8,
- (commonMasks) => [
- commonMasks.uint31Type,
- commonMasks.interceptorType,
- commonMasks.dynamicType.nonNullable()
- ]);
- runTest(TEST_9,
- (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
- runTest(TEST_10,
- (commonMasks) => [commonMasks.uint31Type, commonMasks.uint31Type]);
- runTest(
- TEST_11,
- (commonMasks) =>
- [commonMasks.interceptorType, commonMasks.interceptorType]);
-
- runTest(TEST_12,
- (commonMasks) => [commonMasks.stringType, commonMasks.uint31Type]);
-
- runTest(TEST_13, (commonMasks) => [commonMasks.numType]);
-
- runTest(TEST_14,
- (commonMasks) => [commonMasks.uint31Type, commonMasks.stringType]);
-
- runTest(
- TEST_15, (commonMasks) => [commonMasks.stringType, commonMasks.boolType]);
-
- runTest(
- TEST_16,
- (commonMasks) => [
- commonMasks.uint31Type,
- commonMasks.uint31Type,
- commonMasks.stringType
- ]);
-
- runTest(
- TEST_17,
- (commonMasks) => [
- commonMasks.uint31Type,
- commonMasks.boolType,
- commonMasks.doubleType
- ]);
-
- runTest(
- TEST_18,
- (commonMasks) =>
- [commonMasks.interceptorType, commonMasks.interceptorType]);
-}
-
-void main() {
- test();
-}
diff --git a/tests/compiler/dart2js/inference/callers/field_access.dart b/tests/compiler/dart2js/inference/callers/field_access.dart
new file mode 100644
index 0000000..71699e9
--- /dev/null
+++ b/tests/compiler/dart2js/inference/callers/field_access.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2018, 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.
+
+/*element: B.:[main]*/
+class A {
+ /*element: A.field:[main]*/
+ var field;
+}
+
+/*element: A.:[main]*/
+class B {
+ /*element: B.field:[main]*/
+ var field;
+}
+
+main() {
+ new A().field;
+ new B().field;
+}
diff --git a/tests/compiler/dart2js/inference/callers_test.dart b/tests/compiler/dart2js/inference/callers_test.dart
new file mode 100644
index 0000000..b88f07f
--- /dev/null
+++ b/tests/compiler/dart2js/inference/callers_test.dart
@@ -0,0 +1,145 @@
+// Copyright (c) 2018, 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 'dart:io';
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/common.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
+import 'package:compiler/src/elements/elements.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/inferrer_engine.dart';
+import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
+import 'package:compiler/src/kernel/element_map.dart';
+import 'package:compiler/src/kernel/kernel_backend_strategy.dart';
+import 'package:compiler/src/tree/nodes.dart' as ast;
+import 'package:kernel/ast.dart' as ir;
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+
+main(List<String> args) {
+ InferrerEngineImpl.retainDataForTesting = true;
+ asyncTest(() async {
+ Directory dataDir =
+ new Directory.fromUri(Platform.script.resolve('callers'));
+ await checkTests(dataDir, computeMemberAstCallers, computeMemberIrCallers,
+ args: args, options: [stopAfterTypeInference]);
+ });
+}
+
+/// Compute callers data for [_member] as a [MemberElement].
+///
+/// Fills [actualMap] with the data.
+void computeMemberAstCallers(
+ Compiler compiler, MemberEntity _member, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ MemberElement member = _member;
+ ResolvedAst resolvedAst = member.resolvedAst;
+ compiler.reporter.withCurrentElement(member.implementation, () {
+ new CallersAstComputer(compiler.reporter, actualMap, resolvedAst,
+ compiler.globalInference.typesInferrerInternal)
+ .run();
+ });
+}
+
+abstract class ComputeValueMixin<T> {
+ TypeGraphInferrer get inferrer;
+
+ String getMemberValue(MemberEntity member) {
+ Iterable<MemberEntity> callers = inferrer.getCallersOfForTesting(member);
+ if (callers != null) {
+ List<String> names = callers.map((MemberEntity member) {
+ StringBuffer sb = new StringBuffer();
+ if (member.enclosingClass != null) {
+ sb.write(member.enclosingClass.name);
+ sb.write('.');
+ }
+ sb.write(member.name);
+ if (member.isSetter) {
+ sb.write('=');
+ }
+ return sb.toString();
+ }).toList()
+ ..sort();
+ return '[${names.join(',')}]';
+ }
+ return null;
+ }
+}
+
+/// AST visitor for computing side effects data for a member.
+class CallersAstComputer extends AstDataExtractor
+ with ComputeValueMixin<ast.Node> {
+ final TypeGraphInferrer inferrer;
+
+ CallersAstComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
+ ResolvedAst resolvedAst, this.inferrer)
+ : super(reporter, actualMap, resolvedAst);
+
+ @override
+ String computeElementValue(Id id, AstElement element) {
+ if (element.isParameter) {
+ return null;
+ } else if (element.isLocal && element.isFunction) {
+ LocalFunctionElement localFunction = element;
+ return getMemberValue(localFunction.callMethod);
+ } else {
+ MemberElement member = element.declaration;
+ return getMemberValue(member);
+ }
+ }
+
+ @override
+ String computeNodeValue(Id id, ast.Node node, [AstElement element]) {
+ if (element != null && element.isLocal && element.isFunction) {
+ return computeElementValue(id, element);
+ }
+ return null;
+ }
+}
+
+/// Compute callers data for [member] from kernel based inference.
+///
+/// Fills [actualMap] with the data.
+void computeMemberIrCallers(
+ Compiler compiler, MemberEntity member, Map<Id, ActualData> actualMap,
+ {bool verbose: false}) {
+ KernelBackendStrategy backendStrategy = compiler.backendStrategy;
+ KernelToElementMapForBuilding elementMap = backendStrategy.elementMap;
+ MemberDefinition definition = elementMap.getMemberDefinition(member);
+ new CallersIrComputer(
+ compiler.reporter,
+ actualMap,
+ elementMap,
+ compiler.globalInference.typesInferrerInternal,
+ backendStrategy.closureDataLookup as ClosureDataLookup<ir.Node>)
+ .run(definition.node);
+}
+
+/// AST visitor for computing side effects data for a member.
+class CallersIrComputer extends IrDataExtractor
+ with ComputeValueMixin<ir.Node> {
+ final TypeGraphInferrer inferrer;
+ final KernelToElementMapForBuilding _elementMap;
+ final ClosureDataLookup<ir.Node> _closureDataLookup;
+
+ CallersIrComputer(DiagnosticReporter reporter, Map<Id, ActualData> actualMap,
+ this._elementMap, this.inferrer, this._closureDataLookup)
+ : super(reporter, actualMap);
+
+ @override
+ String computeMemberValue(Id id, ir.Member node) {
+ return getMemberValue(_elementMap.getMember(node));
+ }
+
+ @override
+ String computeNodeValue(Id id, ir.TreeNode node) {
+ if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
+ ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
+ return getMemberValue(info.callMethod);
+ }
+ return null;
+ }
+}
diff --git a/tests/compiler/dart2js/inference/concrete_type_inference_test.dart b/tests/compiler/dart2js/inference/concrete_type_inference_test.dart
deleted file mode 100644
index 4b1b6b5..0000000
--- a/tests/compiler/dart2js/inference/concrete_type_inference_test.dart
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-import 'dart:async';
-import 'package:expect/expect.dart';
-import 'package:async_helper/async_helper.dart';
-import '../compiler_helper.dart';
-
-Future compileAndFind(String code, String name, check(compiler, element)) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(code, uri);
- return compiler.run(uri).then((_) {
- var element = findElement(compiler, name);
- check(compiler, element);
- });
-}
-
-void checkPrintType(String expression, checkType(closedWorld, type)) {
- asyncTest(() => compileAndFind('main() { print($expression); }', 'print',
- (compiler, printElement) {
- var parameter = printElement.functionSignature.requiredParameters.first;
- checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
- _typeOf(compiler, parameter));
- }));
-
- asyncTest(() =>
- compileAndFind('main() { var x = print; print($expression); }', 'print',
- (compiler, printElement) {
- var parameter = printElement.functionSignature.requiredParameters.first;
- checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
- _typeOf(compiler, parameter));
- }));
-
- asyncTest(() => compileAndFind(
- 'main() { print($expression); print($expression); }', 'print',
- (compiler, printElement) {
- var parameter = printElement.functionSignature.requiredParameters.first;
- checkType(compiler.resolutionWorldBuilder.closedWorldForTesting,
- _typeOf(compiler, parameter));
- }));
-}
-
-void testBasicTypes() {
- checkPrintType('true', (closedWorld, type) {
- if (type.isForwarding) type = type.forwardTo;
- Expect.identical(closedWorld.commonMasks.boolType, type);
- });
- checkPrintType('1.5', (closedWorld, type) {
- Expect.identical(closedWorld.commonMasks.doubleType, type);
- });
- checkPrintType('1', (closedWorld, type) {
- Expect.identical(closedWorld.commonMasks.uint31Type, type);
- });
- checkPrintType('[]', (closedWorld, type) {
- if (type.isForwarding) type = type.forwardTo;
- Expect.identical(closedWorld.commonMasks.growableListType, type);
- });
- checkPrintType('null', (closedWorld, type) {
- Expect.identical(closedWorld.commonMasks.nullType, type);
- });
- checkPrintType('"foo"', (closedWorld, type) {
- Expect.isTrue(
- closedWorld.commonMasks.stringType.containsOnlyString(closedWorld));
- });
-}
-
-void testOptionalParameters() {
- compileAndFind('fisk(a, [b, c]) {} main() { fisk(1); }', 'fisk',
- (compiler, fiskElement) {
- var firstParameter = fiskElement.functionSignature.requiredParameters[0];
- var secondParameter = fiskElement.functionSignature.optionalParameters[0];
- var thirdParameter = fiskElement.functionSignature.optionalParameters[1];
- var commonMasks =
- compiler.resolutionWorldBuilder.closedWorldForTesting.commonMasks;
- Expect.identical(commonMasks.uint31Type, _typeOf(compiler, firstParameter));
- Expect.identical(commonMasks.nullType, _typeOf(compiler, secondParameter));
- Expect.identical(commonMasks.nullType, _typeOf(compiler, thirdParameter));
- });
-}
-
-void main() {
- testBasicTypes();
- testOptionalParameters();
-}
-
-_typeOf(compiler, parameter) =>
- compiler.globalInference.results.resultOfParameter(parameter).type;
diff --git a/tests/compiler/dart2js/inference/data/call_site.dart b/tests/compiler/dart2js/inference/data/call_site.dart
new file mode 100644
index 0000000..e9bcd9f
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/call_site.dart
@@ -0,0 +1,309 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+ test8();
+ test9();
+ test10();
+ test11();
+ test12();
+ test13();
+ test14();
+ test15();
+ test16();
+ test17();
+ test18();
+ test19();
+}
+
+/*element: A1.:[exact=A1]*/
+class A1 {
+ /*element: A1.x1:Value([exact=JSString], value: "s")*/
+ x1(
+ /*Value([exact=JSString], value: "s")*/ p) =>
+ p;
+}
+
+/*element: test1:[null]*/
+test1() {
+ new A1(). /*invoke: [exact=A1]*/ x1("s");
+}
+
+/*element: A2.:[exact=A2]*/
+class A2 {
+ /*element: A2.x2:[exact=JSUInt31]*/
+ x2(/*[exact=JSUInt31]*/ p) => p;
+}
+
+/*element: test2:[null]*/
+test2() {
+ new A2(). /*invoke: [exact=A2]*/ x2(1);
+}
+
+/*element: A3.:[exact=A3]*/
+class A3 {
+ /*element: A3.x3:[empty]*/
+ x3(/*[subclass=JSInt]*/ p) => /*invoke: [exact=A3]*/ x3(
+ p /*invoke: [subclass=JSInt]*/ - 1);
+}
+
+/*element: test3:[null]*/
+test3() {
+ new A3(). /*invoke: [exact=A3]*/ x3(1);
+}
+
+/*element: A4.:[exact=A4]*/
+class A4 {
+ /*element: A4.x4:[empty]*/
+ x4(/*[subclass=JSNumber]*/ p) => /*invoke: [exact=A4]*/ x4(
+ p /*invoke: [subclass=JSNumber]*/ - 1);
+}
+
+/*element: test4:[null]*/
+test4() {
+ new A4(). /*invoke: [exact=A4]*/ x4(1.5);
+}
+
+/*element: A5.:[exact=A5]*/
+class A5 {
+ /*element: A5.x5:Union([exact=JSDouble], [exact=JSUInt31])*/
+ x5(
+ /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+ p;
+}
+
+/*element: test5:[null]*/
+test5() {
+ new A5(). /*invoke: [exact=A5]*/ x5(1);
+ new A5(). /*invoke: [exact=A5]*/ x5(1.5);
+}
+
+/*element: A6.:[exact=A6]*/
+class A6 {
+ /*element: A6.x6:Union([exact=JSDouble], [exact=JSUInt31])*/
+ x6(
+ /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+ p;
+}
+
+/*element: test6:[null]*/
+test6() {
+ new A6(). /*invoke: [exact=A6]*/ x6(1.5);
+ new A6(). /*invoke: [exact=A6]*/ x6(1);
+}
+
+/*element: A7.:[exact=A7]*/
+class A7 {
+ /*element: A7.x7:[empty]*/
+ x7(
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p) => /*invoke: [exact=A7]*/ x7("x");
+}
+
+/*element: test7:[null]*/
+test7() {
+ new A7(). /*invoke: [exact=A7]*/ x7(1);
+}
+
+/*element: A8.:[exact=A8]*/
+class A8 {
+ /*element: A8.x8:[empty]*/
+ x8(
+ /*Union([exact=JSString], [subclass=JsLinkedHashMap])*/ p) =>
+ /*invoke: [exact=A8]*/ x8("x");
+}
+
+/*element: test8:[null]*/
+test8() {
+ new A8(). /*invoke: [exact=A8]*/ x8({});
+}
+
+/*element: A9.:[exact=A9]*/
+class A9 {
+ /*element: A9.x9:[empty]*/ x9(
+ /*[exact=JSUInt31]*/ p1,
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p2,
+ /*Union([exact=JSUInt31], [subclass=JsLinkedHashMap])*/ p3) =>
+ /*invoke: [exact=A9]*/ x9(p1, "x", {});
+}
+
+/*element: test9:[null]*/
+test9() {
+ new A9(). /*invoke: [exact=A9]*/ x9(1, 2, 3);
+}
+
+/*element: A10.:[exact=A10]*/
+class A10 {
+ /*element: A10.x10:[empty]*/ x10(
+ /*[exact=JSUInt31]*/ p1,
+ /*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A10]*/ x10(p1, p2);
+}
+
+/*element: test10:[null]*/
+test10() {
+ new A10(). /*invoke: [exact=A10]*/ x10(1, 2);
+}
+
+/*element: A11.:[exact=A11]*/
+class A11 {
+ /*element: A11.x11:[empty]*/
+ x11(
+ /*[exact=JSUInt31]*/ p1,
+ /*[exact=JSUInt31]*/ p2) => /*invoke: [exact=A11]*/ x11(p1, p2);
+}
+
+/*element: f11:[null]*/
+void f11(/*[null]*/ p) {
+ p. /*invoke: [null]*/ x11("x", "y");
+}
+
+/*element: test11:[null]*/
+test11() {
+ f11(null);
+ new A11(). /*invoke: [exact=A11]*/ x11(1, 2);
+}
+
+/*element: A12.:[exact=A12]*/
+class A12 {
+ /*element: A12.x12:[empty]*/
+ x12(
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p1,
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
+ /*invoke: [exact=A12]*/ x12(1, 2);
+}
+
+/*element: test12:[null]*/
+test12() {
+ new A12(). /*invoke: [exact=A12]*/ x12("x", "y");
+}
+
+/*element: A13.:[exact=A13]*/
+class A13 {
+ /*element: A13.x13:[exact=JSUInt31]*/
+ x13(
+ /*Value([exact=JSString], value: "x")*/ p1,
+ [/*[exact=JSUInt31]*/ p2 = 1]) =>
+ 1;
+}
+
+/*element: test13:[null]*/
+test13() {
+ new A13(). /*invoke: [exact=A13]*/ x13("x", 1);
+ new A13(). /*invoke: [exact=A13]*/ x13("x");
+}
+
+/*element: A14.:[exact=A14]*/
+class A14 {
+ /*element: A14.x14:[exact=JSUInt31]*/
+ x14(
+ /*Union([exact=JSDouble], [exact=JSUInt31])*/ p) =>
+ 1;
+}
+
+/*element: f14:[exact=JSUInt31]*/
+f14(/*[exact=A14]*/ p) => p. /*invoke: [exact=A14]*/ x14(2.2);
+
+/*element: test14:[null]*/
+test14() {
+ new A14(). /*invoke: [exact=A14]*/ x14(1);
+ f14(new A14());
+}
+
+/*element: A15.:[exact=A15]*/
+class A15 {
+ /*element: A15.x15:[exact=JSUInt31]*/
+ x15(/*[exact=JSUInt31]*/ p1,
+ [/*Value([exact=JSString], value: "s")*/ p2 = "s"]) =>
+ 1;
+}
+
+/*element: test15:[null]*/
+test15() {
+ new A15(). /*invoke: [exact=A15]*/ x15(1);
+}
+
+/*element: A16.:[exact=A16]*/
+class A16 {
+ /*element: A16.x16:[exact=JSUInt31]*/
+ x16(
+ /*Value([exact=JSString], value: "x")*/ p1,
+ [/*[exact=JSBool]*/ p2 = true]) =>
+ 1;
+}
+
+/*element: f16:[empty]*/
+f16(/*[null]*/ p) => p. /*invoke: [null]*/ a("x");
+
+/*element: test16:[null]*/
+test16() {
+ new A16(). /*invoke: [exact=A16]*/ x16("x");
+ new A16(). /*invoke: [exact=A16]*/ x16("x", false);
+ f16(null);
+}
+
+/*element: A17.:[exact=A17]*/
+class A17 {
+ /*element: A17.x17:[exact=JSUInt31]*/
+ x17(/*[exact=JSUInt31]*/ p1,
+ [/*[exact=JSUInt31]*/ p2 = 1, /*[exact=JSString]*/ p3 = "s"]) =>
+ 1;
+}
+
+/*element: test17:[null]*/
+test17() {
+ new A17(). /*invoke: [exact=A17]*/ x17(1);
+ new A17(). /*invoke: [exact=A17]*/ x17(1, 2);
+ new A17(). /*invoke: [exact=A17]*/ x17(1, 2, "x");
+ // ignore: undefined_named_parameter
+ new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2);
+ // ignore: undefined_named_parameter
+ new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x");
+ // ignore: undefined_named_parameter
+ new A17(). /*invoke: [exact=A17]*/ x17(1, p3: "x", p2: 2);
+ // ignore: undefined_named_parameter
+ new A17(). /*invoke: [exact=A17]*/ x17(1, p2: 2, p3: "x");
+}
+
+/*element: A18.:[exact=A18]*/
+class A18 {
+ /*element: A18.x18:[exact=JSUInt31]*/
+ x18(/*[exact=JSUInt31]*/ p1,
+ [/*[exact=JSBool]*/ p2 = 1, /*[exact=JSDouble]*/ p3 = "s"]) =>
+ 1;
+}
+
+/*element: test18:[null]*/
+test18() {
+ new A18(). /*invoke: [exact=A18]*/ x18(1, true, 1.1);
+ new A18(). /*invoke: [exact=A18]*/ x18(1, false, 2.2);
+ // ignore: undefined_named_parameter
+ new A18(). /*invoke: [exact=A18]*/ x18(1, p3: 3.3, p2: true);
+ // ignore: undefined_named_parameter
+ new A18(). /*invoke: [exact=A18]*/ x18(1, p2: false, p3: 4.4);
+}
+
+/*element: A19.:[exact=A19]*/
+class A19 {
+ /*element: A19.x19:[empty]*/
+ x19(
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p1,
+ /*Union([exact=JSString], [exact=JSUInt31])*/ p2) =>
+ /*invoke: [subclass=A19]*/ x19(p1, p2);
+}
+
+/*element: B19.:[exact=B19]*/
+class B19 extends A19 {}
+
+/*element: test19:[null]*/
+test19() {
+ new B19(). /*invoke: [exact=B19]*/ x19("a", "b");
+ new A19(). /*invoke: [exact=A19]*/ x19(1, 2);
+}
diff --git a/tests/compiler/dart2js/inference/data/dictionary_types.dart b/tests/compiler/dart2js/inference/data/dictionary_types.dart
new file mode 100644
index 0000000..f6f3cc4
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/dictionary_types.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+}
+
+/*element: dictionaryA1:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+var dictionaryA1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: dictionaryB1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+var dictionaryB1 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: otherDict1:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+var otherDict1 = {'stringTwo': "anotherString", 'intTwo': 84};
+
+/*element: int1:[exact=JSUInt31]*/
+var int1 = 0;
+
+/*element: anotherInt1:[exact=JSUInt31]*/
+var anotherInt1 = 0;
+
+/*element: nullOrInt1:[null|exact=JSUInt31]*/
+var nullOrInt1 = 0;
+
+/*element: dynamic1:[null|subclass=Object]*/
+var dynamic1 = 0;
+
+/*element: test1:[null]*/
+test1() {
+ dictionaryA1
+ . /*invoke: Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ addAll(otherDict1);
+ dictionaryB1
+ . /*invoke: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ addAll({'stringTwo': "anotherString", 'intTwo': 84});
+ int1 = dictionaryB1
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ ['int'];
+ anotherInt1 = otherDict1
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {stringTwo: Value([exact=JSString], value: "anotherString"), intTwo: [exact=JSUInt31]})*/
+ ['intTwo'];
+ dynamic1 = dictionaryA1
+ /*Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/ [
+ 'int'];
+ nullOrInt1 = dictionaryB1
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null), stringTwo: Value([null|exact=JSString], value: "anotherString"), intTwo: [null|exact=JSUInt31]})*/
+ ['intTwo'];
+}
+
+/*element: dictionaryA2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionaryA2 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+
+/*element: dictionaryB2:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), intTwo: [exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionaryB2 = {'string': "aString", 'intTwo': 42, 'list': []};
+
+/*element: nullOrInt2:[null|exact=JSUInt31]*/
+var nullOrInt2 = 0;
+
+/*element: aString2:[exact=JSString]*/
+var aString2 = "";
+
+/*element: doubleOrNull2:[null|exact=JSDouble]*/
+var doubleOrNull2 = 22.2;
+
+/*element: test2:[null]*/
+test2() {
+ var union = dictionaryA2
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ ['foo']
+ ? dictionaryA2
+ : dictionaryB2;
+ nullOrInt2 = union
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ ['intTwo'];
+ aString2 = union
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ ['string'];
+ doubleOrNull2 = union
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {int: [null|exact=JSUInt31], double: [null|exact=JSDouble], string: Value([exact=JSString], value: "aString"), intTwo: [null|exact=JSUInt31], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ ['double'];
+}
+
+/*element: dictionary3:Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+var dictionary3 = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
+/*element: keyD3:Value([exact=JSString], value: "double")*/
+var keyD3 = 'double';
+
+/*element: keyI3:Value([exact=JSString], value: "int")*/
+var keyI3 = 'int';
+
+/*element: keyN3:Value([exact=JSString], value: "notFoundInMap")*/
+var keyN3 = 'notFoundInMap';
+
+/*element: knownDouble3:[exact=JSDouble]*/
+var knownDouble3 = 42.2;
+
+/*element: intOrNull3:[null|exact=JSUInt31]*/
+var intOrNull3 = dictionary3
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ [keyI3];
+
+/*element: justNull3:[null]*/
+var justNull3 = dictionary3
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ [keyN3];
+
+/*element: test3:[null]*/
+test3() {
+ knownDouble3 = dictionary3
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [exact=JSExtendableArray], [exact=JSUInt31], [null|exact=JSString]), map: {string: Value([exact=JSString], value: "aString"), int: [exact=JSUInt31], double: [exact=JSDouble], list: Container([exact=JSExtendableArray], element: [empty], length: 0)})*/
+ [keyD3];
+ // ignore: unused_local_variable
+ var x = [intOrNull3, justNull3];
+}
+
+class A4 {
+/*element: A4.:[exact=A4]*/
+ A4();
+/*element: A4.foo4:[exact=JSUInt31]*/
+ foo4(
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+ return value /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ [
+ 'anInt'];
+ }
+}
+
+class B4 {
+/*element: B4.:[exact=B4]*/
+ B4();
+
+/*element: B4.foo4:[exact=JSUInt31]*/
+ foo4(
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSUInt31], [null|exact=JSString]), map: {anInt: [exact=JSUInt31], aString: Value([exact=JSString], value: "theString")})*/ value) {
+ return 0;
+ }
+}
+
+/*element: test4:[null]*/
+test4() {
+ var dictionary = {'anInt': 42, 'aString': "theString"};
+ var it;
+ if ([true, false]
+ /*Container([exact=JSExtendableArray], element: [exact=JSBool], length: 2)*/
+ [0]) {
+ it = new A4();
+ } else {
+ it = new B4();
+ }
+ print(it. /*invoke: Union([exact=A4], [exact=B4])*/ foo4(
+ dictionary) /*invoke: [exact=JSUInt31]*/ +
+ 2);
+}
+
+/*element: dict5:Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+var dict5 = makeMap5([1, 2]);
+
+/*element: notInt5:[null|subclass=Object]*/
+var notInt5 = 0;
+
+/*element: alsoNotInt5:[null|subclass=Object]*/
+var alsoNotInt5 = 0;
+
+/*element: makeMap5:Map([subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+makeMap5(
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/ values) {
+ return {
+ 'moo': values
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
+ [0],
+ 'boo': values
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 2)*/
+ [1]
+ };
+}
+
+/*element: test5:[null]*/
+test5() {
+ dict5
+ /*update: Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ ['goo'] = 42;
+ var closure =
+ /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ () => dict5;
+ notInt5 = closure()['boo'];
+ alsoNotInt5 = dict5
+ /*Map([null|subclass=JsLinkedHashMap], key: [null|subclass=Object], value: [null|subclass=Object])*/
+ ['goo'];
+ print("$notInt5 and $alsoNotInt5.");
+}
diff --git a/tests/compiler/dart2js/inference/data/map_tracer_keys.dart b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
new file mode 100644
index 0000000..fb02458
--- /dev/null
+++ b/tests/compiler/dart2js/inference/data/map_tracer_keys.dart
@@ -0,0 +1,189 @@
+// Copyright (c) 2018, 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.
+
+/*element: main:[null]*/
+main() {
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+}
+
+/*element: aDouble1:[null|exact=JSDouble]*/
+double aDouble1 = 42.5;
+
+/*element: aList1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList1 = [42];
+
+/*element: consume1:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume1(
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+ x;
+
+/*element: test1:[null]*/
+test1() {
+ var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+ theMap
+ /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+ ['d'] = 5.5;
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+ keys) {
+ aDouble1 = theMap
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [null|exact=JSDouble]})*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume1(aList1);
+}
+
+/*element: aDouble2:[null|exact=JSDouble]*/
+double aDouble2 = 42.5;
+
+/*element: aList2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList2 = [42];
+
+/*element: consume2:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume2(
+ /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+ x;
+
+/*element: test2:[null]*/
+test2() {
+ dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+ theMap
+ /*update: Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ [aList2] = 5.5;
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ keys) {
+ aDouble2 = theMap
+ /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume2(aList2);
+}
+
+/*element: aDouble3:Union([exact=JSDouble], [null|exact=JSExtendableArray])*/
+double aDouble3 = 42.5;
+
+/*element: aList3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList3 = [42];
+
+/*element: consume3:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume3(
+ /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+ x;
+
+/*element: test3:[null]*/
+test3() {
+ dynamic theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
+ theMap
+ /*update: Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+ ['d'] = aList3;
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+ keys) {
+ aDouble3 = theMap
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([null|exact=JSExtendableArray], element: [null|subclass=Object], length: null)})*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume3(aList3);
+}
+
+/*element: aDouble4:[null|exact=JSDouble]*/
+double aDouble4 = 42.5;
+
+/*element: aList4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList4 = [42];
+
+/*element: consume4:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume4(
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+ x;
+
+/*element: test4:[null]*/
+test4() {
+ var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': 5.5};
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
+ keys) {
+ aDouble4 = theMap
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: [null|exact=JSDouble], map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: [exact=JSDouble]})*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume4(aList4);
+}
+
+/*element: aDouble5:[null|exact=JSDouble]*/
+double aDouble5 = 42.5;
+
+/*element: aList5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+List aList5 = [42];
+
+/*element: consume5:Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/
+consume5(
+ /*Container([exact=JSExtendableArray], element: [null|subclass=Object], length: null)*/ x) =>
+ x;
+
+/*element: test5:[null]*/
+test5() {
+ var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, aList5: 5.5};
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ keys) {
+ aDouble5 = theMap
+ /*Map([subclass=JsLinkedHashMap], key: Union([exact=JSExtendableArray], [exact=JSString]), value: [null|exact=JSDouble])*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume5(aList5);
+}
+
+/*element: aDouble6:Union([null|exact=JSDouble], [null|exact=JSExtendableArray])*/
+double aDouble6 = 42.5;
+/*element: aList6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+List aList6 = [42];
+
+/*element: consume6:Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/
+consume6(
+ /*Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)*/ x) =>
+ x;
+
+/*element: test6:[null]*/
+test6() {
+ var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, 'd': aList6};
+ /*iterator: [exact=LinkedHashMapKeyIterable]*/
+ /*current: [exact=LinkedHashMapKeyIterator]*/
+ /*moveNext: [exact=LinkedHashMapKeyIterator]*/
+ for (var key in theMap.
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ keys) {
+ aDouble6 = theMap
+ /*Dictionary([subclass=JsLinkedHashMap], key: [exact=JSString], value: Union([null|exact=JSDouble], [null|exact=JSExtendableArray]), map: {a: [exact=JSDouble], b: [exact=JSDouble], c: [exact=JSDouble], d: Container([exact=JSExtendableArray], element: [exact=JSUInt31], length: 1)})*/
+ [key];
+ }
+ // We have to reference it somewhere, so that it always gets resolved.
+ consume6(aList6);
+}
diff --git a/tests/compiler/dart2js/inference/dictionary_types_test.dart b/tests/compiler/dart2js/inference/dictionary_types_test.dart
deleted file mode 100644
index 1d934e6..0000000
--- a/tests/compiler/dart2js/inference/dictionary_types_test.dart
+++ /dev/null
@@ -1,173 +0,0 @@
-// Copyright (c) 2014, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/commandline_options.dart';
-import 'package:expect/expect.dart';
-
-import '../memory_compiler.dart';
-
-var SOURCES = const {
- 'AddAll.dart': """
- var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
- 'list': []};
- var dictionaryB = {'string': "aString", 'int': 42, 'double': 21.5,
- 'list': []};
- var otherDict = {'stringTwo' : "anotherString", 'intTwo' : 84};
- var int = 0;
- var anotherInt = 0;
- var nullOrInt = 0;
- var dynamic = 0;
-
- main() {
- dictionaryA.addAll(otherDict);
- dictionaryB.addAll({'stringTwo' : "anotherString", 'intTwo' : 84});
- int = dictionaryB['int'];
- anotherInt = otherDict['intTwo'];
- dynamic = dictionaryA['int'];
- nullOrInt = dictionaryB['intTwo'];
- }
-""",
- 'Union.dart': """
- var dictionaryA = {'string': "aString", 'int': 42, 'double': 21.5,
- 'list': []};
- var dictionaryB = {'string': "aString", 'intTwo': 42, 'list': []};
- var nullOrInt = 0;
- var aString = "";
- var doubleOrNull = 22.2;
- var key = "string";
-
- main() {
- var union = dictionaryA['foo'] ? dictionaryA : dictionaryB;
- nullOrInt = union['intTwo'];
- aString = union['string'];
- doubleOrNull = union['double'];
- }
-""",
- 'ValueType.dart': """
- var dictionary = {'string': "aString", 'int': 42, 'double': 21.5, 'list': []};
- var keyD = 'double';
- var keyI = 'int';
- var keyN = 'notFoundInMap';
- var knownDouble = 42.2;
- var intOrNull = dictionary[keyI];
- var justNull = dictionary[keyN];
-
- main() {
- knownDouble = dictionary[keyD];
- var x = [intOrNull, justNull];
- }
-""",
- 'Propagation.dart': """
- class A {
- A();
- foo(value) {
- return value['anInt'];
- }
- }
-
- class B {
- B();
- foo(value) {
- return 0;
- }
- }
-
- main() {
- var dictionary = {'anInt': 42, 'aString': "theString"};
- var it;
- if ([true, false][0]) {
- it = new A();
- } else {
- it = new B();
- }
- print(it.foo(dictionary) + 2);
- }
-""",
- 'Bailout.dart': """
- var dict = makeMap([1,2]);
- var notInt = 0;
- var alsoNotInt = 0;
-
- makeMap(values) {
- return {'moo': values[0], 'boo': values[1]};
- }
-
- main () {
- dict['goo'] = 42;
- var closure = () => dict;
- notInt = closure()['boo'];
- alsoNotInt = dict['goo'];
- print("\$notInt and \$alsoNotInt.");
- }
-"""
-};
-
-void main() {
- asyncTest(() async {
- print('--test from ast---------------------------------------------------');
- await runTests(useKernel: false);
- print('--test from kernel------------------------------------------------');
- await runTests(useKernel: true);
- });
-}
-
-runTests({bool useKernel}) async {
- await compileAndTest("AddAll.dart", (types, getType, closedWorld) {
- Expect.equals(getType('int'), types.uint31Type);
- Expect.equals(getType('anotherInt'), types.uint31Type);
- Expect.equals(getType('dynamic'), types.dynamicType);
- Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
- }, useKernel: useKernel);
- await compileAndTest("Union.dart", (types, getType, closedWorld) {
- Expect.equals(getType('nullOrInt'), types.uint31Type.nullable());
- Expect.isTrue(getType('aString').containsOnlyString(closedWorld));
- Expect.equals(getType('doubleOrNull'), types.doubleType.nullable());
- }, useKernel: useKernel);
- await compileAndTest("ValueType.dart", (types, getType, closedWorld) {
- Expect.equals(getType('knownDouble'), types.doubleType);
- Expect.equals(getType('intOrNull'), types.uint31Type.nullable());
- Expect.equals(getType('justNull'), types.nullType);
- }, useKernel: useKernel);
- await compileAndTest("Propagation.dart", (code) {
- Expect.isFalse(code.contains("J.\$add\$ns"));
- }, createCode: true, useKernel: useKernel);
- await compileAndTest("Bailout.dart", (types, getType, closedWorld) {
- Expect.equals(getType('notInt'), types.dynamicType);
- Expect.equals(getType('alsoNotInt'), types.dynamicType);
- Expect.isFalse(getType('dict').isDictionary);
- }, useKernel: useKernel);
-}
-
-compileAndTest(source, checker,
- {bool createCode: false, bool useKernel}) async {
- CompilationResult result = await runCompiler(
- entryPoint: Uri.parse('memory:' + source),
- memorySourceFiles: SOURCES,
- beforeRun: (compiler) {
- compiler.stopAfterTypeInference = !createCode;
- },
- options: useKernel ? [Flags.useKernel] : []);
- var compiler = result.compiler;
- var typesInferrer = compiler.globalInference.typesInferrerInternal;
- var closedWorld = typesInferrer.closedWorld;
- var elementEnvironment = closedWorld.elementEnvironment;
- var commonMasks = closedWorld.commonMasks;
- getType(String name) {
- var element = elementEnvironment.lookupLibraryMember(
- elementEnvironment.mainLibrary, name);
- Expect.isNotNull(element, "No class '$name' found.");
- return typesInferrer.getTypeOfMember(element);
- }
-
- if (!createCode) {
- checker(commonMasks, getType, closedWorld);
- } else {
- var element = elementEnvironment.mainFunction;
- var code = compiler.backend.getGeneratedCode(element);
- checker(code);
- }
-}
diff --git a/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart b/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart
deleted file mode 100644
index 6b46ce7..0000000
--- a/tests/compiler/dart2js/inference/field_type_simple_inferer_test.dart
+++ /dev/null
@@ -1,689 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:expect/expect.dart';
-import 'package:async_helper/async_helper.dart';
-import 'package:compiler/src/types/types.dart' show TypeMask;
-import 'package:compiler/src/world.dart' show ClosedWorld;
-
-import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
-
-void compileAndFind(String code, String className, String memberName,
- bool disableInlining, check(compiler, element)) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(code, uri, disableInlining: disableInlining);
- asyncTest(() => compiler.run(uri).then((_) {
- dynamic cls = findElement(compiler, className);
- var member = cls.lookupMember(memberName);
- check(compiler, member);
- }));
-}
-
-const String TEST_1 = r"""
- class A {
- int f;
- }
- main() { new A(); }
-""";
-
-const String TEST_2 = r"""
- class A {
- int f1;
- int f2 = 1;
- }
- main() { new A(); }
-""";
-
-const String TEST_3 = r"""
- class A {
- int f1;
- int f2;
- A() : f1 = 1;
- }
- main() { new A().f2 = 2; }
-""";
-
-const String TEST_4 = r"""
- class A {
- int f1;
- int f2;
- A() : f1 = 1;
- }
- main() {
- A a = new A();
- a.f1 = "a";
- a.f2 = "a";
- }
-""";
-
-const String TEST_5 = r"""
- class A {
- int f1 = 1;
- int f2 = 1;
- A(x) {
- f1 = "1";
- if (x) {
- f2 = "1";
- } else {
- f2 = "2";
- }
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_6 = r"""
- class A {
- int f1 = 1;
- int f2 = 1;
- A(x) {
- f1 = "1";
- if (x) {
- f2 = "1";
- } else {
- f2 = "2";
- }
- if (x) {
- f2 = new List();
- } else {
- f2 = new List();
- }
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_7 = r"""
- class A {
- int f1 = 1;
- int f2 = 1;
- A(x) {
- f1 = "1";
- if (x) {
- f2 = "1";
- } else {
- f2 = "2";
- }
- if (x) {
- f1 = new List();
- f2 = new List();
- } else {
- f2 = new List();
- }
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_8 = r"""
- class A {
- int f;
- A(x) {
- if (x) {
- f = "1";
- } else {
- }
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_9 = r"""
- class A {
- int f;
- A(x) {
- if (x) {
- } else {
- f = "1";
- }
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_10 = r"""
- class A {
- int f;
- A() {
- f = 1;
- }
- m() => f + 1;
- }
- void f(x) { x.f = "2"; }
- main() {
- A a;
- f(a);
- a = new A();
- a.m();
- }
-""";
-
-const String TEST_11 = r"""
- class S {
- int fs = 1;
- ms() { fs = 1; }
- }
-
- class A extends S {
- m() { ms(); }
- }
-
- main() {
- A a = new A();
- a.m();
- }
-""";
-
-const String TEST_12 = r"""
- class S {
- int fs = 1;
- S() { fs = "2"; }
- }
-
- class A extends S {
- }
-
- main() {
- A a = new A();
- }
-""";
-
-const String TEST_13 = r"""
- class S {
- int fs;
- S() { fs = 1; }
- }
-
- class A extends S {
- A() { fs = 1; }
- }
-
- main() {
- A a = new A();
- }
-""";
-
-const String TEST_14 = r"""
- class A {
- var f;
- A() { f = 1; }
- A.other() { f = 2; }
- }
-
- main() {
- A a = new A();
- a = new A.other();
- }
-""";
-
-const String TEST_15 = r"""
- class A {
- var f;
- A() { f = "1"; }
- A.other() { f = new List(); }
- }
-
- main() {
- A a = new A();
- a = new A.other();
- }
-""";
-
-const String TEST_16 = r"""
- class A {
- var f;
- A() { f = "1"; }
- A.other() : f = 1 { }
- }
-
- main() {
- A a = new A();
- a = new A.other();
- }
-""";
-
-const String TEST_17 = r"""
- g([p]) => p.f = 1;
- class A {
- var f;
- A(x) {
- var a;
- if (x) {
- a = this;
- } else {
- a = g;
- }
- a(this);
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_18 = r"""
- class A {
- var f1;
- var f2;
- var f3;
- A(x) {
- f1 = 1;
- var a;
- if (x) {
- f2 = "1";
- a = this;
- } else {
- a = 1;
- f2 = "1";
- }
- f3 = a;
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_19 = r"""
- class A {
- var f1;
- var f2;
- var f3;
- A(x) {
- f1 = 1;
- var a;
- if (x) {
- f2 = "1";
- a = this;
- } else {
- a = 1;
- f2 = "1";
- }
- f3 = a;
- a();
- }
- }
- main() {
- new A(true);
- new A(false);
- }
-""";
-
-const String TEST_20 = r"""
- class A {
- var f;
- A() {
- for (f in this) {
- }
- }
- get iterator => this;
- get current => 42;
- bool moveNext() => false;
- }
- main() {
- new A();
- }
-""";
-
-const String TEST_21 = r"""
- class A {
- var f;
- A() {
- for (var i in this) {
- }
- f = 42;
- }
- get iterator => null;
- }
- main() {
- new A();
- }
-""";
-
-const String TEST_22 = r"""
- class A {
- var f1;
- var f2;
- var f3;
- A() {
- f1 = 42;
- f2 = f1 == null ? 42 : f3 == null ? 41: 43;
- f3 = 'foo';
- }
- }
- main() {
- new A();
- }
-""";
-
-const String TEST_23 = r"""
- class A {
- var f1 = 42;
- var f2 = 42;
- var f3 = 42;
- var f4 = 42;
- A() {
- // Test string interpolation.
- '${f1 = null}';
- // Test string juxtaposition.
- ''
- '${f2 = null}';
- // Test list literal.
- [f3 = null];
- // Test map literal.
- var c = {'foo': f4 = null };
- }
- }
- main() {
- new A();
- }
-""";
-
-const String TEST_24 = r"""
- class A {
- var f1 = 42;
- var f2 = 42;
- var f3 = 42;
- final f4;
- var f5;
- var f6 = null;
- A() : f4 = 42 {
- f1++;
- f2 += 42;
- var f6 = 'foo';
- this.f6 = f6;
- }
- A.foo(other) : f3 = other.f3, f4 = other.f4, f5 = other.bar();
- operator+(other) => 'foo';
- bar() => 42.5;
- }
- class B extends A {
- bar() => 42;
- }
- main() {
- new A();
- new A.foo(new A());
- new A.foo(new B());
-
- }
-""";
-
-const String TEST_25 = r"""
- class A {
- var f1 = 42;
- }
- class B {
- var f1 = '42';
- }
- main() {
- new B();
- new A().f1 = new A().f1;
- }
-""";
-
-const String TEST_26 = r"""
- class A {
- var f1 = 42;
- }
- class B {
- var f1 = 54;
- }
- main() {
- new A().f1 = [new B(), new A()][0].f1 + 42;
- }
-""";
-
-const String TEST_27 = r"""
- class A {
- var f1;
- var f2;
- A() {
- this.f1 = 42;
- this.f2 = 42;
- }
- }
- class B extends A {
- set f2(value) {}
- }
- main() {
- new A();
- new B();
- }
-""";
-
-const String TEST_28 = r"""
- class A {
- var f1;
- var f2;
- A(x) {
- this.f1 = x;
- if (x == 0) return;
- this.f2 = x;
- }
- }
- main() {
- new A(0);
- new A(1);
- }
-""";
-
-const String TEST_29 = r"""
- class A {
- var f1;
- var f2;
- A(x) {
- this.f1 = x;
- if (x == 0) {
- } else {
- return;
- }
- this.f2 = x;
- }
- }
- main() {
- new A(0);
- new A(1);
- }
-""";
-
-const String TEST_30 = r"""
- class A {
- var f1;
- var f2;
- var f3;
- A(x) {
- this.f1 = x;
- if (x == 0) {
- this.f2 = 1;
- } else {
- this.f2 = x;
- return;
- }
- this.f3 = x;
- }
- }
- main() {
- new A(0);
- new A(1);
- }
-""";
-
-typedef TypeMask TestCallback(ClosedWorld closedWorld);
-
-void doTest(
- String test, bool disableInlining, Map<String, TestCallback> fields) {
- fields.forEach((String name, TestCallback f) {
- compileAndFind(test, 'A', name, disableInlining, (compiler, field) {
- var inferrer = compiler.globalInference.typesInferrerInternal;
- var closedWorld = inferrer.closedWorld;
- TypeMask type = f(closedWorld);
- TypeMask inferredType =
- simplify(inferrer.getTypeOfMember(field), closedWorld);
- Expect.equals(type, inferredType, '$name of:\n$test');
- });
- });
-}
-
-void runTest(String test, Map<String, TestCallback> fields) {
- doTest(test, false, fields);
- doTest(test, true, fields);
-}
-
-void test() {
- runTest(TEST_1, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.nullType
- });
- runTest(TEST_2, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.nullType,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
- runTest(TEST_3, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_4, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
- 'f2': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
- });
-
- // TODO(ngeoffray): We should try to infer that the initialization
- // code at the declaration site of the fields does not matter.
- runTest(TEST_5, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
- 'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
- });
- runTest(TEST_6, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
- 'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
- });
- runTest(TEST_7, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.interceptorType,
- 'f2': (closedWorld) => closedWorld.commonMasks.interceptorType,
- });
-
- runTest(TEST_8, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
- });
- runTest(TEST_9, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
- });
- runTest(TEST_10, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
- runTest(TEST_11, <String, TestCallback>{
- 'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
-
- // TODO(ngeoffray): We should try to infer that the initialization
- // code at the declaration site of the fields does not matter.
- runTest(TEST_12, <String, TestCallback>{
- 'fs': (closedWorld) => closedWorld.commonMasks.interceptorType
- });
-
- runTest(TEST_13, <String, TestCallback>{
- 'fs': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
- runTest(TEST_14, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
- runTest(TEST_15, <String, TestCallback>{
- 'f': (closedWorld) {
- ClassElement cls = closedWorld.commonElements.jsIndexableClass;
- return new TypeMask.nonNullSubtype(cls, closedWorld);
- }
- });
- runTest(TEST_16, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.interceptorType
- });
- runTest(TEST_17, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_18, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.stringType,
- 'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
- });
- runTest(TEST_19, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.stringType,
- 'f3': (closedWorld) => closedWorld.commonMasks.dynamicType
- });
- runTest(TEST_20, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_21, <String, TestCallback>{
- 'f': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
-
- runTest(TEST_22, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f3': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
- });
-
- runTest(TEST_23, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
- 'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable(),
- 'f4': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
-
- runTest(TEST_24, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType,
- 'f2': (closedWorld) => closedWorld.commonMasks.positiveIntType,
- 'f3': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f4': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f5': (closedWorld) => closedWorld.commonMasks.numType.nullable(),
- 'f6': (closedWorld) => closedWorld.commonMasks.stringType.nullable()
- });
-
- runTest(TEST_25, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type
- });
- runTest(TEST_26, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.positiveIntType
- });
- runTest(TEST_27, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_28, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_29, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
- runTest(TEST_30, <String, TestCallback>{
- 'f1': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f2': (closedWorld) => closedWorld.commonMasks.uint31Type,
- 'f3': (closedWorld) => closedWorld.commonMasks.uint31Type.nullable()
- });
-}
-
-void main() {
- test();
-}
diff --git a/tests/compiler/dart2js/inference/list_tracer_length_test.dart b/tests/compiler/dart2js/inference/list_tracer_length_test.dart
index 5ad3506..d5e8d72 100644
--- a/tests/compiler/dart2js/inference/list_tracer_length_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_length_test.dart
@@ -2,7 +2,8 @@
// 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.
-/// TODO(johnniwinther): Currently this only works with the mock compiler.
+/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
+/// works with the mock compiler.
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
diff --git a/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart b/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
index b1d315f..03ae59c 100644
--- a/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_node_type_test.dart
@@ -2,7 +2,8 @@
// 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.
-/// TODO(johnniwinther): Currently this only works with the mock compiler.
+/// TODO(johnniwinther): Move this to the codegen folder. Currently this only
+/// works with the mock compiler.
import "package:expect/expect.dart";
import "package:async_helper/async_helper.dart";
diff --git a/tests/compiler/dart2js/inference/list_tracer_test.dart b/tests/compiler/dart2js/inference/list_tracer_test.dart
index b9f5e819..831ead7 100644
--- a/tests/compiler/dart2js/inference/list_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/list_tracer_test.dart
@@ -5,12 +5,13 @@
/// TODO(johnniwinther): Port this test to use the equivalence framework.
/// Currently it only works with the mock compiler.
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
+import 'package:compiler/src/commandline_options.dart';
+import 'package:expect/expect.dart';
import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
+import '../memory_compiler.dart';
String generateTest(String listAllocation) {
return """
@@ -189,58 +190,76 @@
}
void main() {
- doTest('[]', nullify: false); // Test literal list.
- doTest('new List()', nullify: false); // Test growable list.
- doTest('new List(1)', nullify: true); // Test fixed list.
- doTest('new List.filled(1, 0)', nullify: false); // Test List.filled.
- doTest('new List.filled(1, null)', nullify: true); // Test List.filled.
+ runTest({bool useKernel}) async {
+ // Test literal list.
+ await doTest('[]', nullify: false, useKernel: useKernel);
+ // Test growable list.
+ await doTest('new List()', nullify: false, useKernel: useKernel);
+ // Test fixed list.
+ await doTest('new List(1)', nullify: true, useKernel: useKernel);
+ // Test List.filled.
+ await doTest('new List.filled(1, 0)', nullify: false, useKernel: useKernel);
+ // Test List.filled.
+ await doTest('new List.filled(1, null)',
+ nullify: true, useKernel: useKernel);
+ }
+
+ asyncTest(() async {
+ print('--test from ast---------------------------------------------------');
+ await runTest(useKernel: false);
+ print('--test from kernel------------------------------------------------');
+ await runTest(useKernel: true);
+ });
}
-void doTest(String allocation, {bool nullify}) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(generateTest(allocation), uri,
- expectedErrors: 0, expectedWarnings: 1);
- asyncTest(() => compiler.run(uri).then((_) {
- var typesInferrer = compiler.globalInference.typesInferrerInternal;
- var closedWorld = typesInferrer.closedWorld;
- var commonMasks = closedWorld.commonMasks;
+doTest(String allocation, {bool nullify, bool useKernel}) async {
+ String source = generateTest(allocation);
+ var result = await runCompiler(
+ memorySourceFiles: {'main.dart': source},
+ options: useKernel ? [Flags.useKernel] : []);
+ Expect.isTrue(result.isSuccess);
+ var compiler = result.compiler;
+ var typesInferrer = compiler.globalInference.typesInferrerInternal;
+ var closedWorld = typesInferrer.closedWorld;
+ var commonMasks = closedWorld.commonMasks;
- checkType(String name, type) {
- MemberElement element = findElement(compiler, name);
- ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
- if (nullify) type = type.nullable();
- Expect.equals(type, simplify(mask.elementType, closedWorld), name);
- }
+ checkType(String name, type) {
+ var element = findMember(closedWorld, name);
+ ContainerTypeMask mask = typesInferrer.getTypeOfMember(element);
+ if (nullify) type = type.nullable();
+ Expect.equals(type, simplify(mask.elementType, closedWorld), name);
+ }
- checkType('listInField', commonMasks.numType);
- checkType('listPassedToMethod', commonMasks.numType);
- checkType('listReturnedFromMethod', commonMasks.numType);
- checkType('listUsedWithCascade', commonMasks.numType);
- checkType('listUsedInClosure', commonMasks.numType);
- checkType('listPassedToSelector', commonMasks.numType);
- checkType('listReturnedFromSelector', commonMasks.numType);
- checkType('listUsedWithAddAndInsert', commonMasks.numType);
- checkType('listUsedWithConstraint', commonMasks.positiveIntType);
- checkType('listEscapingFromSetter', commonMasks.numType);
- checkType('listUsedInLocal', commonMasks.numType);
- checkType('listEscapingInSetterValue', commonMasks.numType);
- checkType('listEscapingInIndex', commonMasks.numType);
- checkType('listEscapingInIndexSet', commonMasks.uint31Type);
- checkType('listEscapingTwiceInIndexSet', commonMasks.numType);
- checkType('listSetInNonFinalField', commonMasks.numType);
- checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
+ checkType('listInField', commonMasks.numType);
+ checkType('listPassedToMethod', commonMasks.numType);
+ checkType('listReturnedFromMethod', commonMasks.numType);
+ checkType('listUsedWithCascade', commonMasks.numType);
+ checkType('listUsedInClosure', commonMasks.numType);
+ checkType('listPassedToSelector', commonMasks.numType);
+ checkType('listReturnedFromSelector', commonMasks.numType);
+ checkType('listUsedWithAddAndInsert', commonMasks.numType);
+ checkType('listUsedWithConstraint', commonMasks.positiveIntType);
+ checkType('listEscapingFromSetter', commonMasks.numType);
+ checkType('listUsedInLocal', commonMasks.numType);
+ checkType('listEscapingInSetterValue', commonMasks.numType);
+ checkType('listEscapingInIndex', commonMasks.numType);
+ checkType('listEscapingInIndexSet', commonMasks.uint31Type);
+ // TODO(johnniwinther): Since Iterable.iterableToString is part of the closed
+ // world we find the `dynamicType` instead of `numType`.
+ checkType('listEscapingTwiceInIndexSet', commonMasks.dynamicType);
+ checkType('listSetInNonFinalField', commonMasks.numType);
+ checkType('listWithChangedLength', commonMasks.uint31Type.nullable());
- checkType('listPassedToClosure', commonMasks.dynamicType);
- checkType('listReturnedFromClosure', commonMasks.dynamicType);
- checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
- checkType('listPassedAsOptionalParameter', commonMasks.numType);
- checkType('listPassedAsNamedParameter', commonMasks.numType);
- checkType('listStoredInList', commonMasks.uint31Type);
- checkType('listStoredInListButEscapes', commonMasks.dynamicType);
+ checkType('listPassedToClosure', commonMasks.dynamicType);
+ checkType('listReturnedFromClosure', commonMasks.dynamicType);
+ checkType('listUsedWithNonOkSelector', commonMasks.dynamicType);
+ checkType('listPassedAsOptionalParameter', commonMasks.numType);
+ checkType('listPassedAsNamedParameter', commonMasks.numType);
+ checkType('listStoredInList', commonMasks.uint31Type);
+ checkType('listStoredInListButEscapes', commonMasks.dynamicType);
- if (!allocation.contains('filled')) {
- checkType('listUnset', new TypeMask.nonNullEmpty());
- checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
- }
- }));
+ if (!allocation.contains('filled')) {
+ checkType('listUnset', new TypeMask.nonNullEmpty());
+ checkType('listOnlySetWithConstraint', new TypeMask.nonNullEmpty());
+ }
}
diff --git a/tests/compiler/dart2js/inference/map_tracer_keys_test.dart b/tests/compiler/dart2js/inference/map_tracer_keys_test.dart
deleted file mode 100644
index e968733..0000000
--- a/tests/compiler/dart2js/inference/map_tracer_keys_test.dart
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (c) 2014, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-/// Currently it only works with the mock compiler.
-
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
-import 'package:compiler/src/types/types.dart' show ContainerTypeMask, TypeMask;
-
-import '../compiler_helper.dart';
-
-String generateTest(String key, String value, bool initial) {
- return """
-double aDouble = 42.5;
-List aList = [42];
-
-consume(x) => x;
-
-main() {
-""" +
- (initial
- ? """
- var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4, $key: $value};
-"""
- : """
- var theMap = {'a': 2.2, 'b': 3.3, 'c': 4.4};
- theMap[$key] = $value;
-""") +
- """
- for (var key in theMap.keys) {
- aDouble = theMap[key];
- }
- // We have to reference it somewhere, so that it always gets resolved.
- consume(aList);
-}
-""";
-}
-
-void main() {
- // Test using keys without the list floating in
- doTest();
- // Test using keys with the list floating in as key
- doTest(key: "aList", bail: true);
- // Test using keys with the list floating in as value
- doTest(value: "aList");
- // And the above where we add the list as part of the map literal.
- doTest(initial: true);
- doTest(key: "aList", bail: true, initial: true);
- doTest(value: "aList", initial: true);
-}
-
-void doTest(
- {String key: "'d'",
- String value: "5.5",
- bool bail: false,
- bool initial: false}) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(generateTest(key, value, initial), uri,
- expectedErrors: 0, expectedWarnings: 0);
- asyncTest(() => compiler.run(uri).then((_) {
- var typesInferrer = compiler.globalInference.typesInferrerInternal;
- var commonMasks = typesInferrer.closedWorld.commonMasks;
- MemberElement aDouble = findElement(compiler, 'aDouble');
- var aDoubleType = typesInferrer.getTypeOfMember(aDouble);
- MemberElement aList = findElement(compiler, 'aList');
- var aListType = typesInferrer.getTypeOfMember(aList);
-
- Expect.equals(aDoubleType, commonMasks.doubleType);
- Expect.isTrue(aListType is ContainerTypeMask);
- ContainerTypeMask container = aListType;
- TypeMask elementType = container.elementType;
- if (bail) {
- Expect.equals(elementType, commonMasks.dynamicType);
- } else {
- Expect.equals(elementType, commonMasks.uint31Type);
- }
- }));
-}
diff --git a/tests/compiler/dart2js/inference/map_tracer_test.dart b/tests/compiler/dart2js/inference/map_tracer_test.dart
index ddac6fd..8e8309e 100644
--- a/tests/compiler/dart2js/inference/map_tracer_test.dart
+++ b/tests/compiler/dart2js/inference/map_tracer_test.dart
@@ -5,12 +5,17 @@
/// TODO(johnniwinther): Port this test to use the equivalence framework.
/// Currently it only works with the mock compiler.
-import 'package:expect/expect.dart';
-import "package:async_helper/async_helper.dart";
+import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
+import 'package:compiler/src/compiler.dart';
+import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
import 'package:compiler/src/types/types.dart' show MapTypeMask, TypeMask;
+import 'package:compiler/src/world.dart';
+import 'package:expect/expect.dart';
import 'type_mask_test_helper.dart';
-import '../compiler_helper.dart';
+import '../memory_compiler.dart';
String generateTest(String mapAllocation) {
return """
@@ -119,6 +124,8 @@
}
main() {
+ anInt++;
+
mapReturnedFromMethod[aKey] = anInt;
bar()[aKey] = aDouble;
@@ -202,90 +209,103 @@
}
void main() {
- // Test empty literal map
- doTest('{}');
- // Test preset map of <String,uint32>
- doTest('{presetKey : anInt}', "presetKey", "anInt");
- // Test preset map of <Double,uint32>
- doTest('{aDouble : anInt}', "aDouble", "anInt");
+ runTests({bool useKernel}) async {
+ // Test empty literal map
+ await doTest('{}', useKernel: useKernel);
+ // Test preset map of <String,uint32>
+ await doTest('{presetKey : anInt}',
+ keyElementName: "presetKey",
+ valueElementName: "anInt",
+ useKernel: useKernel);
+ // Test preset map of <Double,uint32>
+ await doTest('{aDouble : anInt}',
+ keyElementName: "aDouble",
+ valueElementName: "anInt",
+ useKernel: useKernel);
+ }
+
+ asyncTest(() async {
+ print('--test from ast---------------------------------------------------');
+ await runTests(useKernel: false);
+ print('--test from kernel------------------------------------------------');
+ await runTests(useKernel: true);
+ });
}
-void doTest(String allocation,
- [String keyElementName, String valueElementName]) {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(generateTest(allocation), uri,
- expectedErrors: 0, expectedWarnings: 1);
- asyncTest(() => compiler.run(uri).then((_) {
- var keyType, valueType;
- var typesInferrer = compiler.globalInference.typesInferrerInternal;
- var closedWorld = typesInferrer.closedWorld;
- var commonMasks = closedWorld.commonMasks;
- var emptyType = new TypeMask.nonNullEmpty();
- MemberElement aKey = findElement(compiler, 'aKey');
- var aKeyType = typesInferrer.getTypeOfMember(aKey);
- if (keyElementName != null) {
- MemberElement keyElement = findElement(compiler, keyElementName);
- keyType = typesInferrer.getTypeOfMember(keyElement);
- }
- if (valueElementName != null) {
- MemberElement valueElement = findElement(compiler, valueElementName);
- valueType = typesInferrer.getTypeOfMember(valueElement);
- }
- if (keyType == null) keyType = emptyType;
- if (valueType == null) valueType = emptyType;
+doTest(String allocation,
+ {String keyElementName, String valueElementName, bool useKernel}) async {
+ String source = generateTest(allocation);
+ var result = await runCompiler(
+ memorySourceFiles: {'main.dart': source},
+ options: useKernel ? [Flags.useKernel] : []);
+ Expect.isTrue(result.isSuccess);
+ Compiler compiler = result.compiler;
+ TypeMask keyType, valueType;
+ TypeGraphInferrer typesInferrer =
+ compiler.globalInference.typesInferrerInternal;
+ ClosedWorld closedWorld = typesInferrer.closedWorld;
+ CommonMasks commonMasks = closedWorld.commonMasks;
+ TypeMask emptyType = new TypeMask.nonNullEmpty();
+ MemberEntity aKey = findMember(closedWorld, 'aKey');
+ TypeMask aKeyType = typesInferrer.getTypeOfMember(aKey);
+ if (keyElementName != null) {
+ MemberEntity keyElement = findMember(closedWorld, keyElementName);
+ keyType = typesInferrer.getTypeOfMember(keyElement);
+ }
+ if (valueElementName != null) {
+ MemberEntity valueElement = findMember(closedWorld, valueElementName);
+ valueType = typesInferrer.getTypeOfMember(valueElement);
+ }
+ if (keyType == null) keyType = emptyType;
+ if (valueType == null) valueType = emptyType;
- checkType(String name, keyType, valueType) {
- MemberElement element = findElement(compiler, name);
- MapTypeMask mask = typesInferrer.getTypeOfMember(element);
- Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
- Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
- }
+ checkType(String name, keyType, valueType) {
+ MemberEntity element = findMember(closedWorld, name);
+ MapTypeMask mask = typesInferrer.getTypeOfMember(element);
+ Expect.equals(keyType, simplify(mask.keyType, closedWorld), name);
+ Expect.equals(valueType, simplify(mask.valueType, closedWorld), name);
+ }
- K(TypeMask other) =>
- simplify(keyType.union(other, closedWorld), closedWorld);
- V(TypeMask other) =>
- simplify(valueType.union(other, closedWorld), closedWorld)
- .nullable();
+ K(TypeMask other) => simplify(keyType.union(other, closedWorld), closedWorld);
+ V(TypeMask other) =>
+ simplify(valueType.union(other, closedWorld), closedWorld).nullable();
- checkType('mapInField', K(aKeyType), V(commonMasks.numType));
- checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
- checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
- checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
- checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
- checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
- checkType(
- 'mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
- checkType(
- 'mapUsedWithConstraint', K(aKeyType), V(commonMasks.uint31Type));
- checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
- checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
- checkType(
- 'mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
- checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
- checkType(
- 'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.uint31Type));
- checkType(
- 'mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
- checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
+ checkType('mapInField', K(aKeyType), V(commonMasks.numType));
+ checkType('mapPassedToMethod', K(aKeyType), V(commonMasks.numType));
+ checkType('mapReturnedFromMethod', K(aKeyType), V(commonMasks.numType));
+ checkType('mapUsedWithCascade', K(aKeyType), V(commonMasks.numType));
+ checkType('mapUsedInClosure', K(aKeyType), V(commonMasks.numType));
+ checkType('mapPassedToSelector', K(aKeyType), V(commonMasks.numType));
+ checkType('mapReturnedFromSelector', K(aKeyType), V(commonMasks.numType));
+ checkType(
+ 'mapUsedWithConstraint', K(aKeyType), V(commonMasks.positiveIntType));
+ checkType('mapEscapingFromSetter', K(aKeyType), V(commonMasks.numType));
+ checkType('mapUsedInLocal', K(aKeyType), V(commonMasks.numType));
+ checkType('mapEscapingInSetterValue', K(aKeyType), V(commonMasks.numType));
+ checkType('mapEscapingInIndex', K(aKeyType), V(commonMasks.numType));
+ checkType(
+ 'mapEscapingInIndexSet', K(aKeyType), V(commonMasks.positiveIntType));
+ // TODO(johnniwinther): Reenable this when we don't bail out due to
+ // (benign) JS calls.
+ //checkType('mapEscapingTwiceInIndexSet', K(aKeyType), V(commonMasks.numType));
+ checkType('mapSetInNonFinalField', K(aKeyType), V(commonMasks.numType));
- checkType('mapPassedToClosure', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapPassedAsOptionalParameter', K(aKeyType),
- V(commonMasks.numType));
- checkType(
- 'mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
- checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
- checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
- checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
- checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
- V(commonMasks.dynamicType));
+ checkType('mapPassedToClosure', K(commonMasks.dynamicType),
+ V(commonMasks.dynamicType));
+ checkType('mapReturnedFromClosure', K(commonMasks.dynamicType),
+ V(commonMasks.dynamicType));
+ checkType('mapUsedWithNonOkSelector', K(commonMasks.dynamicType),
+ V(commonMasks.dynamicType));
+ checkType(
+ 'mapPassedAsOptionalParameter', K(aKeyType), V(commonMasks.numType));
+ checkType('mapPassedAsNamedParameter', K(aKeyType), V(commonMasks.numType));
+ checkType('mapStoredInList', K(aKeyType), V(commonMasks.uint31Type));
+ checkType('mapStoredInListButEscapes', K(commonMasks.dynamicType),
+ V(commonMasks.dynamicType));
+ checkType('mapStoredInMap', K(aKeyType), V(commonMasks.uint31Type));
+ checkType('mapStoredInMapButEscapes', K(commonMasks.dynamicType),
+ V(commonMasks.dynamicType));
- checkType('mapUnset', K(emptyType), V(emptyType));
- checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
- }));
+ checkType('mapUnset', K(emptyType), V(emptyType));
+ checkType('mapOnlySetWithConstraint', K(aKeyType), V(emptyType));
}
diff --git a/tests/compiler/dart2js/inference/show.dart b/tests/compiler/dart2js/inference/show.dart
index 6870b5f..3d7c465 100644
--- a/tests/compiler/dart2js/inference/show.dart
+++ b/tests/compiler/dart2js/inference/show.dart
@@ -4,9 +4,35 @@
/// Helper program that shows the inferrer data on a dart program.
+import 'package:args/args.dart';
+import 'package:compiler/src/inferrer/inferrer_engine.dart';
+import '../equivalence/id_equivalence_helper.dart';
import '../equivalence/show_helper.dart';
import 'inference_test_helper.dart';
+import 'side_effects_test.dart';
+import 'callers_test.dart';
main(List<String> args) async {
- await show(args, computeMemberAstTypeMasks, computeMemberIrTypeMasks);
+ ArgParser argParser = createArgParser();
+ argParser.addFlag('inference', defaultsTo: true);
+ argParser.addFlag('side-effects', defaultsTo: false);
+ argParser.addFlag('callers', defaultsTo: false);
+ ArgResults results = argParser.parse(args);
+
+ ComputeMemberDataFunction astFunction;
+ ComputeMemberDataFunction kernelFunction;
+ if (results['side-effects']) {
+ astFunction = computeMemberAstSideEffects;
+ kernelFunction = computeMemberIrSideEffects;
+ }
+ if (results['callers']) {
+ InferrerEngineImpl.retainDataForTesting = true;
+ astFunction = computeMemberAstCallers;
+ kernelFunction = computeMemberIrCallers;
+ } else {
+ InferrerEngineImpl.useSorterForTesting = true;
+ astFunction = computeMemberAstTypeMasks;
+ kernelFunction = computeMemberIrTypeMasks;
+ }
+ await show(results, astFunction, kernelFunction);
}
diff --git a/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart b/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart
deleted file mode 100644
index 91fd918..0000000
--- a/tests/compiler/dart2js/inference/simple_inferrer_callers_test.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2013, 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.
-
-/// TODO(johnniwinther): Port this test to use the equivalence framework.
-
-// Test that computation of callers of an element works when two
-// elements of the same name are being invoked in the same method.
-
-import 'package:async_helper/async_helper.dart';
-import 'package:expect/expect.dart';
-import 'package:compiler/src/common_elements.dart';
-import 'package:compiler/src/inferrer/type_graph_inferrer.dart';
-import 'package:compiler/src/world.dart' show ClosedWorld, ClosedWorldRefiner;
-
-import '../compiler_helper.dart';
-
-const String TEST = """
-class A {
- var field;
-}
-
-class B {
- var field;
-}
-
-main() {
- new A().field;
- new B().field;
-}
-""";
-
-// Create our own type inferrer to avoid clearing out the internal
-// data structures.
-class MyInferrer extends AstTypeGraphInferrer {
- MyInferrer(compiler, closedWorld, closedWorldRefiner)
- : super(compiler, closedWorld, closedWorldRefiner);
- clear() {}
-}
-
-void main() {
- Uri uri = new Uri(scheme: 'source');
- var compiler = mockCompilerFor(TEST, uri, analyzeOnly: true);
- asyncTest(() => compiler.run(uri).then((_) {
- ElementEnvironment elementEnvironment =
- compiler.frontendStrategy.elementEnvironment;
- ClosedWorldRefiner closedWorldRefiner =
- compiler.closeResolution(elementEnvironment.mainFunction);
- ClosedWorld closedWorld =
- compiler.resolutionWorldBuilder.closedWorldForTesting;
- var inferrer =
- new MyInferrer(compiler, closedWorld, closedWorldRefiner);
- compiler.globalInference.typesInferrerInternal = inferrer;
- compiler.globalInference.runGlobalTypeInference(
- closedWorld.elementEnvironment.mainFunction,
- closedWorld,
- closedWorldRefiner);
- var mainElement = findElement(compiler, 'main');
- dynamic classA = findElement(compiler, 'A');
- var fieldA = classA.lookupLocalMember('field');
- dynamic classB = findElement(compiler, 'B');
- var fieldB = classB.lookupLocalMember('field');
-
- Expect.isTrue(inferrer.getCallersOf(fieldA).contains(mainElement));
- Expect.isTrue(inferrer.getCallersOf(fieldB).contains(mainElement));
- }));
-}
diff --git a/tests/compiler/dart2js/inlining/inlining_viewer.dart b/tests/compiler/dart2js/inlining/inlining_viewer.dart
index ed25d93..9ec0739 100644
--- a/tests/compiler/dart2js/inlining/inlining_viewer.dart
+++ b/tests/compiler/dart2js/inlining/inlining_viewer.dart
@@ -10,5 +10,6 @@
main(List<String> args) async {
JavaScriptBackend.cacheCodegenImpactForTesting = true;
- await show(args, computeMemberAstInlinings, computeMemberIrInlinings);
+ await show(createArgParser().parse(args), computeMemberAstInlinings,
+ computeMemberIrInlinings);
}