Chromium Code Reviews| Index: tests/language/void_type2_test.dart |
| diff --git a/tests/language/void_type2_test.dart b/tests/language/void_type2_test.dart |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0201cb9b16bf8e390efabbc7ec16b2fe1967cc96 |
| --- /dev/null |
| +++ b/tests/language/void_type2_test.dart |
| @@ -0,0 +1,346 @@ |
| +// 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 test for type checks involving the void type. |
| + |
| +void use(dynamic x) { } |
| + |
| +void testVoidParam(void x) { |
| + x; /// param_stmt: ok |
| + true ? x : x; /// param_conditional: ok |
|
eernst
2017/07/10 16:05:33
We decided at a language meeting long ago that the
|
| + for (x; false; x) {} /// param_for: ok |
| + use(x); /// param_argument: error |
| + use(x as Object); /// param_as: error? |
|
eernst
2017/07/10 16:05:32
It was my understanding that we had agreed to allo
|
| + void y = x; /// param_void_init: error |
| + dynamic y = x; /// param_dynamic_init: error |
| + x is Object; /// param_is: error |
|
eernst
2017/07/10 16:05:33
In the informal spec this is allowed, but as I not
|
| + throw x; /// param_throw: error |
| + [x]; /// param_literal_list_init: error |
| + var m1 = {4: x}; /// param_literal_map_value_init: error |
| + var m2 = {x : 4}; /// param_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: x}; /// param_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = {x : 4}; /// param_literal_map_key_init2: error |
| + x ?? 499; /// param_null_equals2: error |
| + null ?? x; /// param_null_equals2: error |
| + return x; /// param_return: error |
| + while (x) {}; /// param_while: error |
| + do {} while (x); /// param_do_while: error |
| + for (var v in x) {} /// param_for_in: error |
| + for (x in [1, 2]) {} /// param_for_in2: ok |
| + x += 1; /// param_plus_eq: error |
| + x.toString(); /// param_toString: error |
| + x?.toString(); /// param_null_dot: error |
| + x..toString(); /// param_cascade: error |
| +} |
| + |
| +void testVoidCall(void f()) { |
| + f(); /// call_stmt: ok |
| + true ? f() : f(); /// call_conditional: ok |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 11.
|
| + for (f(); false; f()) {} /// call_for: ok |
| + use(f()); /// call_argument: error |
| + use(f() as Object); /// call_as: error? |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 14.
|
| + void y = f(); /// call_void_init: error |
| + dynamic y = f(); /// call_dynamic_init: error |
| + f() is Object; /// call_is: error |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 17.
|
| + throw f(); /// call_throw: error |
| + [f()]; /// call_literal_list_init: error |
| + var m1 = {4: f() }; /// call_literal_map_value_init: error |
| + var m2 = { f(): 4}; /// call_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: f() }; /// call_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { f(): 4}; /// call_literal_map_key_init2: error |
| + f() ?? 499; /// call_null_equals2: error |
| + null ?? f(); /// call_null_equals2: error |
| + return f(); /// call_return: error |
| + while (f()) {}; /// call_while: error |
| + do {} while (f()); /// call_do_while: error |
| + for (var v in f()) {} /// call_for_in: error |
| + f().toString(); /// call_toString: error |
| + f()?.toString(); /// call_null_dot: error |
| + f()..toString(); /// call_cascade: error |
| +} |
| + |
| +void testVoidLocal() { |
| + void x; |
| + x = 42; /// local_assign: ok; |
| + x; /// local_stmt: ok |
| + true ? x : x; /// local_conditional: ok |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 11.
|
| + for (x; false; x) {} /// local_for: ok |
| + use(x); /// local_argument: error |
| + use(x as Object); /// local_as: error? |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 14.
|
| + void y = x; /// local_void_init: error |
| + dynamic y = x; /// local_dynamic_init: error |
| + x is Object; /// local_is: error |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 17.
|
| + throw x; /// local_throw: error |
| + [x]; /// local_literal_list_init: error |
| + var m1 = {4: x}; /// local_literal_map_value_init: error |
| + var m2 = {x : 4}; /// local_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: x}; /// local_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = {x : 4}; /// local_literal_map_key_init2: error |
| + x ?? 499; /// local_null_equals2: error |
| + null ?? x; /// local_null_equals2: error |
| + return x; /// local_return: error |
| + while (x) {}; /// local_while: error |
| + do {} while (x); /// local_do_while: error |
| + for (var v in x) {} /// local_for_in: error |
| + for (x in [1, 2]) {} /// local_for_in2: ok |
| + x += 1; /// local_plus_eq: error |
| + x.toString(); /// local_toString: error |
| + x?.toString(); /// local_null_dot: error |
| + x..toString(); /// local_cascade: error |
| +} |
| + |
| +void testVoidFinalLocal() { |
| + final void x; |
| + x = 42; /// final_local_assign: error; |
| + x; /// final_local_stmt: ok |
| + true ? x : x; /// final_local_conditional: ok |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 11.
|
| + for (x; false; x) {} /// final_local_for: ok |
| + use(x); /// final_local_argument: error |
| + use(x as Object); /// final_local_as: error? |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 14.
|
| + void y = x; /// final_local_void_init: error |
| + dynamic y = x; /// final_local_dynamic_init: error |
| + x is Object; /// final_local_is: error |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 17.
|
| + throw x; /// final_local_throw: error |
| + [x]; /// final_local_literal_list_init: error |
| + var m1 = {4: x}; /// final_local_literal_map_value_init: error |
| + var m2 = {x : 4}; /// final_local_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: x}; /// final_local_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = {x : 4}; /// final_local_literal_map_key_init2: error |
| + x ?? 499; /// final_local_null_equals2: error |
| + null ?? x; /// final_local_null_equals2: error |
| + return x; /// final_local_return: error |
| + while (x) {}; /// final_local_while: error |
| + do {} while (x); /// final_local_do_while: error |
| + for (var v in x) {} /// final_local_for_in: error |
| + for (x in [1, 2]) {} /// final_local_for_in2: ok |
|
eernst
2017/07/10 16:05:33
Why would it be OK to assign to a final local, no
|
| + x += 1; /// final_local_plus_eq: error |
| + x.toString(); /// final_local_toString: error |
| + x?.toString(); /// final_local_null_dot: error |
| + x..toString(); /// final_local_cascade: error |
| +} |
| + |
| +void global; |
| +void testVoidGlobal() { |
| + global; /// global_stmt: ok |
| + true ? global : global; /// global_conditional: ok |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 11.
|
| + for (global; false; global) {} /// global_for: ok |
| + use(global); /// global_argument: error |
| + use(global as Object); /// global_as: error? |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 14.
|
| + void y = global; /// global_void_init: error |
| + dynamic y = global; /// global_dynamic_init: error |
| + global is Object; /// global_is: error |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 17.
|
| + throw global; /// global_throw: error |
| + [global]; /// global_literal_list_init: error |
| + var m1 = {4: global }; /// global_literal_map_value_init: error |
| + var m2 = { global: 4}; /// global_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: global }; /// global_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { global: 4}; /// global_literal_map_key_init2: error |
| + null ?? global; /// global_null_equals2: error |
| + global ?? 499; /// global_null_equals2: error |
| + return global; /// global_return: error |
| + while (global) {}; /// global_while: error |
| + do {} while (global); /// global_do_while: error |
| + for (var v in global) {} /// global_for_in: error |
| + for (global in [1, 2]) {} /// global_for_in2: ok |
| + global += 1; /// global_plus_eq: error |
| + global.toString(); /// global_toString: error |
| + global?.toString(); /// global_null_dot: error |
| + global..toString(); /// global_cascade: error |
| +} |
| + |
| +void testVoidConditional() { |
| + void x; |
| + (true ? x : x); /// conditional_parens: error |
|
Leaf
2017/02/23 21:30:52
Seems odd to me. As far as I can find a unifying
eernst
2017/07/10 16:05:30
The informal spec allows `(e)` even for void `e`,
|
| + true ? x : x; /// conditional_stmt: ok |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 11.
|
| + true ? true ? x : x : true ? x : x; /// conditional_conditional: ok |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 11.
|
| + for (true ? x : x; false; true ? x : x) {} /// conditional_for: ok |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 11.
|
| + use(true ? x : x); /// conditional_argument: error |
| + void y = true ? x : x; /// conditional_void_init: error |
| + dynamic y = true ? x : x; /// conditional_dynamic_init: error |
| + throw true ? x : x; /// conditional_throw: error |
| + [true ? x : x]; /// conditional_literal_list_init: error |
| + var m1 = {4: true ? x : x}; /// conditional_literal_map_value_init: error |
| + Map<dynamic, dynamic> m3 = {4: true ? x : x}; /// conditional_literal_map_value_init2: error |
| + null ?? true ? x : x; /// conditional_null_equals2: error |
| + return true ? x : x; /// conditional_return: error |
| + while (true ? x : x) {}; /// conditional_while: error |
| + do {} while (true ? x : x); /// conditional_do_while: error |
| + for (var v in true ? x : x) {} /// conditional_for_in: error |
| + |
| + (true ? 499 : x); /// conditional2_parens: error |
| + true ? 499 : x; /// conditional2_stmt: ok |
| + true ? true ? 499 : x : true ? 499 : x; /// conditional2_conditional: ok |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 11.
|
| + for (true ? 499 : x; false; true ? 499 : x) {} /// conditional2_for: ok |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 11.
|
| + use(true ? 499 : x); /// conditional2_argument: error |
| + void y = true ? 499 : x; /// conditional2_void_init: error |
| + dynamic y = true ? 499 : x; /// conditional2_dynamic_init: error |
| + throw true ? 499 : x; /// conditional2_throw: error |
| + [true ? 499 : x]; /// conditional2_literal_list_init: error |
| + var m1 = {4: true ? 499 : x}; /// conditional2_literal_map_value_init: error |
| + Map<dynamic, dynamic> m3 = {4: true ? 499 : x}; /// conditional2_literal_map_value_init2: error |
| + null ?? true ? 499 : x; /// conditional2_null_equals2: error |
| + return true ? 499 : x; /// conditional2_return: error |
| + while (true ? 499 : x) {}; /// conditional2while: error |
| + do {} while (true ? 499 : x); /// conditional2do_while: error |
| + for (var v in true ? 499 : x) {} /// conditional2for_in: error |
| + |
| + (true ? x : 499); /// conditional3_parens: error |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 11.
|
| + true ? x : 499; /// conditional3_stmt: ok |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 11.
|
| + true ? true ? x : 499 : true ? x : 499; /// conditional3_conditional: ok |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 11.
|
| + for (true ? x : 499; false; true ? x : 499) {} /// conditional3_for: ok |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 11.
|
| + use(true ? x : 499); /// conditional3_argument: error |
| + void y = true ? x : 499; /// conditional3_void_init: error |
| + dynamic y = true ? x : 499; /// conditional3_dynamic_init: error |
| + throw true ? x : 499; /// conditional3_throw: error |
| + [true ? x : 499]; /// conditional3_literal_list_init: error |
| + var m1 = {4: true ? x : 499 }; /// conditional3_literal_map_value_init: error |
| + Map<dynamic, dynamic> m3 = {4: true ? x : 499 }; /// conditional3_literal_map_value_init2: error |
| + null ?? true ? x : 499; /// conditional3_null_equals2: error |
| + return true ? x : 499; /// conditional3_return: error |
| + while (true ? x : 499) {}; /// conditional_while: error |
| + do {} while (true ? x : 499); /// conditional_do_while: error |
| + for (var v in true ? x : 499) {} /// conditional_for_in: error |
| +} |
| + |
| + |
| +class A<T> { |
| + T x; |
| + |
| + void foo() {} |
| +} |
| + |
| +class B implements A<void> { |
|
Leaf
2017/02/23 21:30:52
Consider adding the contra-variant parameter case
|
| + void x; |
| + |
| + int foo() => 499; |
| +} |
| + |
| +class C implements A<void> { |
|
Leaf
2017/02/23 21:30:52
Is it deliberate that there is an error here (unim
|
| + void get x => null; |
| + set x(void y) {}; |
| +} |
| + |
| + |
| +void testInstanceField() { |
| + A<void> a = new A<void>(); |
| + a.x = 499; /// field_assign: ok |
| + a.x; /// instance_stmt: ok |
| + true ? a.x : a.x; /// instance_conditional: ok |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 11.
|
| + for (a.x; false; a.x) {} /// instance_for: ok |
| + use(a.x); /// instance_argument: error |
| + use(a.x as Object); /// instance_as: error? |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 14.
|
| + void y = a.x; /// instance_void_init: error |
| + dynamic y = a.x; /// instance_dynamic_init: error |
| + a.x is Object; /// instance_is: error |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 17.
|
| + throw a.x; /// instance_throw: error |
| + [a.x]; /// instance_literal_list_init: error |
| + var m1 = {4: a.x}; /// instance_literal_map_value_init: error |
| + var m2 = { a.x : 4}; /// instance_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: a.x}; /// instance_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { a.x : 4}; /// instance_literal_map_key_init2: error |
| + null ?? a.x; /// instance_null_equals2: error |
| + a.x ?? 499; /// instance_null_equals2: error |
| + return a.x; /// instance_return: error |
| + while (a.x) {}; /// instance_while: error |
| + do {} while (a.x); /// instance_do_while: error |
| + for (var v in a.x) {} /// instance_for_in: error |
| + for (a.x in [1, 2]) {} /// instance_for_in2: ok |
| + a.x += 1; /// instance_plus_eq: error |
| + a.x.toString(); /// instance_toString: error |
| + a.x?.toString(); /// instance_null_dot: error |
| + a.x..toString(); /// instance_cascade: error |
| + |
| + B b = new B(); |
| + b.x = 42; /// field_assign2: ok |
| + b.x; /// instance2_stmt: ok |
| + true ? b.x : b.x; /// instance2_conditional: ok |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 11.
|
| + for (b.x; false; b.x) {} /// instance2_for: ok |
| + use(b.x); /// instance2_argument: error |
| + use(b.x as Object); /// instance2_as: error? |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 14.
|
| + void y = b.x; /// instance2_void_init: error |
| + dynamic y = b.x; /// instance2_dynamic_init: error |
| + b.x is Object; /// instance2_is: error |
|
eernst
2017/07/10 16:05:30
Should get the same treatment as line 17.
|
| + throw b.x; /// instance2_throw: error |
| + [b.x]; /// instance2_literal_list_init: error |
| + var m1 = {4: b.x}; /// instance2_literal_map_value_init: error |
| + var m2 = { b.x : 4}; /// instance2_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: b.x}; /// instance2_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { b.x : 4}; /// instance2_literal_map_key_init2: error |
| + null ?? b.x; /// instance2_null_equals2: error |
| + b.x ?? 499; /// instance2_null_equals2: error |
| + return b.x; /// instance2_return: error |
| + while (b.x) {}; /// instance2_while: error |
| + do {} while (b.x); /// instance2_do_while: error |
| + for (var v in b.x) {} /// instance2_for_in: error |
| + for (b.x in [1, 2]) {} /// instance2_for_in2: ok |
| + b.x += 1; /// instance2_plus_eq: error |
| + b.x.toString(); /// instance2_toString: error |
| + b.x?.toString(); /// instance2_null_dot: error |
| + b.x..toString(); /// instance2_cascade: error |
| + |
| + C c = new C(); |
| + c.x = 32; /// setter_assign: ok |
| + c.x; /// instance3_stmt: ok |
| + true ? c.x : c.x; /// instance3_conditional: ok |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 11.
|
| + for (c.x; false; c.x) {} /// instance3_for: ok |
| + use(c.x); /// instance3_argument: error |
| + use(c.x as Object); /// instance3_as: error? |
|
eernst
2017/07/10 16:05:34
Should get the same treatment as line 14.
|
| + void y = c.x; /// instance3_void_init: error |
| + dynamic y = c.x; /// instance3_dynamic_init: error |
| + c.x is Object; /// instance3_is: error |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 17.
|
| + throw c.x; /// instance3_throw: error |
| + [c.x]; /// instance3_literal_list_init: error |
| + var m1 = {4: c.x}; /// instance3_literal_map_value_init: error |
| + var m2 = { c.x : 4}; /// instance3_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: c.x}; /// instance3_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { c.x : 4}; /// instance3_literal_map_key_init2: error |
| + null ?? c.x; /// instance3_null_equals2: error |
| + c.x ?? 499; /// instance3_null_equals2: error |
| + return c.x; /// instance3_return: error |
| + while (c.x) {}; /// instance3_while: error |
| + do {} while (c.x); /// instance3_do_while: error |
| + for (var v in c.x) {} /// instance3_for_in: error |
| + for (c.x in [1, 2]) {} /// instance3_for_in2: ok |
| + c.x += 1; /// instance3_plus_eq: error |
| + c.x.toString(); /// instance3_toString: error |
| + c.x?.toString(); /// instance3_null_dot: error |
| + c.x..toString(); /// instance3_cascade: error |
| +} |
| + |
| +void testParenthesized() { |
| + void x; |
| + (x); /// paren_stmt: ok |
| + true ? (x) : (x); /// paren_conditional: ok |
|
eernst
2017/07/10 16:05:33
Should get the same treatment as line 11.
|
| + for ((x); false; (x)) {} /// paren_for: ok |
| + use((x)); /// paren_argument: error |
| + use((x) as Object); /// paren_as: error? |
|
eernst
2017/07/10 16:05:32
Should get the same treatment as line 14.
|
| + void y = (x); /// paren_void_init: error |
| + dynamic y = (x); /// paren_dynamic_init: error |
| + (x) is Object; /// paren_is: error |
|
eernst
2017/07/10 16:05:31
Should get the same treatment as line 17.
|
| + throw (x); /// paren_throw: error |
| + [(x)]; /// paren_literal_list_init: error |
| + var m1 = {4: (x) }; /// paren_literal_map_value_init: error |
| + var m2 = { (x): 4}; /// paren_literal_map_key_init: error |
| + Map<dynamic, dynamic> m3 = {4: (x) }; /// paren_literal_map_value_init2: error |
| + Map<dynamic, dynamic> m4 = { (x): 4}; /// paren_literal_map_key_init2: error |
| + (x) ?? 499; /// paren_null_equals2: error |
| + null ?? (x); /// paren_null_equals2: error |
| + return (x); /// paren_return: error |
| + while ((x)) {}; /// paren_while: error |
| + do {} while ((x)); /// paren_do_while: error |
| + for (var v in (x)) {} /// paren_for_in: error |
| + (x).toString(); /// paren_toString: error |
| + (x)?.toString(); /// paren_null_dot: error |
| + (x)..toString(); /// paren_cascade: error |
| +} |
| + |
| +main() { |
| + testVoidParam(499); |
| + testVoidCall(() {}); |
| + testVoidLocal(); |
| + testVoidFinalLocal(); |
| + testVoidConditional(); |
| + testInstanceField(); |
| + testParenthesized(); |
| +} |