[vm/kernel] Unit tests for type flow analysis

Issue: https://github.com/dart-lang/sdk/issues/30480
Change-Id: If6cf8c7dfb59703b00f5432ce803f81e1bf90232
Reviewed-on: https://dart-review.googlesource.com/34301
Commit-Queue: Alexander Markov <alexmarkov@google.com>
Reviewed-by: Martin Kustermann <kustermann@google.com>
Reviewed-by: Vyacheslav Egorov <vegorov@google.com>
This commit is contained in:
Alexander Markov 2018-01-19 00:55:34 +00:00 committed by commit-bot@chromium.org
parent bc22c3e050
commit bcdb32bc1a
29 changed files with 1512 additions and 7 deletions

View file

@ -49,6 +49,7 @@ front_end/tool/_fasta/compile_platform_test: Fail
front_end/tool/incremental_perf_test: Slow, Pass
kernel/test/closures_test: Slow, Pass
kernel/testcases/*: Skip # These are not tests but input for tests.
vm/testcases/*: SkipByDesign # These are not tests but input for tests.
[ $compiler == dart2analyzer ]
dev_compiler/test/options/*: SkipByDesign
@ -112,6 +113,7 @@ mutation_observer: Skip # Skip tests on the VM if the package depends on dart:ht
[ $runtime != vm ]
dev_compiler/test/options/*: SkipByDesign
front_end/test/src/incremental/hot_reload_e2e_test: Skip
vm/test/*: SkipByDesign # Only meant to run on vm
[ $system == windows ]
front_end/test/fasta/bootstrap_test: Skip # Issue 31902

View file

@ -24,7 +24,6 @@ import 'utils.dart';
// organized in several categories:
//
// === Correctness ===
// * Add unit tests!!!
// * Support dynamic calls via getters & dynamic tear-offs.
// * Re-evaluate field initializer if its dependency changes (avoid
// re-using cached value).

View file

@ -27,7 +27,12 @@ const bool kDumpAllSummaries =
/// Whole-program type flow analysis and transformation.
/// Assumes strong mode and closed world.
Program transformProgram(CoreTypes coreTypes, Program program) {
Program transformProgram(CoreTypes coreTypes, Program program,
// TODO(alexmarkov): Pass entry points descriptors from command line.
{List<String> entryPointsJSONFiles: const [
'pkg/vm/lib/transformations/type_flow/entry_points.json',
'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
]}) {
final hierarchy = new ClassHierarchy(program);
final types = new TypeEnvironment(coreTypes, hierarchy, strongMode: true);
final libraryIndex = new LibraryIndex.all(program);
@ -42,11 +47,7 @@ Program transformProgram(CoreTypes coreTypes, Program program) {
final analysisStopWatch = new Stopwatch()..start();
final typeFlowAnalysis = new TypeFlowAnalysis(hierarchy, types, libraryIndex,
// TODO(alexmarkov): Pass entry points descriptors from command line.
entryPointsJSONFiles: [
'pkg/vm/lib/transformations/type_flow/entry_points.json',
'pkg/vm/lib/transformations/type_flow/entry_points_extra.json',
]);
entryPointsJSONFiles: entryPointsJSONFiles);
Procedure main = program.mainMethod;
final Selector mainSelector = new DirectSelector(main);

View file

@ -0,0 +1,42 @@
// 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:async';
import 'dart:io';
import 'package:front_end/src/api_prototype/front_end.dart';
import 'package:front_end/src/compute_platform_binaries_location.dart'
show computePlatformBinariesLocation;
import 'package:kernel/ast.dart';
import 'package:kernel/target/targets.dart';
import 'package:kernel/target/vm.dart';
import 'package:test/test.dart';
const bool kDumpActualResult = const bool.fromEnvironment('dump.actual.result');
Future<Program> compileTestCaseToKernelProgram(Uri sourceUri) async {
final platformKernel =
computePlatformBinariesLocation().resolve('vm_platform_strong.dill');
final options = new CompilerOptions()
..strongMode = true
..target = new VmTarget(new TargetFlags(strongMode: true))
..linkedDependencies = <Uri>[platformKernel]
..reportMessages = true
..onError = (CompilationMessage error) {
fail("Compilation error: ${error}");
};
return kernelForProgram(sourceUri, options);
}
void compareResultWithExpectationsFile(Uri source, String actual) {
final expectFile = new File(source.toFilePath() + '.expect');
final expected = expectFile.existsSync() ? expectFile.readAsStringSync() : '';
if (actual != expected) {
if (kDumpActualResult) {
new File(source.toFilePath() + '.actual').writeAsStringSync(actual);
}
expect(actual, equals(expected), reason: "Test case: $source");
}
}

View file

@ -0,0 +1,69 @@
// 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:kernel/ast.dart';
import 'package:kernel/class_hierarchy.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/type_environment.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/type_flow/native_code.dart';
import 'package:vm/transformations/type_flow/summary_collector.dart';
import 'common_test_utils.dart';
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
class PrintSummaries extends RecursiveVisitor<Null> {
final SummaryCollector _summaryColector;
final StringBuffer _buf = new StringBuffer();
PrintSummaries(TypeEnvironment environment)
: _summaryColector = new SummaryCollector(
environment, new EntryPointsListener(), new NativeCodeOracle(null));
String print(TreeNode node) {
visitLibrary(node);
return _buf.toString();
}
@override
defaultMember(Member member) {
if (!member.isAbstract) {
_buf.writeln("------------ $member ------------");
_buf.writeln(_summaryColector.createSummary(member));
}
}
}
runTestCase(Uri source) async {
final Program program = await compileTestCaseToKernelProgram(source);
final Library library = program.mainMethod.enclosingLibrary;
// Make sure the library name is the same and does not depend on the order
// of test cases.
library.name = '#lib';
final typeEnvironment =
new TypeEnvironment(new CoreTypes(program), new ClassHierarchy(program));
final actual = new PrintSummaries(typeEnvironment).print(library);
compareResultWithExpectationsFile(source, actual);
}
main() {
group('collect-summary', () {
final testCasesDir = new Directory(
pkgVmDir + '/testcases/transformations/type_flow/summary_collector');
for (var entry
in testCasesDir.listSync(recursive: true, followLinks: false)) {
if (entry.path.endsWith(".dart")) {
test(entry.path, () => runTestCase(entry.uri));
}
}
});
}

View file

@ -0,0 +1,53 @@
// 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:kernel/ast.dart';
import 'package:kernel/core_types.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/text/ast_to_text.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/type_flow/transformer.dart'
show transformProgram;
import 'common_test_utils.dart';
final String pkgVmDir = Platform.script.resolve('../../..').toFilePath();
runTestCase(Uri source) async {
Program program = await compileTestCaseToKernelProgram(source);
// Make sure the library name is the same and does not depend on the order
// of test cases.
program.mainMethod.enclosingLibrary.name = '#lib';
final coreTypes = new CoreTypes(program);
program = transformProgram(coreTypes, program, entryPointsJSONFiles: [
pkgVmDir + '/lib/transformations/type_flow/entry_points.json',
pkgVmDir + '/lib/transformations/type_flow/entry_points_extra.json',
]);
final StringBuffer buffer = new StringBuffer();
new Printer(buffer, showExternal: false, showMetadata: true)
.writeLibraryFile(program.mainMethod.enclosingLibrary);
final actual = buffer.toString();
compareResultWithExpectationsFile(source, actual);
}
main() {
group('transform-program', () {
final testCasesDir = new Directory(
pkgVmDir + '/testcases/transformations/type_flow/transformer');
for (var entry
in testCasesDir.listSync(recursive: true, followLinks: false)) {
if (entry.path.endsWith(".dart")) {
test(entry.path, () => runTestCase(entry.uri));
}
}
});
}

View file

@ -0,0 +1,383 @@
// 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:core' hide Type;
import 'package:kernel/ast.dart';
import 'package:test/test.dart';
import 'package:vm/transformations/type_flow/types.dart';
class TestTypeHierarchy implements TypeHierarchy {
final Map<DartType, List<DartType>> subtypes;
final Map<DartType, Type> specializations;
TestTypeHierarchy(this.subtypes, this.specializations);
@override
bool isSubtype(DartType subType, DartType superType) {
return subtypes[superType].contains(subType);
}
@override
Type specializeTypeCone(DartType base) {
Type result = specializations[base];
expect(result, isNotNull,
reason: "specializeTypeCone($base) is not defined");
return result;
}
}
main() {
test('factory-constructors', () {
Class c1 = new Class(name: 'C1');
Class c2 = new Class(name: 'C2', typeParameters: [new TypeParameter('E')]);
InterfaceType t1 = new InterfaceType(c1);
InterfaceType t2Raw = new InterfaceType(c2);
InterfaceType t2Generic = new InterfaceType(c2, [t1]);
FunctionType f1 = new FunctionType([t1], const VoidType());
expect(new Type.empty(), equals(const EmptyType()));
expect(new Type.cone(const DynamicType()), equals(const AnyType()));
expect(new Type.cone(t1), equals(new ConeType(t1)));
expect(new Type.cone(t2Raw), equals(new ConeType(t2Raw)));
expect(new Type.cone(t2Generic), equals(new ConeType(t2Raw)));
expect(new Type.cone(f1), equals(const AnyType()));
expect(new Type.concrete(t1), equals(new ConcreteType(t1)));
expect(new Type.concrete(t2Raw), equals(new ConcreteType(t2Raw)));
expect(new Type.concrete(t2Generic), equals(new ConcreteType(t2Raw)));
expect(new Type.nullable(new Type.empty()),
equals(new NullableType(new EmptyType())));
expect(new Type.nullable(new Type.cone(t1)),
equals(new NullableType(new ConeType(t1))));
expect(new Type.nullable(new Type.concrete(t1)),
equals(new NullableType(new ConcreteType(t1))));
expect(new Type.fromStatic(const DynamicType()),
equals(new NullableType(new AnyType())));
expect(new Type.fromStatic(const BottomType()),
equals(new NullableType(new EmptyType())));
expect(new Type.fromStatic(t1), equals(new NullableType(new ConeType(t1))));
expect(new Type.fromStatic(t2Raw),
equals(new NullableType(new ConeType(t2Raw))));
expect(new Type.fromStatic(t2Generic),
equals(new NullableType(new ConeType(t2Raw))));
});
test('static-type', () {
InterfaceType classType = new InterfaceType(new Class(name: 'C'));
FunctionType funcType = new FunctionType([], const VoidType());
// [T, T.staticType]
final testCases = [
[new Type.cone(classType), classType],
[new Type.cone(funcType), const DynamicType()],
[new Type.concrete(classType), classType],
[new AnyType(), const DynamicType()],
[new Type.nullable(new Type.empty()), const BottomType()],
[new Type.nullable(new Type.cone(classType)), classType],
[new Type.nullable(new Type.concrete(classType)), classType],
[new Type.nullable(new AnyType()), const DynamicType()],
[new Type.fromStatic(const DynamicType()), const DynamicType()],
[new Type.fromStatic(const BottomType()), const BottomType()],
[new Type.fromStatic(classType), classType],
[new Type.fromStatic(funcType), const DynamicType()],
];
for (List testCase in testCases) {
Type type = testCase[0] as Type;
DartType staticType = testCase[1] as DartType;
expect(type.staticType, equals(staticType),
reason:
"Test case: ${type}.staticType is expected to be $staticType");
}
});
test('union-intersection', () {
// T1 <: T3, T2 <: T3
InterfaceType t1 = new InterfaceType(new Class(name: 'T1'));
InterfaceType t2 = new InterfaceType(new Class(name: 'T2'));
InterfaceType t3 = new InterfaceType(new Class(name: 'T3'));
InterfaceType t4 = new InterfaceType(new Class(name: 'T4'));
final empty = new EmptyType();
final any = new AnyType();
final concreteT1 = new ConcreteType(t1);
final concreteT2 = new ConcreteType(t2);
final concreteT3 = new ConcreteType(t3);
final concreteT4 = new ConcreteType(t4);
final coneT1 = new ConeType(t1);
final coneT2 = new ConeType(t2);
final coneT3 = new ConeType(t3);
final coneT4 = new ConeType(t4);
final setT12 = new SetType([concreteT1, concreteT2].toSet());
final setT14 = new SetType([concreteT1, concreteT4].toSet());
final setT23 = new SetType([concreteT2, concreteT3].toSet());
final setT34 = new SetType([concreteT3, concreteT4].toSet());
final setT123 = new SetType([concreteT1, concreteT2, concreteT3].toSet());
final setT124 = new SetType([concreteT1, concreteT2, concreteT4].toSet());
final setT1234 =
new SetType([concreteT1, concreteT2, concreteT3, concreteT4].toSet());
final nullableEmpty = new Type.nullable(empty);
final nullableAny = new Type.nullable(any);
final nullableConcreteT1 = new Type.nullable(concreteT1);
final nullableConcreteT2 = new Type.nullable(concreteT2);
final nullableConcreteT3 = new Type.nullable(concreteT3);
final nullableConeT1 = new Type.nullable(coneT1);
final nullableConeT3 = new Type.nullable(coneT3);
final nullableConeT4 = new Type.nullable(coneT4);
final nullableSetT12 = new Type.nullable(setT12);
final nullableSetT14 = new Type.nullable(setT14);
final nullableSetT23 = new Type.nullable(setT23);
final nullableSetT34 = new Type.nullable(setT34);
final nullableSetT123 = new Type.nullable(setT123);
final nullableSetT124 = new Type.nullable(setT124);
final nullableSetT1234 = new Type.nullable(setT1234);
// [A, B, union, intersection]
final testCases = [
// empty
[empty, empty, empty, empty],
[empty, any, any, empty],
[empty, concreteT1, concreteT1, empty],
[empty, coneT1, coneT1, empty],
[empty, setT12, setT12, empty],
[empty, nullableEmpty, nullableEmpty, empty],
[empty, nullableAny, nullableAny, empty],
[empty, nullableConcreteT1, nullableConcreteT1, empty],
[empty, nullableConeT1, nullableConeT1, empty],
[empty, nullableSetT12, nullableSetT12, empty],
// any
[any, any, any, any],
[any, concreteT1, any, concreteT1],
[any, coneT1, any, coneT1],
[any, setT12, any, setT12],
[any, nullableEmpty, nullableAny, empty],
[any, nullableAny, nullableAny, any],
[any, nullableConcreteT1, nullableAny, concreteT1],
[any, nullableConeT1, nullableAny, coneT1],
[any, nullableSetT12, nullableAny, setT12],
// nullableEmpty
[nullableEmpty, concreteT1, nullableConcreteT1, empty],
[nullableEmpty, coneT1, nullableConeT1, empty],
[nullableEmpty, setT12, nullableSetT12, empty],
[nullableEmpty, nullableEmpty, nullableEmpty, nullableEmpty],
[nullableEmpty, nullableAny, nullableAny, nullableEmpty],
[nullableEmpty, nullableConcreteT1, nullableConcreteT1, nullableEmpty],
[nullableEmpty, nullableConeT1, nullableConeT1, nullableEmpty],
[nullableEmpty, nullableSetT12, nullableSetT12, nullableEmpty],
// nullableAny
[nullableAny, concreteT1, nullableAny, concreteT1],
[nullableAny, coneT1, nullableAny, coneT1],
[nullableAny, setT12, nullableAny, setT12],
[nullableAny, nullableAny, nullableAny, nullableAny],
[nullableAny, nullableConcreteT1, nullableAny, nullableConcreteT1],
[nullableAny, nullableConeT1, nullableAny, nullableConeT1],
[nullableAny, nullableSetT12, nullableAny, nullableSetT12],
// concrete
[concreteT1, concreteT1, concreteT1, concreteT1],
[concreteT1, concreteT2, setT12, empty],
[concreteT1, coneT1, coneT1, concreteT1],
[concreteT1, coneT2, setT12, empty],
[concreteT1, coneT3, coneT3, concreteT1],
[concreteT1, coneT4, setT14, empty],
[concreteT1, setT12, setT12, concreteT1],
[concreteT1, setT23, setT123, empty],
[concreteT1, nullableConcreteT1, nullableConcreteT1, concreteT1],
[concreteT1, nullableConcreteT2, nullableSetT12, empty],
[concreteT1, nullableConeT1, nullableConeT1, concreteT1],
[concreteT1, nullableConeT3, nullableConeT3, concreteT1],
[concreteT1, nullableConeT4, nullableSetT14, empty],
[concreteT1, nullableSetT12, nullableSetT12, concreteT1],
[concreteT1, nullableSetT23, nullableSetT123, empty],
// cone
[coneT1, coneT1, coneT1, coneT1],
[coneT1, coneT2, setT12, empty],
[coneT1, coneT3, coneT3, coneT1],
[coneT3, coneT4, setT1234, empty],
[coneT1, setT12, setT12, concreteT1],
[coneT1, setT23, setT123, empty],
[coneT3, setT12, setT123, setT12],
[coneT3, setT1234, setT1234, setT123],
[coneT1, nullableConcreteT1, nullableConeT1, concreteT1],
[coneT1, nullableConcreteT2, nullableSetT12, empty],
[coneT3, nullableConcreteT2, nullableConeT3, concreteT2],
[coneT1, nullableConeT1, nullableConeT1, coneT1],
[coneT1, nullableConeT3, nullableConeT3, coneT1],
[coneT1, nullableConeT4, nullableSetT14, empty],
[coneT1, nullableSetT12, nullableSetT12, concreteT1],
[coneT3, nullableSetT23, nullableSetT123, setT23],
// set
[setT12, setT12, setT12, setT12],
[setT12, setT123, setT123, setT12],
[setT12, setT23, setT123, concreteT2],
[setT12, setT34, setT1234, empty],
[setT12, nullableConcreteT1, nullableSetT12, concreteT1],
[setT12, nullableConcreteT3, nullableSetT123, empty],
[setT12, nullableConeT1, nullableSetT12, concreteT1],
[setT12, nullableConeT3, nullableSetT123, setT12],
[setT12, nullableConeT4, nullableSetT124, empty],
[setT12, nullableSetT12, nullableSetT12, setT12],
[setT12, nullableSetT123, nullableSetT123, setT12],
[setT12, nullableSetT23, nullableSetT123, concreteT2],
[setT12, nullableSetT34, nullableSetT1234, empty],
// nullableConcrete
[
nullableConcreteT1,
nullableConcreteT1,
nullableConcreteT1,
nullableConcreteT1
],
[nullableConcreteT1, nullableConcreteT2, nullableSetT12, nullableEmpty],
[nullableConcreteT1, nullableConeT1, nullableConeT1, nullableConcreteT1],
[nullableConcreteT1, nullableConeT3, nullableConeT3, nullableConcreteT1],
[nullableConcreteT1, nullableConeT4, nullableSetT14, nullableEmpty],
[nullableConcreteT1, nullableSetT12, nullableSetT12, nullableConcreteT1],
[nullableConcreteT1, nullableSetT23, nullableSetT123, nullableEmpty],
// nullableCone
[nullableConeT1, nullableConeT1, nullableConeT1, nullableConeT1],
[nullableConeT1, nullableConeT3, nullableConeT3, nullableConeT1],
[nullableConeT1, nullableConeT4, nullableSetT14, nullableEmpty],
[nullableConeT1, nullableSetT12, nullableSetT12, nullableConcreteT1],
[nullableConeT1, nullableSetT23, nullableSetT123, nullableEmpty],
[nullableConeT3, nullableSetT14, nullableSetT1234, nullableConcreteT1],
// nullableSet
[nullableSetT12, nullableSetT12, nullableSetT12, nullableSetT12],
[nullableSetT12, nullableSetT23, nullableSetT123, nullableConcreteT2],
[nullableSetT12, nullableSetT34, nullableSetT1234, nullableEmpty],
];
final hierarchy = new TestTypeHierarchy(
// subtypes
{
t1: [t1],
t2: [t2],
t3: [t1, t2, t3],
t4: [t4],
},
// specializations
{
t1: concreteT1,
t2: concreteT2,
t3: setT123,
t4: concreteT4
});
for (List testCase in testCases) {
Type a = testCase[0] as Type;
Type b = testCase[1] as Type;
Type union = testCase[2] as Type;
Type intersection = testCase[3] as Type;
expect(a.union(b, hierarchy), equals(union),
reason: "Test case: UNION($a, $b) = $union");
expect(b.union(a, hierarchy), equals(union),
reason: "Test case: UNION($b, $a) = $union");
expect(a.intersection(b, hierarchy), equals(intersection),
reason: "Test case: INTERSECTION($a, $b) = $intersection");
expect(b.intersection(a, hierarchy), equals(intersection),
reason: "Test case: INTERSECTION($b, $a) = $intersection");
}
});
test('hashcode-equals', () {
final c1 = new Class(name: 'C1');
final c2 = new Class(name: 'C2');
final c3 = new Class(name: 'C3');
final t1a = new InterfaceType(c1);
final t1b = new InterfaceType(c1);
final t2 = new InterfaceType(c2);
final t3 = new InterfaceType(c3);
final f1a = new FunctionType([t1a], const VoidType());
final f1b = new FunctionType([t1b], const VoidType());
final f2 = new FunctionType([t1a, t1a], const VoidType());
void eq(dynamic a, dynamic b) {
expect(a == b, isTrue, reason: "Test case: $a == $b");
expect(a.hashCode == b.hashCode, isTrue,
reason: "Test case: ${a}.hashCode == ${b}.hashCode");
}
void ne(dynamic a, dynamic b) {
expect(a == b, isFalse, reason: "Test case: $a != $b");
// Hash codes can be the same, but it is unlikely.
expect(a.hashCode == b.hashCode, isFalse,
reason: "Test case: ${a}.hashCode != ${b}.hashCode");
}
eq(t1a, t1b);
ne(t1a, t2);
eq(f1a, f1b);
ne(f1a, f2);
ne(t1a, f1a);
eq(new EmptyType(), new EmptyType());
ne(new EmptyType(), new AnyType());
ne(new EmptyType(), new ConcreteType(t1a));
ne(new EmptyType(), new ConeType(t1a));
ne(new EmptyType(),
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
ne(new EmptyType(), new NullableType(new EmptyType()));
eq(new AnyType(), new AnyType());
ne(new AnyType(), new ConcreteType(t1a));
ne(new AnyType(), new ConeType(t1a));
ne(new AnyType(),
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
ne(new AnyType(), new NullableType(new EmptyType()));
eq(new ConcreteType(t1a), new ConcreteType(t1b));
eq(new ConcreteType(f1a), new ConcreteType(f1b));
ne(new ConcreteType(t1a), new ConcreteType(t2));
ne(new ConcreteType(f1a), new ConcreteType(f2));
ne(new ConcreteType(t1a), new ConcreteType(f1a));
ne(new ConcreteType(t1a), new ConeType(t1a));
ne(new ConcreteType(t1a), new ConeType(t2));
ne(new ConcreteType(t1a),
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
ne(new ConcreteType(t1a), new NullableType(new ConcreteType(t1a)));
eq(new ConeType(t1a), new ConeType(t1b));
eq(new ConeType(f1a), new ConeType(f1b));
ne(new ConeType(t1a), new ConeType(t2));
ne(new ConeType(f1a), new ConeType(f2));
ne(new ConeType(t1a), new ConeType(f1a));
ne(new ConeType(t1a),
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()));
ne(new ConeType(t1a), new NullableType(new ConeType(t1a)));
eq(new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
new SetType([new ConcreteType(t2), new ConcreteType(t1b)].toSet()));
eq(
new SetType([
new ConcreteType(t1a),
new ConcreteType(t2),
new ConcreteType(t3)
].toSet()),
new SetType([
new ConcreteType(t2),
new ConcreteType(t1b),
new ConcreteType(t3)
].toSet()));
ne(
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
new SetType([
new ConcreteType(t1a),
new ConcreteType(t2),
new ConcreteType(t3)
].toSet()));
ne(new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
new SetType([new ConcreteType(t1a), new ConcreteType(t3)].toSet()));
ne(
new SetType([new ConcreteType(t1a), new ConcreteType(t2)].toSet()),
new NullableType(new SetType(
[new ConcreteType(t1a), new ConcreteType(t2)].toSet())));
});
}

View file

@ -0,0 +1,43 @@
// 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.
abstract class A {
void foo1(Object x) {}
dynamic get foo2;
set foo3(int x);
}
class B {
void bar1(Object arg) {}
dynamic get bar2 => null;
set bar3(int y) {}
int bar4;
}
class C {
interfaceCalls(A aa, Object a2, Object a3, Object a4) {
aa.foo1(new B());
aa.foo3 = aa.foo2;
a4 = aa.foo2(a2, a3, aa.foo1);
return a4;
}
dynamicCalls(dynamic aa, Object a2, Object a3, Object a4) {
aa.foo1(new B());
aa.foo3 = aa.foo2;
a4 = aa.foo2(a2, a3, aa.foo1);
return a4;
}
}
class D extends B {
superCalls(Object a1, Object a2, Object a3, Object a4) {
super.bar1(a1);
super.bar3 = super.bar4;
a4 = super.bar2(a2, a3, super.bar1);
return a4;
}
}
main() {}

View file

@ -0,0 +1,78 @@
------------ #lib::A:: ------------
%this = _Parameter #0 [#lib::A]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::A::foo1 ------------
%this = _Parameter #0 [#lib::A]
%x = _Parameter #1 [dart.core::Object]
RESULT: _T {}?
------------ #lib::B:: ------------
%this = _Parameter #0 [#lib::B]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::B::bar1 ------------
%this = _Parameter #0 [#lib::B]
%arg = _Parameter #1 [dart.core::Object]
RESULT: _T {}?
------------ #lib::B::bar2 ------------
%this = _Parameter #0 [#lib::B]
RESULT: _T {}?
------------ #lib::B::bar3 ------------
%this = _Parameter #0 [#lib::B]
%y = _Parameter #1 [dart.core::int]
RESULT: _T {}?
------------ #lib::B::bar4 ------------
RESULT: _T {}?
------------ #lib::C:: ------------
%this = _Parameter #0 [#lib::C]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::C::interfaceCalls ------------
%this = _Parameter #0 [#lib::C]
%aa = _Parameter #1 [#lib::A]
%a2 = _Parameter #2 [dart.core::Object]
%a3 = _Parameter #3 [dart.core::Object]
%a4 = _Parameter #4 [dart.core::Object]
t5 = _Call direct [#lib::B::] (_T (#lib::B))
t6 = _Call [#lib::A::foo1] (%aa, _T (#lib::B))
t7* = _Call get [#lib::A::foo2] (%aa)
t8 = _Narrow (t7 to _T (dart.core::int)+?)
t9 = _Call set [#lib::A::foo3] (%aa, t8)
t10 = _Call get [#lib::A::foo2] (%aa)
a4 = _Join [dart.core::Object] (%a4, _T ANY?)
RESULT: a4
------------ #lib::C::dynamicCalls ------------
%this = _Parameter #0 [#lib::C]
%aa = _Parameter #1 [dynamic]
%a2 = _Parameter #2 [dart.core::Object]
%a3 = _Parameter #3 [dart.core::Object]
%a4 = _Parameter #4 [dart.core::Object]
t5 = _Call direct [#lib::B::] (_T (#lib::B))
t6 = _Call dynamic [foo1] (%aa, _T (#lib::B))
t7* = _Call dynamic get [foo2] (%aa)
t8 = _Call dynamic set [foo3] (%aa, t7)
t9* = _Call dynamic get [foo1] (%aa)
t10* = _Call dynamic [foo2] (%aa, %a2, %a3, t9)
a4 = _Join [dart.core::Object] (%a4, t10)
RESULT: a4
------------ #lib::D:: ------------
%this = _Parameter #0 [#lib::D]
t1 = _Call direct [#lib::B::] (%this)
RESULT: _T {}?
------------ #lib::D::superCalls ------------
%this = _Parameter #0 [#lib::D]
%a1 = _Parameter #1 [dart.core::Object]
%a2 = _Parameter #2 [dart.core::Object]
%a3 = _Parameter #3 [dart.core::Object]
%a4 = _Parameter #4 [dart.core::Object]
t5 = _Call direct [#lib::B::bar1] (%this, %a1)
t6* = _Call direct get [#lib::B::bar4] (%this)
t7 = _Call direct set [#lib::B::bar3] (%this, t6)
t8* = _Call direct get [#lib::B::bar2] (%this)
t9* = _Call dynamic [call] (t8, %a2, %a3, _T ANY?)
a4 = _Join [dart.core::Object] (%a4, t9)
RESULT: a4
------------ #lib::main ------------
RESULT: _T {}?

View file

@ -0,0 +1,7 @@
// 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.
main(List<String> args) {
print('Hello, world!');
}

View file

@ -0,0 +1,4 @@
------------ #lib::main ------------
%args = _Parameter #0 [dart.core::List<dart.core::String>]
t1 = _Call direct [dart.core::print] (_T (dart.core::String)+)
RESULT: _T {}?

View file

@ -0,0 +1,43 @@
// 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.
bool someStatic;
class A {}
class B {}
Object foo(Object a1, [Object a2]) {
if (someStatic) {
a1 = new A();
}
bar(a1, 42);
a1 = new B();
return (a1 != a2) ? a1 : a2;
}
int bar(Object a1, int a2) {
Object v1 = a1;
if (v1 is int) {
int v2 = v1 + a2;
return v2 * 3;
}
return -1;
}
Object loop1(Object a1, Object a2) {
Object x = a1;
x = loop1(x, a1);
x = a2;
return x;
}
int loop2(int x) {
for (int i = 0; i < 5; i++) {
x = x + 10;
}
return x;
}
main() {}

View file

@ -0,0 +1,50 @@
------------ #lib::A:: ------------
%this = _Parameter #0 [#lib::A]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::B:: ------------
%this = _Parameter #0 [#lib::B]
t1 = _Call direct [dart.core::Object::] (%this)
RESULT: _T {}?
------------ #lib::foo ------------
%a1 = _Parameter #0 [dart.core::Object]
%a2 = _Parameter #1 [dart.core::Object]
t2 = _Call direct get [#lib::someStatic] ()
t3 = _Call direct [#lib::A::] (_T (#lib::A))
a1 = _Join [dart.core::Object] (%a1, _T (#lib::A), _T (#lib::B))
t5 = _Call direct [#lib::bar] (a1, _T (dart.core::int)+)
t6 = _Call direct [#lib::B::] (_T (#lib::B))
a2 = _Join [dart.core::Object] (_T {}?, %a2)
t8 = _Call [dart.core::Object::==] (a1, a2)
t9 = _Join [dart.core::Object] (a1, a2)
t10 = _Narrow (t9 to _T (dart.core::Object)+?)
RESULT: t10
------------ #lib::bar ------------
%a1 = _Parameter #0 [dart.core::Object]
%a2 = _Parameter #1 [dart.core::int]
t2 = _Narrow (%a1 to _T (dart.core::int)+)
t3* = _Call [dart.core::num::+] (t2, %a2)
t4* = _Call [dart.core::num::*] (t3, _T (dart.core::int)+)
t5* = _Call [dart.core::int::unary-] (_T (dart.core::int)+)
%result = _Join [dart.core::int] (t4, t5)
RESULT: %result
------------ #lib::loop1 ------------
%a1 = _Parameter #0 [dart.core::Object]
%a2 = _Parameter #1 [dart.core::Object]
t2* = _Call direct [#lib::loop1] (_T (dart.core::Object)+?, %a1)
x = _Join [dart.core::Object] (%a1, t2, %a2)
RESULT: x
------------ #lib::loop2 ------------
%x = _Parameter #0 [dart.core::int]
t1* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
i = _Join [dart.core::int] (_T (dart.core::int)+, t1)
t3 = _Call [dart.core::num::<] (i, _T (dart.core::int)+)
t4* = _Call [dart.core::num::+] (_T (dart.core::int)+?, _T (dart.core::int)+)
x = _Join [dart.core::int] (%x, t4)
RESULT: x
------------ #lib::main ------------
RESULT: _T {}?
------------ #lib::someStatic ------------
RESULT: _T {}?

View file

@ -0,0 +1,44 @@
import 'dart:typed_data';
class _Vector {
_Vector(int size)
: _offset = 0,
_length = size,
_elements = new Float64List(size);
_Vector.fromVOL(List<double> values, int offset, int length)
: _offset = offset,
_length = length,
_elements = values;
final int _offset;
final int _length;
final List<double> _elements;
double operator [](int i) => _elements[i + _offset];
void operator []=(int i, double value) {
_elements[i + _offset] = value;
}
double operator *(_Vector a) {
double result = 0.0;
for (int i = 0; i < _length; i += 1) result += this[i] * a[i];
return result;
}
}
_Vector v = new _Vector(10);
double x = 0.0;
main(List<String> args) {
Stopwatch timer = new Stopwatch()..start();
for (int i = 0; i < 100000000; i++) {
x = x + v * v;
}
timer.stop();
print("Elapsed ${timer.elapsedMilliseconds}ms, result $x");
}

View file

@ -0,0 +1,37 @@
library #lib;
import self as self;
import "dart:core" as core;
import "dart:typed_data" as typ;
class _Vector extends core::Object {
final field core::int _offset;
final field core::int _length;
final field core::List<core::double> _elements;
constructor •(core::int size) → void
: self::_Vector::_offset = 0, self::_Vector::_length = size, self::_Vector::_elements = [@vm.inferred-type.metadata=dart.typed_data::_Float64List] typ::Float64List::•(size), super core::Object::•()
;
constructor fromVOL(core::List<core::double> values, core::int offset, core::int length) → void
: self::_Vector::_offset = offset, self::_Vector::_length = length, self::_Vector::_elements = values, super core::Object::•()
throw "TFA Error: #lib::_Vector::fromVOL";
operator [](core::int i) → core::double
return [@vm.direct-call.metadata=dart.typed_data::_Float64List::[]] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::_elements??] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]}(i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset??] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}));
operator []=(core::int i, core::double value) → void {
[@vm.direct-call.metadata=#lib::_Vector::_elements??] [@vm.inferred-type.metadata=dart.typed_data::_Float64List] this.{self::_Vector::_elements}.{core::List::[]=}([@vm.inferred-type.metadata=!] i.{core::num::+}([@vm.direct-call.metadata=#lib::_Vector::_offset??] [@vm.inferred-type.metadata=!] this.{self::_Vector::_offset}), value);
}
operator *(self::_Vector a) → core::double {
core::double result = 0.0;
for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}([@vm.direct-call.metadata=#lib::_Vector::_length] [@vm.inferred-type.metadata=!] this.{self::_Vector::_length}); i = i.{core::num::+}(1))
result = [@vm.direct-call.metadata=dart.core::_Double::+??] [@vm.inferred-type.metadata=dart.core::_Double] result.{core::double::+}([@vm.direct-call.metadata=dart.core::_Double::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] this.{self::_Vector::[]}(i).{core::double::*}([@vm.direct-call.metadata=#lib::_Vector::[]] [@vm.inferred-type.metadata=dart.core::_Double] a.{self::_Vector::[]}(i)));
return result;
}
}
static field self::_Vector v = new self::_Vector::•(10);
static field core::double x = 0.0;
static method main(core::List<core::String> args) → dynamic {
core::Stopwatch timer = let final core::Stopwatch #t1 = new core::Stopwatch::•() in let final dynamic #t2 = [@vm.direct-call.metadata=dart.core::Stopwatch::start] #t1.{core::Stopwatch::start}() in #t1;
for (core::int i = 0; [@vm.direct-call.metadata=dart.core::_IntegerImplementation::<??] i.{core::num::<}(100000000); i = i.{core::num::+}(1)) {
self::x = [@vm.direct-call.metadata=dart.core::_Double::+] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=dart.core::_Double] self::x.{core::double::+}([@vm.direct-call.metadata=#lib::_Vector::*] [@vm.inferred-type.metadata=dart.core::_Double] [@vm.inferred-type.metadata=#lib::_Vector] self::v.{self::_Vector::*}([@vm.inferred-type.metadata=#lib::_Vector] self::v));
}
[@vm.direct-call.metadata=dart.core::Stopwatch::stop] timer.{core::Stopwatch::stop}();
core::print("Elapsed ${[@vm.direct-call.metadata=dart.core::Stopwatch::elapsedMilliseconds] timer.{core::Stopwatch::elapsedMilliseconds}}ms, result ${self::x}");
}

View file

@ -0,0 +1,60 @@
// 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.
abstract class A {
int foo();
}
class B extends A {
int foo() => 1;
}
class C implements A {
int foo() => 2;
}
class D extends C {}
class E {
String toString() => 'D';
}
void callerA1(A aa) {
aa.foo();
}
void callerA2(A aa) {
aa.foo();
}
void callerA3(A aa) {
aa.foo();
}
void callerA4(A aa) {
aa.foo();
}
void callerE1(x) {
x.toString();
}
void callerE2(x) {
x.toString();
}
A dd;
E ee = new E();
main(List<String> args) {
callerA1(new B());
callerA1(new C());
callerA2(new B());
callerA3(new C());
callerA4(dd);
dd = new D();
callerE1('abc');
callerE2(ee);
}

View file

@ -0,0 +1,66 @@
library #lib;
import self as self;
import "dart:core" as core;
abstract class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
abstract method foo() → core::int;
}
class B extends self::A {
default constructor •() → void
: super self::A::•()
;
method foo() → core::int
return 1;
}
class C extends core::Object implements self::A {
default constructor •() → void
: super core::Object::•()
;
method foo() → core::int
return 2;
}
class D extends self::C {
default constructor •() → void
: super self::C::•()
;
}
class E extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method toString() → core::String
return "D";
}
static field self::A dd;
static field self::E ee = new self::E::•();
static method callerA1(self::A aa) → void {
aa.{self::A::foo}();
}
static method callerA2(self::A aa) → void {
[@vm.direct-call.metadata=#lib::B::foo] aa.{self::A::foo}();
}
static method callerA3(self::A aa) → void {
[@vm.direct-call.metadata=#lib::C::foo] aa.{self::A::foo}();
}
static method callerA4(self::A aa) → void {
[@vm.direct-call.metadata=#lib::C::foo??] aa.{self::A::foo}();
}
static method callerE1(dynamic x) → void {
[@vm.direct-call.metadata=dart.core::_StringBase::toString] x.{core::Object::toString}();
}
static method callerE2(dynamic x) → void {
[@vm.direct-call.metadata=#lib::E::toString] x.{core::Object::toString}();
}
static method main(core::List<core::String> args) → dynamic {
self::callerA1(new self::B::•());
self::callerA1(new self::C::•());
self::callerA2(new self::B::•());
self::callerA3(new self::C::•());
self::callerA4([@vm.inferred-type.metadata=#lib::D?] self::dd);
self::dd = new self::D::•();
self::callerE1("abc");
self::callerE2([@vm.inferred-type.metadata=#lib::E] self::ee);
}

View file

@ -0,0 +1,11 @@
// 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.
class A {}
Object foo() => new A();
main(List<String> args) {
print(foo());
}

View file

@ -0,0 +1,14 @@
library #lib;
import self as self;
import "dart:core" as core;
class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
static method foo() → core::Object
return new self::A::•();
static method main(core::List<core::String> args) → dynamic {
core::print([@vm.inferred-type.metadata=#lib::A] self::foo());
}

View file

@ -0,0 +1,42 @@
// 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.
class T1 {}
class T2 {}
abstract class A {
foo();
}
class B extends A {
foo() => new T1();
}
class C implements B {
foo() => new T2();
}
class Intermediate {
bar(A aa) => aa.foo();
}
use1(Intermediate i, A aa) => i.bar(aa);
use2(Intermediate i, A aa) => i.bar(aa);
Function unknown;
getDynamic() => unknown.call();
allocateB() {
new B();
}
main(List<String> args) {
use1(new Intermediate(), getDynamic()); // No subclasses of A allocated.
allocateB();
use2(new Intermediate(), getDynamic()); // Now B is allocated.
}

View file

@ -0,0 +1,56 @@
library #lib;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
class T2 extends core::Object {
default constructor •() → void
: super core::Object::•()
throw "TFA Error: #lib::T2::";
}
abstract class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
abstract method foo() → dynamic;
}
class B extends self::A {
default constructor •() → void
: super self::A::•()
;
method foo() → dynamic
return new self::T1::•();
}
class C extends core::Object implements self::B {
default constructor •() → void
: super core::Object::•()
throw "TFA Error: #lib::C::";
method foo() → dynamic
throw "TFA Error: #lib::C::foo";
}
class Intermediate extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method bar(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::B::foo??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::foo}();
}
static field core::Function unknown;
static method use1(self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
static method use2(self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=#lib::T1] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
static method main(core::List<core::String> args) → dynamic {
self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
self::allocateB();
self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
}

View file

@ -0,0 +1,55 @@
// 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.
class T1 {}
class T2 {}
abstract class A {
foo();
}
class B extends A {
foo() => new T1();
}
abstract class C implements B {}
class D {}
class E extends D with C {
foo() => new T2();
}
class Intermediate {
bar(A aa) => aa.foo();
}
use1(Intermediate i, A aa) => i.bar(aa);
use2(Intermediate i, A aa) => i.bar(aa);
use3(Intermediate i, A aa) => i.bar(aa);
Function unknown;
getDynamic() => unknown.call();
allocateB() {
new B();
}
allocateE() {
new E();
}
main(List<String> args) {
use1(new Intermediate(), getDynamic()); // No subclasses of A allocated.
allocateB();
use2(new Intermediate(), getDynamic()); // Now B is allocated.
allocateE();
use3(new Intermediate(), getDynamic()); // Now E is also allocated.
}

View file

@ -0,0 +1,78 @@
library #lib;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
class T2 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
abstract class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
abstract method foo() → dynamic;
}
class B extends self::A {
default constructor •() → void
: super self::A::•()
;
method foo() → dynamic
return new self::T1::•();
}
abstract class C extends core::Object implements self::B {
default constructor •() → void
: super core::Object::•()
throw "TFA Error: #lib::C::";
}
class D extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
abstract class _D&C extends self::D implements self::C {
constructor •() → void
: super self::D::•()
;
}
class E extends self::_D&C {
default constructor •() → void
: super self::D::•()
;
method foo() → dynamic
return new self::T2::•();
}
class Intermediate extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method bar(self::A aa) → dynamic
return [@vm.inferred-type.metadata=!] aa.{self::A::foo}();
}
static field core::Function unknown;
static method use1(self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
static method use2(self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
static method use3(self::Intermediate i, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::Intermediate::bar] [@vm.inferred-type.metadata=!] i.{self::Intermediate::bar}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
static method allocateB() → dynamic {
new self::B::•();
}
static method allocateE() → dynamic {
new self::E::•();
}
static method main(core::List<core::String> args) → dynamic {
self::use1(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
self::allocateB();
self::use2(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
self::allocateE();
self::use3(new self::Intermediate::•(), self::getDynamic() as{TypeError} self::A);
}

View file

@ -0,0 +1,50 @@
// 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.
class T1 {}
class T2 {}
class A {
dynamic field1 = new T1();
dynamic field2 = new T1();
}
// Methods of this class should have inferred type = T1.
class DeepCaller1 {
barL1(A aa) => barL2(aa);
barL2(A aa) => barL3(aa);
barL3(A aa) => barL4(aa);
barL4(A aa) => aa.field1;
}
// Methods of this class should have inferred type = T1 | T2.
class DeepCaller2 {
barL1(A aa) => barL2(aa);
barL2(A aa) => barL3(aa);
barL3(A aa) => barL4(aa);
barL4(A aa) => aa.field2;
}
use1(DeepCaller1 x, A aa) => x.barL1(aa);
use2(DeepCaller2 x, A aa) => x.barL1(aa);
Function unknown;
getDynamic() => unknown.call();
void setField2(A aa, dynamic value) {
aa.field2 = value;
}
main(List<String> args) {
new A();
new T1();
new T2();
use1(new DeepCaller1(), getDynamic());
use2(new DeepCaller2(), getDynamic());
setField2(new A(), new T2());
}

View file

@ -0,0 +1,65 @@
library #lib;
import self as self;
import "dart:core" as core;
class T1 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
class T2 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
}
class A extends core::Object {
field dynamic field1 = new self::T1::•();
field dynamic field2 = new self::T1::•();
default constructor •() → void
: super core::Object::•()
;
}
class DeepCaller1 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method barL1(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller1::barL2] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL2}(aa);
method barL2(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller1::barL3] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL3}(aa);
method barL3(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller1::barL4] [@vm.inferred-type.metadata=#lib::T1] this.{self::DeepCaller1::barL4}(aa);
method barL4(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::A::field1??] [@vm.inferred-type.metadata=#lib::T1] aa.{self::A::field1};
}
class DeepCaller2 extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method barL1(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL2] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL2}(aa);
method barL2(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL3] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL3}(aa);
method barL3(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL4] [@vm.inferred-type.metadata=!] this.{self::DeepCaller2::barL4}(aa);
method barL4(self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::A::field2??] [@vm.inferred-type.metadata=!] aa.{self::A::field2};
}
static field core::Function unknown;
static method use1(self::DeepCaller1 x, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller1::barL1] [@vm.inferred-type.metadata=#lib::T1] x.{self::DeepCaller1::barL1}(aa);
static method use2(self::DeepCaller2 x, self::A aa) → dynamic
return [@vm.direct-call.metadata=#lib::DeepCaller2::barL1] [@vm.inferred-type.metadata=!] x.{self::DeepCaller2::barL1}(aa);
static method getDynamic() → dynamic
return self::unknown.call();
static method setField2(self::A aa, dynamic value) → void {
[@vm.direct-call.metadata=#lib::A::field2] aa.{self::A::field2} = value;
}
static method main(core::List<core::String> args) → dynamic {
new self::A::•();
new self::T1::•();
new self::T2::•();
self::use1(new self::DeepCaller1::•(), self::getDynamic() as{TypeError} self::A);
self::use2(new self::DeepCaller2::•(), self::getDynamic() as{TypeError} self::A);
self::setField2(new self::A::•(), new self::T2::•());
}

View file

@ -0,0 +1,28 @@
// 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.
A aa = new B();
dynamic knownResult() => new B();
abstract class A {
int foo();
}
class B extends A {
int foo() => 1 + knownResult().foo(); // Should have metadata.
}
class C implements A {
int foo() => 2 + knownResult().foo(); // Should be unreachable.
}
class TearOffInterfaceMethod {
dynamic bazz;
TearOffInterfaceMethod(A arg) : bazz = arg.foo;
}
main(List<String> args) {
new TearOffInterfaceMethod(new B()).bazz();
}

View file

@ -0,0 +1,36 @@
library #lib;
import self as self;
import "dart:core" as core;
abstract class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
abstract method foo() → core::int;
}
class B extends self::A {
default constructor •() → void
: super self::A::•()
;
method foo() → core::int
return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
}
class C extends core::Object implements self::A {
default constructor •() → void
: super core::Object::•()
throw "TFA Error: #lib::C::";
method foo() → core::int
throw "TFA Error: #lib::C::foo";
}
class TearOffInterfaceMethod extends core::Object {
field dynamic bazz;
constructor •(self::A arg) → void
: self::TearOffInterfaceMethod::bazz = arg.{self::A::foo}, super core::Object::•()
;
}
static field self::A aa = throw "TFA Error: #lib::aa";
static method knownResult() → dynamic
return new self::B::•();
static method main(core::List<core::String> args) → dynamic {
new self::TearOffInterfaceMethod::•(new self::B::•()).{self::TearOffInterfaceMethod::bazz}();
}

View file

@ -0,0 +1,40 @@
// 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.
A aa = new B();
dynamic knownResult() => new B();
abstract class A {
int foo();
}
class B extends A {
int foo() => 1 + knownResult().foo(); // Should have metadata.
}
class C implements A {
int foo() => 2 + knownResult().foo(); // Should be unreachable.
}
class Base {
int foo() => 3 + knownResult().foo(); // Should have metadata.
int doCall(x) => x();
}
class TearOffSuperMethod extends Base {
int foo() {
// Should be unreachable.
aa = new C();
return 4 + knownResult().foo();
}
int bar() => doCall(super.foo);
}
main(List<String> args) {
new TearOffSuperMethod().bar();
aa.foo(); // Should be devirtualized.
}

View file

@ -0,0 +1,49 @@
library #lib;
import self as self;
import "dart:core" as core;
abstract class A extends core::Object {
default constructor •() → void
: super core::Object::•()
;
abstract method foo() → core::int;
}
class B extends self::A {
default constructor •() → void
: super self::A::•()
;
method foo() → core::int
return 1.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
}
class C extends core::Object implements self::A {
default constructor •() → void
: super core::Object::•()
throw "TFA Error: #lib::C::";
method foo() → core::int
throw "TFA Error: #lib::C::foo";
}
class Base extends core::Object {
default constructor •() → void
: super core::Object::•()
;
method foo() → core::int
return 3.{core::num::+}([@vm.inferred-type.metadata=#lib::B] self::knownResult().foo() as{TypeError} core::num) as{TypeError} core::int;
method doCall(dynamic x) → core::int
return x.call() as{TypeError} core::int;
}
class TearOffSuperMethod extends self::Base {
default constructor •() → void
: super self::Base::•()
;
method foo() → core::int
throw "TFA Error: #lib::TearOffSuperMethod::foo";
method bar() → core::int
return [@vm.direct-call.metadata=#lib::Base::doCall] this.{self::Base::doCall}(super.{self::Base::foo});
}
static field self::A aa = new self::B::•();
static method knownResult() → dynamic
return new self::B::•();
static method main(core::List<core::String> args) → dynamic {
[@vm.direct-call.metadata=#lib::TearOffSuperMethod::bar] new self::TearOffSuperMethod::•().{self::TearOffSuperMethod::bar}();
[@vm.direct-call.metadata=#lib::B::foo] [@vm.inferred-type.metadata=#lib::B] self::aa.{self::A::foo}();
}