@@ -1183,6 +1183,85 @@ class TypeSystemTests: XCTestCase {
1183
1183
XCTAssertEqual ( tagIntersection, . nothing)
1184
1184
}
1185
1185
1186
+ func testWasmAbstractHeapTypeSubsumptionRules( ) {
1187
+ let groupAny : [ WasmAbstractHeapType ] =
1188
+ [ . WasmAny, . WasmEq, . WasmI31, . WasmStruct, . WasmArray, . WasmNone]
1189
+ let groupExtern : [ WasmAbstractHeapType ] = [ . WasmExtern, . WasmNoExtern]
1190
+ let groupFunc : [ WasmAbstractHeapType ] = [ . WasmFunc, . WasmNoFunc]
1191
+ let groupExn : [ WasmAbstractHeapType ] = [ . WasmExn, . WasmNoExn]
1192
+ let allGroups = [ groupAny, groupExtern, groupFunc, groupExn]
1193
+ let allTypes = allGroups. joined ( )
1194
+ // If this fails, please extend the arrays above with the newly added type(s).
1195
+ XCTAssert ( WasmAbstractHeapType . allCases. allSatisfy ( allTypes. contains) )
1196
+
1197
+ // All types in the same type group share the same bottom type.
1198
+ XCTAssert ( groupAny. allSatisfy { $0. getBottom ( ) == . WasmNone} )
1199
+ XCTAssert ( groupExtern. allSatisfy { $0. getBottom ( ) == . WasmNoExtern} )
1200
+ XCTAssert ( groupFunc. allSatisfy { $0. getBottom ( ) == . WasmNoFunc} )
1201
+ XCTAssert ( groupExn. allSatisfy { $0. getBottom ( ) == . WasmNoExn} )
1202
+
1203
+ // The union and intersection of of two unrelated types are nil.
1204
+ for groupA in allGroups {
1205
+ for groupB in allGroups where groupA != groupB {
1206
+ for typeA in groupA {
1207
+ for typeB in groupB {
1208
+ XCTAssertNil ( typeA. union ( typeB) , " a= \( typeA) b= \( typeB) " )
1209
+ XCTAssertNil ( typeA. intersection ( typeB) , " a= \( typeA) b= \( typeB) " )
1210
+ }
1211
+ }
1212
+ }
1213
+ }
1214
+
1215
+ for type in allTypes {
1216
+ XCTAssertEqual ( type. union ( type) , type)
1217
+ XCTAssertEqual ( type. union ( type. getBottom ( ) ) , type)
1218
+ XCTAssertEqual ( type. getBottom ( ) . union ( type) , type)
1219
+ XCTAssertEqual ( type. intersection ( type) , type)
1220
+ XCTAssertEqual ( type. intersection ( type. getBottom ( ) ) , type. getBottom ( ) )
1221
+ }
1222
+
1223
+ // Testing a few combinations.
1224
+ XCTAssertEqual ( WasmAbstractHeapType . WasmAny. union ( . WasmEq) , . WasmAny)
1225
+ XCTAssertEqual ( WasmAbstractHeapType . WasmStruct. union ( . WasmArray) , . WasmEq)
1226
+ XCTAssertEqual ( WasmAbstractHeapType . WasmI31. union ( . WasmArray) , . WasmEq)
1227
+ XCTAssertEqual ( WasmAbstractHeapType . WasmArray. union ( . WasmEq) , . WasmEq)
1228
+ XCTAssertEqual ( WasmAbstractHeapType . WasmArray. intersection ( . WasmStruct) , . WasmNone)
1229
+ XCTAssertEqual ( WasmAbstractHeapType . WasmI31. intersection ( . WasmStruct) , . WasmNone)
1230
+ XCTAssertEqual ( WasmAbstractHeapType . WasmI31. intersection ( . WasmEq) , . WasmI31)
1231
+ XCTAssertEqual ( WasmAbstractHeapType . WasmAny. intersection ( . WasmArray) , . WasmArray)
1232
+
1233
+ // Tests on the whole ILType.
1234
+ let ref = { t in ILType . wasmRef ( . Abstract( t) , nullability: false ) }
1235
+ let refNull = { t in ILType . wasmRef ( . Abstract( t) , nullability: false ) }
1236
+ for type in allTypes {
1237
+ let refT = ref ( type)
1238
+ let refNullT = refNull ( type)
1239
+ XCTAssertEqual ( refT. union ( with: refNullT) , refNullT)
1240
+ XCTAssertEqual ( refNullT. union ( with: refT) , refNullT)
1241
+ XCTAssertEqual ( refT. union ( with: refT) , refT)
1242
+ XCTAssertEqual ( refNullT. union ( with: refNullT) , refNullT)
1243
+ XCTAssertEqual ( refT. intersection ( with: refT) , refT)
1244
+ XCTAssertEqual ( refNullT. intersection ( with: refNullT) , refNullT)
1245
+ XCTAssertEqual ( refT. intersection ( with: refNullT) , refT)
1246
+ XCTAssertEqual ( refNullT. intersection ( with: refT) , refT)
1247
+ }
1248
+
1249
+ XCTAssertEqual ( ref ( . WasmAny) . union ( with: refNull ( . WasmEq) ) , refNull ( . WasmAny) )
1250
+ XCTAssertEqual ( ref ( . WasmStruct) . union ( with: ref ( . WasmArray) ) , ref ( . WasmEq) )
1251
+ // We should never do this for the type information of any Variable as .wasmGenericRef
1252
+ // cannot be encoded in the Wasm module and any instruction that leads to such a static type
1253
+ // is "broken". However, we will still need to allow this union type if we want to be able
1254
+ // to request a .required(.wasmGenericRef) for operations like WasmRefIsNull.
1255
+ XCTAssertEqual ( ref ( . WasmI31) . union ( with: refNull ( . WasmExn) ) , . wasmGenericRef)
1256
+
1257
+ XCTAssertEqual ( ref ( . WasmAny) . intersection ( with: refNull ( . WasmEq) ) , ref ( . WasmEq) )
1258
+ XCTAssertEqual ( refNull ( . WasmI31) . intersection ( with: refNull ( . WasmStruct) ) , refNull ( . WasmNone) )
1259
+ // Note that `ref none` is a perfectly valid type in Wasm but such a reference can never be
1260
+ // constructed.
1261
+ XCTAssertEqual ( ref ( . WasmArray) . intersection ( with: refNull ( . WasmStruct) ) , ref ( . WasmNone) )
1262
+ XCTAssertEqual ( refNull ( . WasmArray) . intersection ( with: ref ( . WasmAny) ) , ref ( . WasmArray) )
1263
+ }
1264
+
1186
1265
func testUnboundFunctionSubsumptionRules( ) {
1187
1266
XCTAssertEqual ( ILType . unboundFunction ( ) , . unboundFunction( ) )
1188
1267
XCTAssertNotEqual ( ILType . unboundFunction ( [ ] => . object( ) ) , . unboundFunction( ) )
0 commit comments