OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 import 'dart:math'; | 5 import 'dart:math'; |
6 import 'package:expect/expect.dart'; | 6 import 'package:expect/expect.dart'; |
7 | 7 |
8 void testInstantiateToBounds() { | 8 void testInstantiateToBounds() { |
9 f<T extends num, U extends T>() => [T, U]; | 9 f<T extends num, U extends T>() => [T, U]; |
10 g<T extends List<U>, U extends int>() => [T, U]; | 10 g<T extends List<U>, U extends int>() => [T, U]; |
11 h<T extends num, U extends T>(T x, U y) => h.runtimeType.toString(); | 11 h<T extends num, U extends T>(T x, U y) => h.runtimeType.toString(); |
12 | 12 |
13 Expect.listEquals((f as dynamic)(), [num, num]); | 13 Expect.listEquals((f as dynamic)(), [num, num]); |
14 Expect.equals((g as dynamic)().join('|'), 'List<int>|int'); | 14 Expect.equals((g as dynamic)().join('|'), 'List<int>|int'); |
15 Expect.equals((h as dynamic)(null, null), | 15 Expect.equals((h as dynamic)(null, null), |
16 '<T extends num, U extends T>(T, U) -> String'); | 16 '<T extends num, U extends T>(T, U) -> String'); |
17 | 17 |
18 i<T extends Iterable<T>>() => null; | 18 i<T extends Iterable<T>>() => null; |
19 j<T extends Iterable<S>, S extends T>() => null; | 19 j<T extends Iterable<S>, S extends T>() => null; |
20 Expect.throws(() => (i as dynamic)(), | 20 Expect.throws( |
21 (e) => '$e'.contains('Instantiate to bounds')); | 21 () => (i as dynamic)(), (e) => '$e'.contains('Instantiate to bounds')); |
22 Expect.throws(() => (j as dynamic)(), | 22 Expect.throws( |
23 (e) => '$e'.contains('Instantiate to bounds')); | 23 () => (j as dynamic)(), (e) => '$e'.contains('Instantiate to bounds')); |
24 } | 24 } |
25 | 25 |
26 void testChecksBound() { | 26 void testChecksBound() { |
27 f<T extends num>(T x) => x; | 27 f<T extends num>(T x) => x; |
28 Expect.equals((f as dynamic)(42), 42); | 28 Expect.equals((f as dynamic)(42), 42); |
29 Expect.throws(() => (f as dynamic)('42')); | 29 Expect.throws(() => (f as dynamic)('42')); |
30 | 30 |
| 31 msg(t1, t2, tf) => Expect.throws(() => (f as dynamic)<Object>(42), |
| 32 (e) => '$e' == 'type `Object` does not extend `num` of `T'); |
| 33 |
31 g<T extends U, U extends num>(T x, U y) => x; | 34 g<T extends U, U extends num>(T x, U y) => x; |
32 Expect.equals((g as dynamic)(42.0, 100), 42.0); | 35 Expect.equals((g as dynamic)(42.0, 100), 42.0); |
33 Expect.throws(() => (g as dynamic)('hi', 100)); | 36 Expect.throws(() => (g as dynamic)('hi', 100)); |
| 37 Expect.throws(() => (g as dynamic)<double, int>(42.0, 100), |
| 38 (e) => '$e' == 'type `double` does not extend `int` of `T`.'); |
| 39 |
| 40 Expect.throws(() => (g as dynamic)<num, Object>(42.0, 100), |
| 41 (e) => '$e' == 'type `Object` does not extend `num` of `U`.'); |
34 } | 42 } |
35 | 43 |
36 typedef G<U> = T Function<T extends U>(T x); | 44 typedef G<U> = T Function<T extends U>(T x); |
37 | 45 |
38 void testSubtype() { | 46 void testSubtype() { |
39 f<T extends num>(T x) => x + 2; | 47 f<T extends num>(T x) => x + 2; |
40 | 48 |
41 dynamic d = f; | 49 dynamic d = f; |
42 Expect.equals(d(40.0), 42.0); | 50 Expect.equals(d(40.0), 42.0); |
43 Expect.equals((f as G<int>)(40), 42); | 51 Expect.equals((f as G<int>)(40), 42); |
44 Expect.equals((d as G<int>)(40), 42); | 52 Expect.equals((d as G<int>)(40), 42); |
45 Expect.equals((f as G<double>)(40.0), 42.0); | 53 Expect.equals((f as G<double>)(40.0), 42.0); |
46 Expect.equals((d as G<double>)(40.0), 42.0); | 54 Expect.equals((d as G<double>)(40.0), 42.0); |
47 | 55 |
48 d as G<Null>; | 56 d as G<Null>; |
49 Expect.throws(() => d as G); | 57 Expect.throws(() => d as G); |
50 Expect.throws(() => d as G<Object>); | 58 Expect.throws(() => d as G<Object>); |
51 Expect.throws(() => d as G<String>); | 59 Expect.throws(() => d as G<String>); |
52 } | 60 } |
53 | 61 |
54 void testToString() { | 62 void testToString() { |
55 // TODO(jmesserly): I don't think the cast on `y` should be required. | 63 // TODO(jmesserly): I don't think the cast on `y` should be required. |
56 num f<T extends num, U extends T>(T x, U y) => min(x, y as num); | 64 num f<T extends num, U extends T>(T x, U y) => min(x, y as num); |
57 num g<T, U>(T x, U y) => max(x as num, y as num); | 65 num g<T, U>(T x, U y) => max(x as num, y as num); |
58 String h<T, U>(T x, U y) => h.runtimeType.toString(); | 66 String h<T, U>(T x, U y) => h.runtimeType.toString(); |
59 Expect.equals(f.runtimeType.toString(), | 67 Expect.equals( |
60 '<T extends num, U extends T>(T, U) -> num'); | 68 f.runtimeType.toString(), '<T extends num, U extends T>(T, U) -> num'); |
61 Expect.equals(g.runtimeType.toString(), '<T, U>(T, U) -> num'); | 69 Expect.equals(g.runtimeType.toString(), '<T, U>(T, U) -> num'); |
62 Expect.equals(h(42, 123.0), '<T, U>(T, U) -> String'); | 70 Expect.equals(h(42, 123.0), '<T, U>(T, U) -> String'); |
63 } | 71 } |
64 | 72 |
65 main() { | 73 main() { |
66 testInstantiateToBounds(); | 74 testInstantiateToBounds(); |
67 testToString(); | 75 testToString(); |
68 testChecksBound(); | 76 testChecksBound(); |
69 testSubtype(); | 77 testSubtype(); |
70 } | 78 } |
OLD | NEW |