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 'package:expect/expect.dart'; | 8 import 'package:expect/expect.dart'; |
8 import 'package:async_helper/async_helper.dart'; | 9 import 'package:async_helper/async_helper.dart'; |
9 import 'type_test_helper.dart'; | 10 import 'type_test_helper.dart'; |
10 import 'package:compiler/src/elements/elements.dart' | 11 import 'package:compiler/src/elements/elements.dart' |
11 show Element, ClassElement; | 12 show Element, ClassElement; |
12 import 'package:compiler/src/types/types.dart'; | 13 import 'package:compiler/src/types/types.dart'; |
| 14 import 'package:compiler/src/world.dart' show |
| 15 ClassWorld; |
13 | 16 |
14 isCheckedMode() { | 17 isCheckedMode() { |
15 try { | 18 try { |
16 var i = 1; | 19 var i = 1; |
17 String s = i; | 20 String s = i; |
18 return false; | 21 return false; |
19 } catch (e) { | 22 } catch (e) { |
20 return true; | 23 return true; |
21 } | 24 } |
22 } | 25 } |
23 | 26 |
24 void main() { | 27 void main() { |
25 testUnionTypeMaskFlatten(); | 28 asyncTest(() async { |
| 29 await testUnionTypeMaskFlatten(); |
| 30 await testStringSubtypes(); |
| 31 }); |
26 } | 32 } |
27 | 33 |
28 void testUnionTypeMaskFlatten() { | 34 checkMasks(ClassWorld classWorld, |
29 asyncTest(() => TypeEnvironment.create(r""" | 35 List<ClassElement> allClasses, |
| 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""" |
30 class A {} | 89 class A {} |
31 class B {} | 90 class B {} |
32 class C extends A {} | 91 class C extends A {} |
33 class D implements A {} | 92 class D implements A {} |
34 class E extends B implements A {} | 93 class E extends B implements A {} |
35 """, | 94 """, |
36 mainSource: r""" | 95 mainSource: r""" |
37 main() { | 96 main() { |
38 new A(); | 97 new A(); |
39 new B(); | 98 new B(); |
40 new C(); | 99 new C(); |
41 new D(); | 100 new D(); |
42 new E(); | 101 new E(); |
43 } | 102 } |
44 """, | 103 """, |
45 useMockCompiler: false).then((env) { | 104 useMockCompiler: false); |
| 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); |
46 var classWorld = env.compiler.world; | 227 var classWorld = env.compiler.world; |
| 228 var backend = env.compiler.backend; |
47 | 229 |
48 ClassElement Object_ = env.getElement("Object"); | 230 ClassElement Object_ = env.getElement("Object"); |
49 ClassElement A = env.getElement("A"); | 231 ClassElement String_ = env.getElement("String"); |
50 ClassElement B = env.getElement("B"); | 232 ClassElement JSString = backend.helpers.jsStringClass; |
51 ClassElement C = env.getElement("C"); | |
52 ClassElement D = env.getElement("D"); | |
53 ClassElement E = env.getElement("E"); | |
54 | 233 |
55 List<ClassElement> allClasses = <ClassElement>[Object_, A, B, C, D, E]; | 234 List<ClassElement> allClasses = <ClassElement>[Object_, String_]; |
56 | 235 |
57 check(List<FlatTypeMask> masks, | 236 Expect.isFalse(classWorld.isDirectlyInstantiated(Object_)); |
58 {FlatTypeMask result, | 237 Expect.isTrue(classWorld.isIndirectlyInstantiated(Object_)); |
59 List<FlatTypeMask> disjointMasks, | 238 Expect.isTrue(classWorld.isInstantiated(Object_)); |
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 } | |
103 | 239 |
104 } | 240 Expect.isFalse(classWorld.isDirectlyInstantiated(String_)); |
105 return union; | 241 Expect.isFalse(classWorld.isIndirectlyInstantiated(String_)); |
106 } | 242 Expect.isFalse(classWorld.isInstantiated(String_)); |
107 | 243 |
108 TypeMask empty = const TypeMask.nonNullEmpty(); | 244 Expect.isTrue(classWorld.isDirectlyInstantiated(JSString)); |
109 TypeMask subclassObject = new TypeMask.nonNullSubclass(Object_, classWorld); | 245 Expect.isFalse(classWorld.isIndirectlyInstantiated(JSString)); |
110 TypeMask exactA = new TypeMask.nonNullExact(A, classWorld); | 246 Expect.isTrue(classWorld.isInstantiated(JSString)); |
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); | |
118 | 247 |
119 check([], | 248 TypeMask subtypeString = new TypeMask.nonNullSubtype(String_, classWorld); |
120 result: empty, | 249 TypeMask exactJSString = new TypeMask.nonNullExact(JSString, classWorld); |
121 disjointMasks: [], | 250 TypeMask subtypeJSString = |
122 containedClasses: []); | 251 new TypeMask.nonNullSubtype(JSString, classWorld); |
| 252 TypeMask subclassJSString = |
| 253 new TypeMask.nonNullSubclass(JSString, classWorld); |
123 | 254 |
124 check([exactA], | 255 Expect.equals(exactJSString, subtypeString); |
125 result: exactA, | 256 Expect.equals(exactJSString, subtypeJSString); |
126 disjointMasks: [exactA], | 257 Expect.equals(exactJSString, subclassJSString); |
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 })); | |
194 } | 258 } |
OLD | NEW |