Remove implicit 'implements Function' for strong mode
Change-Id: Ie3e3e11a727f7fbe3c8d7af17c84dedfbdfcdf3a
Reviewed-on: https://dart-review.googlesource.com/44422
Reviewed-by: Sigmund Cherem <sigmund@google.com>
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index ddb3abb..b54f422 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -485,6 +485,11 @@
void _ensureCallType(IndexedClass cls, ClassData data) {
if (!data.isCallTypeComputed) {
data.isCallTypeComputed = true;
+ if (options.strongMode && !cls.isClosure) {
+ // In Dart 2, a regular class with a 'call' method is no longer a
+ // subtype of its function type.
+ return;
+ }
MemberEntity callMethod = lookupClassMember(cls, Identifiers.call);
if (callMethod != null) {
if (callMethod.isFunction) {
diff --git a/tests/compiler/dart2js/class_set_test.dart b/tests/compiler/dart2js/class_set_test.dart
index 6f446e6..cf71cf5 100644
--- a/tests/compiler/dart2js/class_set_test.dart
+++ b/tests/compiler/dart2js/class_set_test.dart
@@ -9,6 +9,7 @@
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'type_test_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/entities.dart' show ClassEntity;
import 'package:compiler/src/universe/class_set.dart';
import 'package:compiler/src/util/enumset.dart';
@@ -21,13 +22,15 @@
await testAll(CompileMode.memory);
print('--test from kernel------------------------------------------------');
await testAll(CompileMode.kernel);
+ print('--test from kernel (strong)---------------------------------------');
+ await testAll(CompileMode.kernel, strongMode: true);
});
}
-testAll(CompileMode compileMode) async {
+testAll(CompileMode compileMode, {bool strongMode: false}) async {
await testIterators(compileMode);
await testForEach(compileMode);
- await testClosures(compileMode);
+ await testClosures(compileMode, strongMode);
}
testIterators(CompileMode compileMode) async {
@@ -587,30 +590,37 @@
find: I, anySubtype: true, expectedResult: true);
}
-testClosures(CompileMode compileMode) async {
+testClosures(CompileMode compileMode, bool strongMode) async {
var env = await TypeEnvironment.create(r"""
class A {
call() => null;
}
- """, mainSource: r"""
+ """,
+ mainSource: r"""
main() {
new A();
() {};
local() {}
}
- """, compileMode: compileMode, testBackendWorld: true);
+ """,
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [],
+ testBackendWorld: true);
ClosedWorld world = env.closedWorld;
ClassEntity functionClass = world.commonElements.functionClass;
ClassEntity closureClass = world.commonElements.closureClass;
ClassEntity A = env.getClass("A");
- checkIsFunction(ClassEntity cls) {
- Expect.isTrue(world.isSubtypeOf(cls, functionClass),
- "Expected $cls to be a subtype of $functionClass.");
+ checkIsFunction(ClassEntity cls, {bool expected: true}) {
+ Expect.equals(
+ expected,
+ world.isSubtypeOf(cls, functionClass),
+ "Expected $cls ${expected ? '' : 'not '}to be a subtype "
+ "of $functionClass.");
}
- checkIsFunction(A);
+ checkIsFunction(A, expected: !strongMode);
world.forEachStrictSubtypeOf(closureClass, checkIsFunction);
}
diff --git a/tests/compiler/dart2js/rti/emission/call_strong.dart b/tests/compiler/dart2js/rti/emission/call_strong.dart
new file mode 100644
index 0000000..51f2ee76
--- /dev/null
+++ b/tests/compiler/dart2js/rti/emission/call_strong.dart
@@ -0,0 +1,19 @@
+// 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 'package:expect/expect.dart';
+import 'package:meta/dart2js.dart';
+
+/*class: A:checks=[],instance*/
+class A {
+ call() {}
+}
+
+@noInline
+test(o) => o is Function;
+
+main() {
+ Expect.isFalse(test(new A()));
+ Expect.isFalse(test(null));
+}
diff --git a/tests/compiler/dart2js/rti/emission/list.dart b/tests/compiler/dart2js/rti/emission/list.dart
index 250706c..bfcd830 100644
--- a/tests/compiler/dart2js/rti/emission/list.dart
+++ b/tests/compiler/dart2js/rti/emission/list.dart
@@ -4,8 +4,7 @@
import 'package:meta/dart2js.dart';
-/*ast.class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
-/*kernel.class: global#JSArray:checkedInstance,checks=[$isIterable,$isList],instance*/
+/*class: global#JSArray:checkedInstance,checks=[$isIterable],instance*/
/*class: global#Iterable:checkedInstance*/
/*class: A:checkedTypeArgument,checks=[],typeArgument*/
diff --git a/tests/compiler/dart2js/rti/rti_emission_test.dart b/tests/compiler/dart2js/rti/rti_emission_test.dart
index 186a4ae..f7b516b 100644
--- a/tests/compiler/dart2js/rti/rti_emission_test.dart
+++ b/tests/compiler/dart2js/rti/rti_emission_test.dart
@@ -5,7 +5,6 @@
import 'dart:io';
import 'package:async_helper/async_helper.dart';
import 'package:compiler/src/closure.dart';
-import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/common.dart';
import 'package:compiler/src/compiler.dart';
import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
@@ -32,9 +31,6 @@
computeClassDataFromAst: computeAstRtiClassEmission,
computeClassDataFromKernel: computeKernelRtiClassEmission,
args: args,
- options: [
- Flags.strongMode
- ],
skipForKernel: [
// TODO(johnniwinther): Fix this. It triggers a crash in the ssa
// builder.
diff --git a/tests/compiler/dart2js/subtype_test.dart b/tests/compiler/dart2js/subtype_test.dart
index 7d938fc..8053400 100644
--- a/tests/compiler/dart2js/subtype_test.dart
+++ b/tests/compiler/dart2js/subtype_test.dart
@@ -6,6 +6,7 @@
import 'dart:async';
import 'package:async_helper/async_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/entities.dart' show ClassEntity;
import 'package:compiler/src/elements/types.dart';
import 'package:compiler/src/elements/resolution_types.dart';
@@ -18,19 +19,21 @@
await runTests(CompileMode.memory);
print('--test from kernel------------------------------------------------');
await runTests(CompileMode.kernel);
+ print('--test from kernel (strong)---------------------------------------');
+ await runTests(CompileMode.kernel, strongMode: true);
});
}
-Future runTests(CompileMode compileMode) async {
- await testInterfaceSubtype(compileMode);
- await testCallableSubtype(compileMode);
- await testFunctionSubtyping(compileMode);
- await testTypedefSubtyping(compileMode);
- await testFunctionSubtypingOptional(compileMode);
- await testTypedefSubtypingOptional(compileMode);
- await testFunctionSubtypingNamed(compileMode);
- await testTypedefSubtypingNamed(compileMode);
- await testTypeVariableSubtype(compileMode);
+Future runTests(CompileMode compileMode, {bool strongMode: false}) async {
+ await testCallableSubtype(compileMode, strongMode);
+ await testInterfaceSubtype(compileMode, strongMode);
+ await testFunctionSubtyping(compileMode, strongMode);
+ await testTypedefSubtyping(compileMode, strongMode);
+ await testFunctionSubtypingOptional(compileMode, strongMode);
+ await testTypedefSubtypingOptional(compileMode, strongMode);
+ await testFunctionSubtypingNamed(compileMode, strongMode);
+ await testTypedefSubtypingNamed(compileMode, strongMode);
+ await testTypeVariableSubtype(compileMode, strongMode);
}
void testTypes(TypeEnvironment env, DartType subtype, DartType supertype,
@@ -51,14 +54,16 @@
testTypes(env, subtype, supertype, expectSubtype, expectMoreSpecific);
}
-Future testInterfaceSubtype(CompileMode compileMode) async {
+Future testInterfaceSubtype(CompileMode compileMode, bool strongMode) async {
await TypeEnvironment.create(r"""
class A<T> {}
class B<T1, T2> extends A<T1> {}
// TODO(johnniwinther): Inheritance with different type arguments is
// currently not supported by the implementation.
class C<T1, T2> extends B<T2, T1> /*implements A<A<T1>>*/ {}
- """, compileMode: compileMode).then((env) {
+ """,
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : []).then((env) {
void expect(bool expectSubtype, DartType T, DartType S,
{bool expectMoreSpecific}) {
testTypes(env, T, S, expectSubtype, expectMoreSpecific);
@@ -292,7 +297,7 @@
});
}
-Future testCallableSubtype(CompileMode compileMode) async {
+Future testCallableSubtype(CompileMode compileMode, bool strongMode) async {
await TypeEnvironment.create(r"""
class U {}
class V extends U {}
@@ -306,7 +311,9 @@
int m4(V v, U u) => null;
void m5(V v, int i) => null;
}
- """, compileMode: compileMode).then((env) {
+ """,
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : []).then((env) {
void expect(bool expectSubtype, DartType T, DartType S,
{bool expectMoreSpecific}) {
testTypes(env, T, S, expectSubtype, expectMoreSpecific);
@@ -322,14 +329,14 @@
DartType m4 = env.getMemberType('m4', classA);
DartType m5 = env.getMemberType('m5', classA);
- expect(true, A, function);
- expect(true, A, call);
+ expect(!strongMode, A, function);
+ expect(!strongMode, A, call);
expect(true, call, m1);
- expect(true, A, m1);
- expect(true, A, m2, expectMoreSpecific: false);
+ expect(!strongMode, A, m1);
+ expect(!strongMode, A, m2, expectMoreSpecific: false);
expect(false, A, m3);
expect(false, A, m4);
- expect(true, A, m5);
+ expect(!strongMode, A, m5);
});
}
@@ -353,15 +360,19 @@
'void', 'inline_void__int', '(void Function(int i) f)'),
];
-Future testFunctionSubtyping(CompileMode compileMode) async {
+Future testFunctionSubtyping(CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
- .create(createMethods(functionTypesData), compileMode: compileMode)
+ .create(createMethods(functionTypesData),
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingHelper);
}
-Future testTypedefSubtyping(CompileMode compileMode) async {
+Future testTypedefSubtyping(CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
- .create(createTypedefs(functionTypesData), compileMode: compileMode)
+ .create(createTypedefs(functionTypesData),
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingHelper);
}
@@ -437,17 +448,21 @@
const FunctionTypeData('void', 'void___Object_int', '([Object o, int i])'),
];
-Future testFunctionSubtypingOptional(CompileMode compileMode) async {
+Future testFunctionSubtypingOptional(
+ CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
.create(createMethods(optionalFunctionTypesData),
- compileMode: compileMode)
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingOptionalHelper);
}
-Future testTypedefSubtypingOptional(CompileMode compileMode) async {
+Future testTypedefSubtypingOptional(
+ CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
.create(createTypedefs(optionalFunctionTypesData),
- compileMode: compileMode)
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingOptionalHelper);
}
@@ -511,15 +526,21 @@
const FunctionTypeData('void', 'void___c_int', '({int c})'),
];
-Future testFunctionSubtypingNamed(CompileMode compileMode) async {
+Future testFunctionSubtypingNamed(
+ CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
- .create(createMethods(namedFunctionTypesData), compileMode: compileMode)
+ .create(createMethods(namedFunctionTypesData),
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingNamedHelper);
}
-Future testTypedefSubtypingNamed(CompileMode compileMode) async {
+Future testTypedefSubtypingNamed(
+ CompileMode compileMode, bool strongMode) async {
await TypeEnvironment
- .create(createTypedefs(namedFunctionTypesData), compileMode: compileMode)
+ .create(createTypedefs(namedFunctionTypesData),
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : [])
.then(functionSubtypingNamedHelper);
}
@@ -559,7 +580,7 @@
expect(true, 'void___a_int_b_int_c_int', 'void___c_int');
}
-Future testTypeVariableSubtype(CompileMode compileMode) async {
+Future testTypeVariableSubtype(CompileMode compileMode, bool strongMode) async {
await TypeEnvironment.create(r"""
class A<T> {}
class B<T extends Object> {}
@@ -571,7 +592,9 @@
class H<T extends S, S extends T> {}
class I<T extends S, S extends U, U extends T> {}
class J<T extends S, S extends U, U extends S> {}
- """, compileMode: compileMode).then((env) {
+ """,
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : []).then((env) {
void expect(bool expectSubtype, DartType T, DartType S,
{bool expectMoreSpecific}) {
testTypes(env, T, S, expectSubtype, expectMoreSpecific);
diff --git a/tests/compiler/dart2js/subtypeset_test.dart b/tests/compiler/dart2js/subtypeset_test.dart
index 9a43016..d5038c6 100644
--- a/tests/compiler/dart2js/subtypeset_test.dart
+++ b/tests/compiler/dart2js/subtypeset_test.dart
@@ -9,6 +9,7 @@
import 'package:expect/expect.dart';
import 'package:async_helper/async_helper.dart';
import 'type_test_helper.dart';
+import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/universe/class_set.dart';
import 'package:compiler/src/world.dart';
@@ -19,10 +20,12 @@
await runTests(CompileMode.memory);
print('--test from kernel------------------------------------------------');
await runTests(CompileMode.kernel);
+ print('--test from kernel (strong)---------------------------------------');
+ await runTests(CompileMode.kernel, strongMode: true);
});
}
-runTests(CompileMode compileMode) async {
+runTests(CompileMode compileMode, {bool strongMode: false}) async {
var env = await TypeEnvironment.create(r"""
/// A
/// / \
@@ -41,7 +44,8 @@
class G extends C {}
class H implements C {}
class I implements H {}
- """, mainSource: r"""
+ """,
+ mainSource: r"""
main() {
new A().call;
new C();
@@ -50,7 +54,9 @@
new F();
new G();
}
- """, compileMode: compileMode);
+ """,
+ compileMode: compileMode,
+ options: strongMode ? [Flags.strongMode] : []);
ClosedWorld world = env.closedWorld;
ClassEntity A = env.getElement("A");
@@ -62,16 +68,28 @@
ClassEntity G = env.getElement("G");
ClassEntity H = env.getElement("H");
ClassEntity I = env.getElement("I");
+ ClassEntity Function_ = env.getElement("Function");
- void checkClass(ClassEntity cls, List<ClassEntity> subtypes) {
+ void checkClass(ClassEntity cls, List<ClassEntity> expectedSubtypes,
+ {bool checkSubset: false}) {
ClassSet node = world.getClassSet(cls);
- print('$cls:\n${node}');
- Expect.setEquals(
- subtypes,
- node.subtypes().toList(),
- "Unexpected subtypes of ${cls.name}:\n"
- "Expected: $subtypes\n"
- "Found : ${node.subtypes().toList()}");
+ Set<ClassEntity> actualSubtypes = node.subtypes().toSet();
+ if (checkSubset) {
+ for (ClassEntity subtype in expectedSubtypes) {
+ Expect.isTrue(
+ actualSubtypes.contains(subtype),
+ "Unexpected subtype ${subtype} of ${cls.name}:\n"
+ "Expected: $expectedSubtypes\n"
+ "Found : $actualSubtypes");
+ }
+ } else {
+ Expect.setEquals(
+ expectedSubtypes,
+ actualSubtypes,
+ "Unexpected subtypes of ${cls.name}:\n"
+ "Expected: $expectedSubtypes\n"
+ "Found : $actualSubtypes");
+ }
}
checkClass(A, [A, C, E, F, G, B, D, H, I]);
@@ -83,4 +101,6 @@
checkClass(G, [G]);
checkClass(H, [H, I]);
checkClass(I, [I]);
+ checkClass(Function_, strongMode ? [] : [A, B, C, D, E, F, G],
+ checkSubset: true);
}
diff --git a/tests/corelib_2/apply_test.dart b/tests/corelib_2/apply_test.dart
index 2540d9a..9a3e94b 100644
--- a/tests/corelib_2/apply_test.dart
+++ b/tests/corelib_2/apply_test.dart
@@ -42,6 +42,8 @@
Expect.equals(res, Function.apply(func, list, new Map<Symbol, dynamic>()));
}
+ testListTyped(res, Function func, list) => testList(res, func, list);
+
test(res, func, list, map) {
map = symbolMapToStringMap(map);
Expect.equals(res, Function.apply(func, list, map));
@@ -71,6 +73,8 @@
[17, 25]
]));
- // Test that apply works on callable objects.
- testList(42, new Callable(), [13, 29]);
+ // Test that apply works on callable objects when it is passed to a method
+ // that expects Function (and not dynamic).
+ Expect.throws(() => testList(42, new Callable(), [13, 29])); //# 01: ok
+ testListTyped(42, new Callable(), [13, 29]); //# 02: ok
}
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index 303d5ef..92a3bee 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -365,7 +365,6 @@
# ===== dartk + vm status lines =====
[ $compiler == dartk && $runtime == vm && $strong ]
apply3_test: RuntimeError
-apply_test: RuntimeError, OK
iterable_fold_test/02: RuntimeError
iterable_reduce_test/01: CompileTimeError # Issue 31533
iterable_reduce_test/none: RuntimeError
@@ -377,7 +376,6 @@
unicode_test: RuntimeError # Issue 18061: German double S.
[ $compiler == dartkp && $runtime == dart_precompiled && $strong ]
-apply_test: RuntimeError, OK
iterable_fold_test/02: RuntimeError
iterable_reduce_test/01: CompileTimeError # Issue 31533
iterable_reduce_test/none: RuntimeError
@@ -460,6 +458,7 @@
typed_data_with_limited_ints_test: Skip # dart2js and dartdevc don't know about --limit-ints-to-64-bits
[ $runtime != none && ($compiler == dartdevc || $compiler == dartdevk) ]
+apply_test/01: RuntimeError # Issue 32157
apply2_test: RuntimeError # Issue 29921
apply3_test: RuntimeError # Issue 29921
bigint_test: Pass, Slow
@@ -667,3 +666,6 @@
bigint_test: Pass, Crash # Issue 31660
integer_parsed_mul_div_vm_test: Pass, Slow # Slow
+[ $compiler != dartk && $runtime == vm && $checked ]
+apply_test/01: RuntimeError
+
diff --git a/tests/language_2/call_operator_test.dart b/tests/language_2/call_operator_test.dart
index 6709ac7..8513bcb 100644
--- a/tests/language_2/call_operator_test.dart
+++ b/tests/language_2/call_operator_test.dart
@@ -75,6 +75,6 @@
Expect.equals("foo:foo", e.call("foo", count: 2));
Expect.equals("foo:foo:foo", e.call("foo", count: 3));
- Expect.isTrue(a1 is Function);
- Expect.isTrue(e is Function);
+ Expect.isFalse(a1 is Function); //# 01: ok
+ Expect.isFalse(e is Function); //# 02: ok
}
diff --git a/tests/language_2/language_2_dart2js.status b/tests/language_2/language_2_dart2js.status
index f2e28b0..afef09fa 100644
--- a/tests/language_2/language_2_dart2js.status
+++ b/tests/language_2/language_2_dart2js.status
@@ -1069,7 +1069,6 @@
bug31436_test: RuntimeError
call_method_as_cast_test/01: RuntimeError
call_method_as_cast_test/02: RuntimeError
-call_method_as_cast_test/03: RuntimeError
call_method_as_cast_test/04: RuntimeError
call_method_as_cast_test/05: RuntimeError
call_method_function_typed_value_test/02: RuntimeError
@@ -1078,7 +1077,6 @@
call_method_function_typed_value_test/08: RuntimeError
call_method_is_check_test/01: RuntimeError
call_method_is_check_test/02: RuntimeError
-call_method_is_check_test/03: RuntimeError
call_method_is_check_test/04: RuntimeError
call_method_is_check_test/05: RuntimeError
call_method_must_not_be_field_test/03: RuntimeError # Issue 32155
diff --git a/tests/language_2/language_2_dartdevc.status b/tests/language_2/language_2_dartdevc.status
index 08daf52..fd6aff1 100644
--- a/tests/language_2/language_2_dartdevc.status
+++ b/tests/language_2/language_2_dartdevc.status
@@ -734,6 +734,8 @@
branch_canonicalization_test: RuntimeError # Issue 29920; Expect.equals(expected: <0>, actual: <1>) fails.
built_in_identifier_prefix_test: CompileTimeError
call_closurization_test: RuntimeError # Issue 29920; TypeError: Cannot read property '0' of undefined
+call_operator_test/01: RuntimeError # Issue 32157
+call_operator_test/02: RuntimeError # Issue 32157
call_test: RuntimeError # Expect.throws(NoSuchMethodError) fails: Did not throw
canonical_const2_test: RuntimeError # Ints and doubles are unified.; Expect.isFalse(true) fails.
closure_call_wrong_argument_count_negative_test: Fail
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 99371f7..94a1e0f 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -578,7 +578,6 @@
built_in_identifier_prefix_test: CompileTimeError
call_method_must_not_be_field_test/03: RuntimeError # Issue 32265
call_method_must_not_be_getter_test/03: RuntimeError # Issue 32265
-call_operator_test: RuntimeError, OK
call_with_no_such_method_test: RuntimeError
compile_time_constant_k_test/01: MissingCompileTimeError
compile_time_constant_k_test/02: MissingCompileTimeError
@@ -895,7 +894,6 @@
built_in_identifier_prefix_test: CompileTimeError
call_method_must_not_be_field_test/03: RuntimeError # Issue 32265
call_method_must_not_be_getter_test/03: RuntimeError # Issue 32265
-call_operator_test: RuntimeError, OK
call_with_no_such_method_test: RuntimeError
checked_setter3_test/01: MissingCompileTimeError
checked_setter3_test/02: MissingCompileTimeError
diff --git a/tests/language_2/language_2_vm.status b/tests/language_2/language_2_vm.status
index 907d293..e24a1d3 100644
--- a/tests/language_2/language_2_vm.status
+++ b/tests/language_2/language_2_vm.status
@@ -1037,6 +1037,8 @@
unresolved_top_level_var_test: MissingCompileTimeError
[ $compiler != dartk && $runtime == vm && $checked ]
+call_operator_test/01: RuntimeError
+call_operator_test/02: RuntimeError
call_type_literal_test: RuntimeError
class_literal_static_test/none: RuntimeError
class_literal_test/none: RuntimeError