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