Index: tests/language/least_upper_bound_test.dart |
diff --git a/tests/language/least_upper_bound_test.dart b/tests/language/least_upper_bound_test.dart |
new file mode 100644 |
index 0000000000000000000000000000000000000000..410671a8c7420ca4af183fffbf3a4f41f297bf97 |
--- /dev/null |
+++ b/tests/language/least_upper_bound_test.dart |
@@ -0,0 +1,103 @@ |
+// Copyright (c) 2013, 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. |
+ |
+// Test least upper bound through type checking of conditionals. |
+ |
+class A { |
+ var a; |
+} |
+class B { |
+ var b; |
+} |
+class C extends B { |
+ var c; |
+} |
+class D extends B { |
+ var d; |
+} |
+ |
+class E<T> { |
+ T e; |
+ |
+ E(this.e); |
+} |
+class F<T> extends E<T> { |
+ T f; |
+ |
+ F(T f) : this.f = f, super(f); |
+} |
+ |
+void main() { |
+ testAB(new A(), new B()); |
+ testBC(new C(), new C()); |
+ testCD(new C(), new D()); |
+ testEE(new F<C>(new C()), new F<C>(new C())); |
+ testEF(new F<C>(new C()), new F<C>(new C())); |
+} |
+ |
+void testAB(A a, B b) { |
+ A r1 = true ? a : b; /// 01: ok |
+ B r2 = false ? a : b; /// 02: ok |
+ (true ? a : b).a = 0; /// 03: static type warning |
+ (false ? a : b).b = 0; /// 04: static type warning |
+ var c = new C(); |
+ (true ? a : c).a = 0; /// 05: ok |
+ (false ? c : b).b = 0; /// 06: ok |
+} |
+ |
+void testBC(B b, C c) { |
+ B r1 = true ? b : c; /// 07: ok |
+ C r2 = false ? b : c; /// 08: ok |
+ (true ? b : c).b = 0; /// 09: ok |
+ (false ? b : c).c = 0; /// 10: static type warning |
+ var a = null; |
+ (true ? b : a).b = 0; /// 11: ok |
+ (false ? a : b).c = 0; /// 12: ok |
+ (true ? c : a).b = 0; /// 13: ok |
+ (false ? a : c).c = 0; /// 14: ok |
+} |
+ |
+void testCD(C c, D d) { |
+ C r1 = true ? c : d; /// 15: ok |
+ D r2 = false ? c : d; /// 16: ok |
+ (true ? c : d).b = 0; /// 17: ok |
+ (false ? c : d).b = 0; /// 18: ok |
+ (true ? c : d).c = 0; /// 19: static type warning |
+ (false ? c : d).d = 0; /// 20: static type warning |
+} |
+ |
+void testEE(E<B> e, E<C> f) { |
+ // The least upper bound of E<B> and E<C> is Object since the supertypes are |
+ // {E<B>, Object} for E<B> and |
+ // {E<C>, Object} for E<C> and |
+ // Object is the most specific type in the intersection of the supertypes. |
+ E<B> r1 = true ? e : f; /// 21: ok |
+ F<C> r2 = false ? e : f; /// 22: ok |
+ try { |
+ A r3 = true ? e : f; /// 23: ok |
+ B r4 = false ? e : f; /// 24: ok |
+ } catch (e) { |
+ // Type error in checked mode. |
+ } |
+ (true ? e : f).e = null; /// 25: static type warning |
+ (false ? e : f).e = null; /// 26: static type warning |
+} |
+ |
+void testEF(E<B> e, F<C> f) { |
+ // The least upper bound of E<B> and F<C> is Object since the supertypes are |
+ // {E<B>, Object} for E<B> and |
+ // {F<C>, E<C>, Object} for F<C> and |
+ // Object is the most specific type in the intersection of the supertypes. |
+ E<B> r1 = true ? e : f; /// 27: ok |
+ F<C> r2 = false ? e : f; /// 28: ok |
+ try { |
+ A r3 = true ? e : f; /// 29: ok |
+ B r4 = false ? e : f; /// 30: ok |
+ } catch (e) { |
+ // Type error in checked mode. |
+ } |
+ var r5; |
+ r5 = (true ? e : f).e; /// 31: static type warning |
+ r5 = (false ? e : f).f; /// 32: static type warning |
+} |