20faaa5d94
Change-Id: Ib18f554c1076f27a3f7c0df5a36410da41a1f467 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148784 Reviewed-by: Paul Berry <paulberry@google.com> Reviewed-by: Sigmund Cherem <sigmund@google.com>
215 lines
5.5 KiB
Dart
215 lines
5.5 KiB
Dart
// Copyright (c) 2017, 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.
|
|
|
|
// @dart = 2.7
|
|
|
|
import 'package:async_helper/async_helper.dart';
|
|
import 'package:compiler/src/commandline_options.dart';
|
|
import 'package:compiler/src/common_elements.dart';
|
|
import 'package:compiler/src/compiler.dart';
|
|
import 'package:compiler/src/elements/entities.dart';
|
|
import 'package:compiler/src/js/js.dart' as js;
|
|
import 'package:compiler/src/js_model/js_strategy.dart';
|
|
import 'package:compiler/src/world.dart';
|
|
import 'package:expect/expect.dart';
|
|
import '../helpers/d8_helper.dart';
|
|
import '../helpers/memory_compiler.dart';
|
|
|
|
const String SOURCE = r'''
|
|
@pragma('dart2js:noInline')
|
|
method1<T>(T t) {
|
|
print('method1:');
|
|
print('$t is $T = ${t is T}');
|
|
print('"foo" is $T = ${"foo" is T}');
|
|
print('');
|
|
}
|
|
|
|
@pragma('dart2js:noInline')
|
|
method2<T, S>(S s, T t) {
|
|
print('method2:');
|
|
print('$t is $T = ${t is T}');
|
|
print('$s is $T = ${s is T}');
|
|
print('$t is $S = ${t is S}');
|
|
print('$s is $S = ${s is S}');
|
|
print('');
|
|
}
|
|
|
|
@pragma('dart2js:tryInline')
|
|
method3<T, S>(T t, S s) {
|
|
print('method3:');
|
|
print('$t is $T = ${t is T}');
|
|
print('$s is $T = ${s is T}');
|
|
print('$t is $S = ${t is S}');
|
|
print('$s is $S = ${s is S}');
|
|
print('');
|
|
}
|
|
|
|
class Class1<T> {
|
|
final int index;
|
|
|
|
Class1(this.index);
|
|
|
|
String toString() => 'c$index';
|
|
}
|
|
|
|
method4<T>(int index) => new Class1<T>(index);
|
|
|
|
testMethod4() {
|
|
print('method4:');
|
|
var c1 = method4<int>(1);
|
|
var c2 = method4<String>(2);
|
|
print('$c1 is Class1<int> = ${c1 is Class1<int>}');
|
|
print('$c2 is Class1<int> = ${c2 is Class1<int>}');
|
|
print('$c1 is Class1<String> = ${c1 is Class1<String>}');
|
|
print('$c2 is Class1<String> = ${c2 is Class1<String>}');
|
|
print('');
|
|
}
|
|
|
|
class Class2 {
|
|
@pragma('dart2js:tryInline')
|
|
method5<T>(T t) {
|
|
print('Class2.method5:');
|
|
print('$t is $T = ${t is T}');
|
|
print('"foo" is $T = ${"foo" is T}');
|
|
print('');
|
|
}
|
|
|
|
@pragma('dart2js:noInline')
|
|
method6(o) {
|
|
print('Class2.method6:');
|
|
print('$o is int = ${o is int}');
|
|
print('$o is String = ${o is String}');
|
|
print('');
|
|
}
|
|
}
|
|
|
|
class Class3 {
|
|
@pragma('dart2js:noInline')
|
|
method6<T>(T t) {
|
|
print('Class3.method6:');
|
|
print('$t is $T = ${t is T}');
|
|
print('"foo" is $T = ${"foo" is T}');
|
|
print('');
|
|
}
|
|
}
|
|
|
|
class Class4<T> {
|
|
Function method7<Q>() {
|
|
foo(T t, Q q) => '';
|
|
return foo;
|
|
}
|
|
}
|
|
|
|
// Nested generic local function.
|
|
outside<T>() {
|
|
nested<T>(T t) => '';
|
|
return nested;
|
|
}
|
|
|
|
main(args) {
|
|
method1<int>(0);
|
|
method2<String, double>(0.5, 'foo');
|
|
method3<double, String>(1.5, 'bar');
|
|
testMethod4();
|
|
new Class2().method5<int>(0);
|
|
new Class3().method6<int>(0);
|
|
dynamic c3 = args != null ? new Class3() : new Class2();
|
|
c3.method6(0); // Missing type arguments.
|
|
try {
|
|
dynamic c2 = args == null ? new Class3() : new Class2();
|
|
c2.method6(0); // Valid call.
|
|
c2.method6<int>(0); // Extra type arguments.
|
|
} catch (e) {
|
|
print('noSuchMethod: Class2.method6<int>');
|
|
print('');
|
|
}
|
|
var c = new Class4<bool>();
|
|
print((c.method7<int>()).runtimeType);
|
|
outside();
|
|
}
|
|
''';
|
|
|
|
const String OUTPUT = r'''
|
|
method1:
|
|
0 is int = true
|
|
"foo" is int = false
|
|
|
|
method2:
|
|
foo is String = true
|
|
0.5 is String = false
|
|
foo is double = false
|
|
0.5 is double = true
|
|
|
|
method3:
|
|
1.5 is double = true
|
|
bar is double = false
|
|
1.5 is String = false
|
|
bar is String = true
|
|
|
|
method4:
|
|
c1 is Class1<int> = true
|
|
c2 is Class1<int> = false
|
|
c1 is Class1<String> = false
|
|
c2 is Class1<String> = true
|
|
|
|
Class2.method5:
|
|
0 is int = true
|
|
"foo" is int = false
|
|
|
|
Class3.method6:
|
|
0 is int = true
|
|
"foo" is int = false
|
|
|
|
Class3.method6:
|
|
0 is dynamic = true
|
|
"foo" is dynamic = true
|
|
|
|
Class2.method6:
|
|
0 is int = true
|
|
0 is String = false
|
|
|
|
noSuchMethod: Class2.method6<int>
|
|
|
|
(bool, int) => String
|
|
''';
|
|
|
|
main(List<String> args) {
|
|
asyncTest(() async {
|
|
D8Result result = await runWithD8(memorySourceFiles: {
|
|
'main.dart': SOURCE
|
|
}, options: [
|
|
Flags.disableRtiOptimization,
|
|
'--libraries-spec=$sdkLibrariesSpecificationUri',
|
|
], expectedOutput: OUTPUT, printJs: args.contains('-v'));
|
|
Compiler compiler = result.compilationResult.compiler;
|
|
JsBackendStrategy backendStrategy = compiler.backendStrategy;
|
|
JClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
|
|
ElementEnvironment elementEnvironment = closedWorld.elementEnvironment;
|
|
|
|
void checkMethod(String methodName,
|
|
{String className, int expectedParameterCount}) {
|
|
FunctionEntity method;
|
|
if (className != null) {
|
|
ClassEntity cls = elementEnvironment.lookupClass(
|
|
elementEnvironment.mainLibrary, className);
|
|
Expect.isNotNull(cls, "Class '$className' not found.");
|
|
method = elementEnvironment.lookupClassMember(cls, methodName);
|
|
Expect.isNotNull(method, "Method '$methodName' not found in $cls.");
|
|
} else {
|
|
method = elementEnvironment.lookupLibraryMember(
|
|
elementEnvironment.mainLibrary, methodName);
|
|
Expect.isNotNull(method, "Method '$methodName' not found.");
|
|
}
|
|
js.Fun fun = backendStrategy.generatedCode[method];
|
|
Expect.equals(expectedParameterCount, fun.params.length,
|
|
"Unexpected parameter count for $method:\n${js.nodeToString(fun)}");
|
|
}
|
|
|
|
checkMethod('method1', expectedParameterCount: 2);
|
|
checkMethod('method2', expectedParameterCount: 4);
|
|
checkMethod('method6', className: 'Class2', expectedParameterCount: 1);
|
|
checkMethod('method6', className: 'Class3', expectedParameterCount: 2);
|
|
});
|
|
}
|