mirror of
https://github.com/dart-lang/sdk
synced 2024-09-15 21:30:17 +00:00
[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:
parent
bc22c3e050
commit
bcdb32bc1a
|
@ -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
|
||||
|
|
|
@ -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).
|
||||
|
|
|
@ -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);
|
||||
|
|
42
pkg/vm/test/transformations/type_flow/common_test_utils.dart
Normal file
42
pkg/vm/test/transformations/type_flow/common_test_utils.dart
Normal 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");
|
||||
}
|
||||
}
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
53
pkg/vm/test/transformations/type_flow/transformer_test.dart
Normal file
53
pkg/vm/test/transformations/type_flow/transformer_test.dart
Normal 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));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
383
pkg/vm/test/transformations/type_flow/types_test.dart
Normal file
383
pkg/vm/test/transformations/type_flow/types_test.dart
Normal 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())));
|
||||
});
|
||||
}
|
|
@ -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() {}
|
|
@ -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 {}?
|
|
@ -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!');
|
||||
}
|
|
@ -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 {}?
|
|
@ -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() {}
|
|
@ -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 {}?
|
|
@ -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");
|
||||
}
|
|
@ -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}");
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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());
|
||||
}
|
|
@ -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::•());
|
||||
}
|
|
@ -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();
|
||||
}
|
|
@ -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}();
|
||||
}
|
|
@ -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.
|
||||
}
|
|
@ -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}();
|
||||
}
|
Loading…
Reference in a new issue