| Index: tests/language/least_upper_bound_expansive_test.dart
|
| diff --git a/tests/language/least_upper_bound_expansive_test.dart b/tests/language/least_upper_bound_expansive_test.dart
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..704b2a384faefb22cc9a892a87481f363ac20185
|
| --- /dev/null
|
| +++ b/tests/language/least_upper_bound_expansive_test.dart
|
| @@ -0,0 +1,101 @@
|
| +// 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 N<T> {
|
| + T get n => null;
|
| +}
|
| +
|
| +class C1<T> extends N<N<C1<T>>> {
|
| + T get c1 => null;
|
| +}
|
| +
|
| +class C2<T> extends N<N<C2<N<C2<T>>>>> {
|
| + T get c2 => null;
|
| +}
|
| +
|
| +/**
|
| + * Test that we don't try to find the least upper bound by applying the
|
| + * algorithm for finding the most specific common declaration recursively on
|
| + * type arguments.
|
| + *
|
| + * For C1<int> and N<C1<String>> this would result in this infinite chain of
|
| + * computations:
|
| + *
|
| + * lub(C1<int>, N<C1<String>>) = lub(N<N<C1<int>>>, N<C1<String>>)
|
| + * =>
|
| + * lub(N<C1<int>>, C1<String>) = lub(N<C1<int>>, N<N<C1<String>>>)
|
| + * =>
|
| + * lub(C1<int>, N<C1<String>>) = lub(N<N<C1<int>>>, N<C1<String>>>)
|
| + * => ...
|
| + */
|
| +void testC1(bool z, C1<int> a, N<C1<String>> b) {
|
| + if (z) {
|
| + // The least upper bound of C1<int> and N<C1<String>> is Object since the
|
| + // supertypes are
|
| + // {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
|
| + // {N<C1<String>>, Object} for N<C1<String>> and
|
| + // Object is the most specific type in the intersection of the supertypes.
|
| +
|
| + // Is least upper bound dynamic?
|
| + (z ? a : b).z; /// 01: static type warning
|
| + // Is least upper bound N<...> ?
|
| + (z ? a : b).n; /// 02: static type warning
|
| + // Is least upper bound C1<...> ?
|
| + (z ? a : b).c1; /// 03: static type warning
|
| + // Is least upper bound N<dynamic> ?
|
| + (z ? a : b).n.z; /// 04: static type warning
|
| + // Is least upper bound N<N<...>> ?
|
| + (z ? a : b).n.n; /// 05: static type warning
|
| + // Is least upper bound N<C1<...>> ?
|
| + (z ? a : b).n.c1; /// 06: static type warning
|
| + }
|
| +}
|
| +
|
| +/**
|
| + * Test that we don't try to find the least upper bound by applying the
|
| + * algorithm for finding the most specific common declaration recursively on
|
| + * type arguments.
|
| + *
|
| + * For C1<int> and N<C1<String>> this would result in this infinite and
|
| + * expanding chain of computations:
|
| + *
|
| + * lub(C2<int>, N<C2<String>>) = lub(N<N<C2<N<C2<int>>>>>, N<C2<String>>)
|
| + * =>
|
| + * lub(N<C2<N<C2<int>>>>, C2<String>) =
|
| + * lub(N<C2<N<C2<int>>>>, N<N<C2<N<C2<String>>>>>)
|
| + * =>
|
| + * lub(C2<N<C2<int>>>, N<C2<N<C2<String>>>>) =
|
| + * lub(N<N<C2<N<C2<int>>>>>, N<C2<N<C2<String>>>>>)
|
| + * => ...
|
| + */
|
| +
|
| +void testC2(bool z, C2<int> a, N<C2<String>> b) {
|
| + if (z) {
|
| + // The least upper bound of C2<int> and N<C2<String>> is Object since the
|
| + // supertypes are
|
| + // {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C1<int> and
|
| + // {N<C2<String>>, Object} for N<C1<String>> and
|
| + // Object is the most specific type in the intersection of the supertypes.
|
| +
|
| + // Is least upper bound dynamic?
|
| + (z ? a : b).z; /// 07: static type warning
|
| + // Is least upper bound N<...> ?
|
| + (z ? a : b).n; /// 08: static type warning
|
| + // Is least upper bound C2<...> ?
|
| + (z ? a : b).c2; /// 09: static type warning
|
| + // Is least upper bound N<dynamic> ?
|
| + (z ? a : b).n.z; /// 10: static type warning
|
| + // Is least upper bound N<N<...>> ?
|
| + (z ? a : b).n.n; /// 11: static type warning
|
| + // Is least upper bound N<C2<...>> ?
|
| + (z ? a : b).n.c2; /// 12: static type warning
|
| + }
|
| +}
|
| +
|
| +void main() {
|
| + testC1(false, null, null);
|
| + testC2(false, null, null);
|
| +}
|
|
|