Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(383)

Side by Side Diff: tests/language_strong/covariant_subtyping_test.dart

Issue 2954523002: fix #27259, implement covariance checking for strong mode and DDC (Closed)
Patch Set: rebase Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4 import 'package:expect/expect.dart';
5
6 class Fields<T> {
7 T x;
8 T _y;
9 T _z;
10
11 m() {
12 _y = x;
13 }
14
15 n(Fields<T> c) {
16 c._z = x;
17 }
18 }
19
20 testField() {
21 Fields<Object> c = new Fields<int>();
22 Expect.throws(() {
23 c.x = 'hello';
24 });
25 }
26
27 testPrivateFields() {
28 Fields<Object> c = new Fields<int>()..x = 42;
29 c.m();
30 Expect.equals(c._y, 42);
31
32 Fields<Object> c2 = new Fields<String>()..x = 'hi';
33 c2.n(c2);
34 Expect.equals(c2._z, 'hi');
35 Expect.throws(() {
36 c.n(c2);
37 });
38 Expect.equals(c2._z, 'hi');
39 }
40
41 class NumBounds<T extends num> {
42 bool m(T t) => t.isNegative;
43 }
44
45 class MethodTakesNum extends NumBounds<int> {
46 bool m(num obj) => obj.isNegative; // does not need check
47 }
48
49 class MethodTakesInt extends NumBounds<int> {
50 bool m(int obj) => obj.isNegative; // needs a check
51 }
52
53 testClassBounds() {
54 NumBounds<num> d = new MethodTakesNum();
55 Expect.equals(d.m(-1.1), true);
56 d = new MethodTakesInt();
57 Expect.throws(() {
58 d.m(-1.1);
59 });
60 }
61
62 typedef void F<T>(T t);
63 typedef G<T> = void Function<S extends T>(S s);
64
65 class FnChecks<T> {
66 F<T> f;
67 G<T> g;
68 T _t;
69 T getT() => _t;
70 F<T> setterForT() {
71 return (T t) {
72 _t = t;
73 };
74 }
75 }
76
77 testReturnOfFunctionType() {
78 FnChecks<int> cInt = new FnChecks<int>();
79 FnChecks<Object> cObj = cInt;
80 cObj.setterForT();
81 Expect.throws(() {
82 cObj.setterForT()(42);
83 });
84 Expect.throws(() {
85 cObj.setterForT()('hi');
86 });
87 cInt.setterForT()(42);
88 Expect.equals(cObj.getT(), 42);
89 dynamic d = cObj.setterForT();
90 d(100);
91 Expect.equals(cInt.getT(), 100);
92 Expect.throws(() {
93 d('hi');
94 });
95 }
96
97 testFieldOfFunctionType() {
98 FnChecks<Object> c = new FnChecks<String>()..f = (String b) {};
99 Expect.throws(() {
100 F<Object> f = c.f;
101 });
102 Expect.throws(() {
103 var f = c.f;
104 });
105 Expect.throws(() {
106 c.f(42);
107 });
108 Expect.throws(() {
109 c.f('hi');
110 });
111 FnChecks<String> cStr = c;
112 cStr.f('hi');
113 }
114
115 testFieldOfGenericFunctionType() {
116 FnChecks<Object> c = new FnChecks<num>()
117 ..g = <S extends num>(S s) => s.isNegative;
118
119 Expect.throws(() {
120 G<Object> g = c.g;
121 });
122 Expect.throws(() {
123 var g = c.g;
124 });
125 Expect.throws(() {
126 c.g<String>('hi');
127 });
128 Expect.throws(() {
129 c.g<int>(42);
130 });
131 FnChecks<num> cNum = c;
132 cNum.g(42);
133 }
134
135 class Base {
136 int _t = 0;
137 add(int t) {
138 _t += t;
139 }
140 }
141
142 abstract class I<T> {
143 add(T t);
144 }
145
146 class ExtendsBase extends Base implements I<int> {}
147
148 class MixinBase extends Object with Base implements I<int> {}
149
150 class MixinBase2 = Object with Base implements I<int>;
151
152 testMixinApplication() {
153 I<Object> i = new ExtendsBase();
154 I<Object> j = new MixinBase();
155 I<Object> k = new MixinBase2();
156 Expect.throws(() {
157 i.add('hi');
158 });
159 Expect.throws(() {
160 j.add('hi');
161 });
162 // TODO(jmesserly): this should also throw. It does not because DDC's
163 // technique for generating mixin aliases (mixin applications of the form
164 // `class X = Object with Y /* optional implements */;`) does not allow
165 // adding any methods in the class. The normal technique of generating
166 // a method that performs the check and then calls `super` will not work,
167 // because there is no superclass to call. We will need some sort of
168 // special case code to implement this, perhaps move the original
169 // method to a symbol, then generate a wrapper with the original method name,
170 // that checks and calls it.
171 k.add('hi');
172 }
173
174 abstract class GenericAdd<T> {
175 add<S extends T>(S t);
176 }
177
178 class GenericAdder implements GenericAdd<num> {
179 num _t = 0;
180 add<T extends num>(T t) {
181 _t = t;
182 }
183 }
184
185 testGenericMethodBounds() {
186 GenericAdd<Object> i = new GenericAdder();
187 Expect.throws(() {
188 i.add('hi');
189 });
190 Expect.throws(() {
191 i.add<String>(null);
192 });
193 i.add(null);
194 i.add(42);
195 }
196
197 class ClassF<T> {
198 T x;
199 void call(T t) {
200 x = t;
201 }
202 }
203
204 testCallMethod() {
205 ClassF<int> cc = new ClassF<int>();
206 ClassF<Object> ca = cc; // An upcast, per covariance.
207 F<Object> f = ca;
208 Expect.equals(f.runtimeType.toString(), 'ClassF<int>');
209 Expect.throws(() {
210 f(new Object());
211 });
212 }
213
214 main() {
215 testField();
216 testPrivateFields();
217 testClassBounds();
218 testReturnOfFunctionType();
219 testFieldOfFunctionType();
220 testFieldOfGenericFunctionType();
221 testMixinApplication();
222 testGenericMethodBounds();
223 testCallMethod();
224 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698