OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 library type_mask2_test; | 5 library type_mask2_test; |
6 | 6 |
7 import 'dart:async'; | |
8 import 'package:expect/expect.dart'; | 7 import 'package:expect/expect.dart'; |
9 import 'package:async_helper/async_helper.dart'; | 8 import 'package:async_helper/async_helper.dart'; |
10 import 'type_test_helper.dart'; | 9 import 'type_test_helper.dart'; |
11 import 'package:compiler/src/elements/elements.dart' | 10 import 'package:compiler/src/elements/elements.dart' |
12 show Element, ClassElement; | 11 show Element, ClassElement; |
13 import 'package:compiler/src/types/types.dart'; | 12 import 'package:compiler/src/types/types.dart'; |
14 import 'package:compiler/src/world.dart' show | |
15 ClassWorld; | |
16 | 13 |
17 isCheckedMode() { | 14 isCheckedMode() { |
18 try { | 15 try { |
19 var i = 1; | 16 var i = 1; |
20 String s = i; | 17 String s = i; |
21 return false; | 18 return false; |
22 } catch (e) { | 19 } catch (e) { |
23 return true; | 20 return true; |
24 } | 21 } |
25 } | 22 } |
26 | 23 |
27 void main() { | 24 void main() { |
28 asyncTest(() async { | 25 testUnionTypeMaskFlatten(); |
29 await testUnionTypeMaskFlatten(); | |
30 await testStringSubtypes(); | |
31 }); | |
32 } | 26 } |
33 | 27 |
34 checkMasks(ClassWorld classWorld, | 28 void testUnionTypeMaskFlatten() { |
35 List<ClassElement> allClasses, | 29 asyncTest(() => TypeEnvironment.create(r""" |
36 List<FlatTypeMask> masks, | |
37 {FlatTypeMask result, | |
38 List<FlatTypeMask> disjointMasks, | |
39 FlatTypeMask flattened, | |
40 List<ClassElement> containedClasses}) { | |
41 List<FlatTypeMask> disjoint = <FlatTypeMask>[]; | |
42 UnionTypeMask.unionOfHelper(masks, disjoint, classWorld); | |
43 Expect.listEquals(disjointMasks, disjoint, | |
44 'Unexpected disjoint masks: $disjoint, expected $disjointMasks.'); | |
45 if (flattened == null) { | |
46 // We only do the invalid call to flatten in checked mode, as flatten's | |
47 // behaviour in unchecked mode is not defined and thus cannot be | |
48 // reliably tested. | |
49 if (isCheckedMode()) { | |
50 Expect.throws(() => UnionTypeMask.flatten(disjoint, classWorld), | |
51 (e) => e is AssertionError, | |
52 'Expect assertion failure on flattening of $disjoint.'); | |
53 } | |
54 } else { | |
55 TypeMask flattenResult = | |
56 UnionTypeMask.flatten(disjoint, classWorld); | |
57 Expect.equals(flattened, flattenResult, | |
58 'Unexpected flattening of $disjoint: ' | |
59 '$flattenResult, expected $flattened.'); | |
60 } | |
61 var union = UnionTypeMask.unionOf(masks, classWorld); | |
62 if (result == null) { | |
63 Expect.isTrue(union is UnionTypeMask, | |
64 'Expected union of $masks to be a union-type: $union.'); | |
65 Expect.listEquals(disjointMasks, union.disjointMasks, | |
66 'Unexpected union masks: ' | |
67 '${union.disjointMasks}, expected $disjointMasks.'); | |
68 } else { | |
69 Expect.equals(result, union, | |
70 'Unexpected union of $masks: $union, expected $result.'); | |
71 } | |
72 if (containedClasses != null) { | |
73 for (ClassElement cls in allClasses) { | |
74 if (containedClasses.contains(cls)) { | |
75 Expect.isTrue(union.contains(cls, classWorld), | |
76 'Expected $union to contain $cls.'); | |
77 } else { | |
78 Expect.isFalse(union.contains(cls, classWorld), | |
79 '$union not expected to contain $cls.'); | |
80 } | |
81 } | |
82 | |
83 } | |
84 return union; | |
85 } | |
86 | |
87 Future testUnionTypeMaskFlatten() async { | |
88 TypeEnvironment env = await TypeEnvironment.create(r""" | |
89 class A {} | 30 class A {} |
90 class B {} | 31 class B {} |
91 class C extends A {} | 32 class C extends A {} |
92 class D implements A {} | 33 class D implements A {} |
93 class E extends B implements A {} | 34 class E extends B implements A {} |
94 """, | 35 """, |
95 mainSource: r""" | 36 mainSource: r""" |
96 main() { | 37 main() { |
97 new A(); | 38 new A(); |
98 new B(); | 39 new B(); |
99 new C(); | 40 new C(); |
100 new D(); | 41 new D(); |
101 new E(); | 42 new E(); |
102 } | 43 } |
103 """, | 44 """, |
104 useMockCompiler: false); | 45 useMockCompiler: false).then((env) { |
105 | |
106 ClassWorld classWorld = env.compiler.world; | |
107 | |
108 ClassElement Object_ = env.getElement("Object"); | |
109 ClassElement A = env.getElement("A"); | |
110 ClassElement B = env.getElement("B"); | |
111 ClassElement C = env.getElement("C"); | |
112 ClassElement D = env.getElement("D"); | |
113 ClassElement E = env.getElement("E"); | |
114 | |
115 List<ClassElement> allClasses = <ClassElement>[Object_, A, B, C, D, E]; | |
116 | |
117 check(List<FlatTypeMask> masks, | |
118 {FlatTypeMask result, | |
119 List<FlatTypeMask> disjointMasks, | |
120 FlatTypeMask flattened, | |
121 List<ClassElement> containedClasses}) { | |
122 return checkMasks( | |
123 classWorld, | |
124 allClasses, | |
125 masks, | |
126 result: result, | |
127 disjointMasks: disjointMasks, | |
128 flattened: flattened, | |
129 containedClasses: containedClasses); | |
130 } | |
131 | |
132 TypeMask empty = const TypeMask.nonNullEmpty(); | |
133 TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld); | |
134 TypeMask exactA = new TypeMask.nonNullExact(A, classWorld); | |
135 TypeMask subclassA = new TypeMask.nonNullSubclass(A, classWorld); | |
136 TypeMask subtypeA = new TypeMask.nonNullSubtype(A, classWorld); | |
137 TypeMask exactB = new TypeMask.nonNullExact(B, classWorld); | |
138 TypeMask subclassB = new TypeMask.nonNullSubclass(B, classWorld); | |
139 TypeMask exactC = new TypeMask.nonNullExact(C, classWorld); | |
140 TypeMask exactD = new TypeMask.nonNullExact(D, classWorld); | |
141 TypeMask exactE = new TypeMask.nonNullExact(E, classWorld); | |
142 | |
143 check([], | |
144 result: empty, | |
145 disjointMasks: [], | |
146 containedClasses: []); | |
147 | |
148 check([exactA], | |
149 result: exactA, | |
150 disjointMasks: [exactA], | |
151 containedClasses: [A]); | |
152 | |
153 check([exactA, exactA], | |
154 result: exactA, | |
155 disjointMasks: [exactA], | |
156 containedClasses: [A]); | |
157 | |
158 check([exactA, exactB], | |
159 disjointMasks: [exactA, exactB], | |
160 flattened: subclassObject, | |
161 containedClasses: [A, B]); | |
162 | |
163 check([subclassObject], | |
164 result: subclassObject, | |
165 disjointMasks: [subclassObject], | |
166 containedClasses: [Object_, A, B, C, D, E]); | |
167 | |
168 check([subclassObject, exactA], | |
169 disjointMasks: [subclassObject], | |
170 result: subclassObject, | |
171 containedClasses: [Object_, A, B, C, D, E]); | |
172 | |
173 check([exactA, exactC], | |
174 disjointMasks: [subclassA], | |
175 result: subclassA, | |
176 containedClasses: [A, C]); | |
177 | |
178 check([exactA, exactB, exactC], | |
179 disjointMasks: [subclassA, exactB], | |
180 flattened: subclassObject, | |
181 containedClasses: [A, B, C]); | |
182 | |
183 check([exactA, exactD], | |
184 disjointMasks: [subtypeA], | |
185 result: subtypeA, | |
186 containedClasses: [A, C, D, E]); | |
187 | |
188 check([exactA, exactB, exactD], | |
189 disjointMasks: [subtypeA, exactB], | |
190 flattened: subclassObject, | |
191 containedClasses: [A, B, C, D, E]); | |
192 | |
193 check([exactA, exactE], | |
194 disjointMasks: [subtypeA], | |
195 result: subtypeA, | |
196 containedClasses: [A, C, D, E]); | |
197 | |
198 check([exactA, exactB, exactE], | |
199 disjointMasks: [subtypeA, exactB], | |
200 flattened: subclassObject, | |
201 containedClasses: [A, B, C, D, E]); | |
202 | |
203 check([exactB, exactE, exactA], | |
204 disjointMasks: [subclassB, exactA], | |
205 flattened: subclassObject, | |
206 containedClasses: [A, B, E]); | |
207 | |
208 check([exactE, exactA, exactB], | |
209 disjointMasks: [subtypeA, exactB], | |
210 flattened: subclassObject, | |
211 containedClasses: [A, B, C, D, E]); | |
212 | |
213 check([exactE, exactB, exactA], | |
214 disjointMasks: [subclassB, exactA], | |
215 flattened: subclassObject, | |
216 containedClasses: [A, B, E]); | |
217 } | |
218 | |
219 Future testStringSubtypes() async { | |
220 TypeEnvironment env = await TypeEnvironment.create('', | |
221 mainSource: r""" | |
222 main() { | |
223 '' is String; | |
224 } | |
225 """, | |
226 useMockCompiler: false); | |
227 var classWorld = env.compiler.world; | 46 var classWorld = env.compiler.world; |
228 var backend = env.compiler.backend; | |
229 | 47 |
230 ClassElement Object_ = env.getElement("Object"); | 48 ClassElement Object_ = env.getElement("Object"); |
231 ClassElement String_ = env.getElement("String"); | 49 ClassElement A = env.getElement("A"); |
232 ClassElement JSString = backend.helpers.jsStringClass; | 50 ClassElement B = env.getElement("B"); |
| 51 ClassElement C = env.getElement("C"); |
| 52 ClassElement D = env.getElement("D"); |
| 53 ClassElement E = env.getElement("E"); |
233 | 54 |
234 List<ClassElement> allClasses = <ClassElement>[Object_, String_]; | 55 List<ClassElement> allClasses = <ClassElement>[Object_, A, B, C, D, E]; |
235 | 56 |
236 Expect.isFalse(classWorld.isDirectlyInstantiated(Object_)); | 57 check(List<FlatTypeMask> masks, |
237 Expect.isTrue(classWorld.isIndirectlyInstantiated(Object_)); | 58 {FlatTypeMask result, |
238 Expect.isTrue(classWorld.isInstantiated(Object_)); | 59 List<FlatTypeMask> disjointMasks, |
| 60 FlatTypeMask flattened, |
| 61 List<ClassElement> containedClasses}) { |
| 62 List<FlatTypeMask> disjoint = <FlatTypeMask>[]; |
| 63 UnionTypeMask.unionOfHelper(masks, disjoint, classWorld); |
| 64 Expect.listEquals(disjointMasks, disjoint, |
| 65 'Unexpected disjoint masks: $disjoint, expected $disjointMasks.'); |
| 66 if (flattened == null) { |
| 67 // We only do the invalid call to flatten in checked mode, as flatten's |
| 68 // brehaviour in unchecked more is not defined and thus cannot be |
| 69 // reliably tested. |
| 70 if (isCheckedMode()) { |
| 71 Expect.throws(() => UnionTypeMask.flatten(disjoint, classWorld), |
| 72 (e) => e is AssertionError, |
| 73 'Expect assertion failure on flattening of $disjoint.'); |
| 74 } |
| 75 } else { |
| 76 TypeMask flattenResult = |
| 77 UnionTypeMask.flatten(disjoint, classWorld); |
| 78 Expect.equals(flattened, flattenResult, |
| 79 'Unexpected flattening of $disjoint: ' |
| 80 '$flattenResult, expected $flattened.'); |
| 81 } |
| 82 var union = UnionTypeMask.unionOf(masks, classWorld); |
| 83 if (result == null) { |
| 84 Expect.isTrue(union is UnionTypeMask, |
| 85 'Expected union of $masks to be a union-type: $union.'); |
| 86 Expect.listEquals(disjointMasks, union.disjointMasks, |
| 87 'Unexpected union masks: ' |
| 88 '${union.disjointMasks}, expected $disjointMasks.'); |
| 89 } else { |
| 90 Expect.equals(result, union, |
| 91 'Unexpected union of $masks: $union, expected $result.'); |
| 92 } |
| 93 if (containedClasses != null) { |
| 94 for (ClassElement cls in allClasses) { |
| 95 if (containedClasses.contains(cls)) { |
| 96 Expect.isTrue(union.contains(cls, classWorld), |
| 97 'Expected $union to contain $cls.'); |
| 98 } else { |
| 99 Expect.isFalse(union.contains(cls, classWorld), |
| 100 '$union not expected to contain $cls.'); |
| 101 } |
| 102 } |
239 | 103 |
240 Expect.isFalse(classWorld.isDirectlyInstantiated(String_)); | 104 } |
241 Expect.isFalse(classWorld.isIndirectlyInstantiated(String_)); | 105 return union; |
242 Expect.isFalse(classWorld.isInstantiated(String_)); | 106 } |
243 | 107 |
244 Expect.isTrue(classWorld.isDirectlyInstantiated(JSString)); | 108 TypeMask empty = const TypeMask.nonNullEmpty(); |
245 Expect.isFalse(classWorld.isIndirectlyInstantiated(JSString)); | 109 TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld); |
246 Expect.isTrue(classWorld.isInstantiated(JSString)); | 110 TypeMask exactA = new TypeMask.nonNullExact(A, classWorld); |
| 111 TypeMask subclassA = new TypeMask.nonNullSubclass(A, classWorld); |
| 112 TypeMask subtypeA = new TypeMask.nonNullSubtype(A, classWorld); |
| 113 TypeMask exactB = new TypeMask.nonNullExact(B, classWorld); |
| 114 TypeMask subclassB = new TypeMask.nonNullSubclass(B, classWorld); |
| 115 TypeMask exactC = new TypeMask.nonNullExact(C, classWorld); |
| 116 TypeMask exactD = new TypeMask.nonNullExact(D, classWorld); |
| 117 TypeMask exactE = new TypeMask.nonNullExact(E, classWorld); |
247 | 118 |
248 TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, classWorld); | 119 check([], |
249 TypeMask exactJSString = new TypeMask.nonNullExact(JSString, classWorld); | 120 result: empty, |
250 TypeMask subtypeJSString = | 121 disjointMasks: [], |
251 new TypeMask.nonNullSubtype(JSString, classWorld); | 122 containedClasses: []); |
252 TypeMask subclassJSString = | |
253 new TypeMask.nonNullSubclass(JSString, classWorld); | |
254 | 123 |
255 Expect.equals(exactJSString, subtypeString); | 124 check([exactA], |
256 Expect.equals(exactJSString, subtypeJSString); | 125 result: exactA, |
257 Expect.equals(exactJSString, subclassJSString); | 126 disjointMasks: [exactA], |
| 127 containedClasses: [A]); |
| 128 |
| 129 check([exactA, exactA], |
| 130 result: exactA, |
| 131 disjointMasks: [exactA], |
| 132 containedClasses: [A]); |
| 133 |
| 134 check([exactA, exactB], |
| 135 disjointMasks: [exactA, exactB], |
| 136 flattened: subclassObject, |
| 137 containedClasses: [A, B]); |
| 138 |
| 139 check([subclassObject], |
| 140 result: subclassObject, |
| 141 disjointMasks: [subclassObject], |
| 142 containedClasses: [Object_, A, B, C, D, E]); |
| 143 |
| 144 check([subclassObject, exactA], |
| 145 disjointMasks: [subclassObject], |
| 146 result: subclassObject, |
| 147 containedClasses: [Object_, A, B, C, D, E]); |
| 148 |
| 149 check([exactA, exactC], |
| 150 disjointMasks: [subclassA], |
| 151 result: subclassA, |
| 152 containedClasses: [A, C]); |
| 153 |
| 154 check([exactA, exactB, exactC], |
| 155 disjointMasks: [subclassA, exactB], |
| 156 flattened: subclassObject, |
| 157 containedClasses: [A, B, C]); |
| 158 |
| 159 check([exactA, exactD], |
| 160 disjointMasks: [subtypeA], |
| 161 result: subtypeA, |
| 162 containedClasses: [A, C, D, E]); |
| 163 |
| 164 check([exactA, exactB, exactD], |
| 165 disjointMasks: [subtypeA, exactB], |
| 166 flattened: subclassObject, |
| 167 containedClasses: [A, B, C, D, E]); |
| 168 |
| 169 check([exactA, exactE], |
| 170 disjointMasks: [subtypeA], |
| 171 result: subtypeA, |
| 172 containedClasses: [A, C, D, E]); |
| 173 |
| 174 check([exactA, exactB, exactE], |
| 175 disjointMasks: [subtypeA, exactB], |
| 176 flattened: subclassObject, |
| 177 containedClasses: [A, B, C, D, E]); |
| 178 |
| 179 check([exactB, exactE, exactA], |
| 180 disjointMasks: [subclassB, exactA], |
| 181 flattened: subclassObject, |
| 182 containedClasses: [A, B, E]); |
| 183 |
| 184 check([exactE, exactA, exactB], |
| 185 disjointMasks: [subtypeA, exactB], |
| 186 flattened: subclassObject, |
| 187 containedClasses: [A, B, C, D, E]); |
| 188 |
| 189 check([exactE, exactB, exactA], |
| 190 disjointMasks: [subclassB, exactA], |
| 191 flattened: subclassObject, |
| 192 containedClasses: [A, B, E]); |
| 193 })); |
258 } | 194 } |
OLD | NEW |