summaryrefslogtreecommitdiffstats
path: root/js/src/jit-test/tests/wasm/gc/value_subtyping.js
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit-test/tests/wasm/gc/value_subtyping.js')
-rw-r--r--js/src/jit-test/tests/wasm/gc/value_subtyping.js305
1 files changed, 305 insertions, 0 deletions
diff --git a/js/src/jit-test/tests/wasm/gc/value_subtyping.js b/js/src/jit-test/tests/wasm/gc/value_subtyping.js
new file mode 100644
index 0000000000..bc0a3df678
--- /dev/null
+++ b/js/src/jit-test/tests/wasm/gc/value_subtyping.js
@@ -0,0 +1,305 @@
+// |jit-test| skip-if: !wasmGcEnabled()
+
+function simpleTypeSection(types) {
+ return types.map((x, i) => `(type \$${i} ${x})`).join('\n');
+}
+
+function assertSubtype(superType, subType, types) {
+ types = types || [];
+ wasmEvalText(`(module
+ ${types}
+ (func
+ unreachable
+ (block (param ${subType})
+ (block (param ${superType})
+ drop
+ )
+ )
+ )
+ )`);
+}
+
+function assertNotSubtype(superType, subType, types) {
+ assertErrorMessage(() => {
+ assertSubtype(superType, subType, types);
+ }, WebAssembly.CompileError, /type mismatch/);
+}
+
+// Primitive trivial subtyping
+assertSubtype('i32', 'i32');
+assertSubtype('i64', 'i64');
+assertSubtype('f32', 'f32');
+assertSubtype('f64', 'f64');
+assertSubtype('eqref', 'eqref');
+assertSubtype('funcref', 'funcref');
+
+// No subtyping relation between funcref, anyref, externref. These are our top
+// types.
+assertNotSubtype('funcref', 'anyref');
+assertNotSubtype('anyref', 'funcref');
+assertNotSubtype('funcref', 'externref');
+assertNotSubtype('externref', 'funcref');
+assertNotSubtype('externref', 'anyref');
+assertNotSubtype('anyref', 'externref');
+
+// eqref is a subtype of anyref
+assertSubtype('anyref', 'eqref');
+
+// structref is a subtype of eqref and anyref
+assertSubtype('anyref', 'structref');
+assertSubtype('eqref', 'structref');
+
+// arrayref is a subtype of eqref and anyref
+assertSubtype('anyref', 'arrayref');
+assertSubtype('eqref', 'arrayref');
+
+// Structs are subtypes of anyref, eqref, and structref
+assertSubtype(
+ 'anyref',
+ '(ref 0)',
+ simpleTypeSection(['(struct)']));
+assertSubtype(
+ 'eqref',
+ '(ref 0)',
+ simpleTypeSection(['(struct)']));
+assertSubtype(
+ 'structref',
+ '(ref 0)',
+ simpleTypeSection(['(struct)']));
+
+// Struct identity
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection(['(struct)', '(struct)']));
+assertSubtype(
+ '(ref 1)',
+ '(ref 0)',
+ simpleTypeSection(['(struct)', '(struct)']));
+
+// Self referential struct
+assertSubtype(
+ '(ref 1)',
+ '(ref 0)',
+ simpleTypeSection(['(struct (ref 0))', '(struct (ref 1))']));
+
+// Mutually referential structs
+assertSubtype(
+ '(ref 2)',
+ '(ref 0)',
+ `(rec
+ (type (struct (ref 1)))
+ (type (struct (ref 0)))
+ )
+ (rec
+ (type (struct (ref 3)))
+ (type (struct (ref 2)))
+ )`);
+
+// Struct subtypes can have extra fields
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ `(type (struct))
+ (type (sub 0 (struct (field i32))))`);
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ `(type (struct))
+ (type (sub 0 (struct (field i32) (field i32))))`);
+
+// Struct supertypes cannot have extra fields
+assertNotSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(struct (field i32))',
+ '(struct)']));
+
+// Struct field mutability must match
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(struct (field (mut i32)))',
+ '(struct (field (mut i32)))']));
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(struct (field i32))',
+ '(struct (field i32))']));
+assertNotSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(struct (field (mut i32)))',
+ '(struct (field i32))']));
+assertNotSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(struct (field i32))',
+ '(struct (field (mut i32)))']));
+
+// Struct fields are invariant when mutable
+assertSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ simpleTypeSection([
+ '(struct)',
+ '(struct)',
+ '(struct (field (mut (ref 0))))',
+ '(struct (field (mut (ref 1))))']));
+assertNotSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ simpleTypeSection([
+ '(struct)',
+ '(struct (field i32))',
+ '(struct (field (mut (ref 0))))',
+ '(struct (field (mut (ref 1))))']));
+
+// Struct fields are covariant when immutable
+assertSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ `(type (struct))
+ (type (sub 0 (struct (field i32))))
+ (type (struct (field (ref 0))))
+ (type (sub 2 (struct (field (ref 1)))))`);
+
+// Arrays are subtypes of anyref, eqref, and arrayref
+assertSubtype(
+ 'anyref',
+ '(ref 0)',
+ simpleTypeSection(['(array i32)']));
+assertSubtype(
+ 'eqref',
+ '(ref 0)',
+ simpleTypeSection(['(array i32)']));
+assertSubtype(
+ 'arrayref',
+ '(ref 0)',
+ simpleTypeSection(['(array i32)']));
+
+// Array identity
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection(['(array i32)', '(array i32)']));
+assertSubtype(
+ '(ref 1)',
+ '(ref 0)',
+ simpleTypeSection(['(array i32)', '(array i32)']));
+
+// Self referential array
+assertSubtype(
+ '(ref 1)',
+ '(ref 0)',
+ simpleTypeSection(['(array (ref 0))', '(array (ref 1))']));
+
+// Mutually referential arrays
+assertSubtype(
+ '(ref 2)',
+ '(ref 0)',
+ `(rec
+ (type (array (ref 1)))
+ (type (array (ref 0)))
+ )
+ (rec
+ (type (array (ref 3)))
+ (type (array (ref 2)))
+ )`);
+
+// Array mutability must match
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(array (mut i32))',
+ '(array (mut i32))']));
+assertSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(array i32)',
+ '(array i32)']));
+assertNotSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(array (mut i32))',
+ '(array i32)']));
+assertNotSubtype(
+ '(ref 0)',
+ '(ref 1)',
+ simpleTypeSection([
+ '(array i32)',
+ '(array (mut i32))']));
+
+// Array elements are invariant when mutable
+assertSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ simpleTypeSection([
+ '(struct)',
+ '(struct)',
+ '(array (mut (ref 0)))',
+ '(array (mut (ref 1)))']));
+assertNotSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ simpleTypeSection([
+ '(struct)',
+ '(struct (field i32))',
+ '(array (mut (ref 0)))',
+ '(array (mut (ref 1)))']));
+
+// Array elements are covariant when immutable
+assertSubtype(
+ '(ref 2)',
+ '(ref 3)',
+ `(type (struct))
+ (type (sub 0 (struct (field i32))))
+ (type (array (ref 0)))
+ (type (sub 2 (array (ref 1))))`);
+
+// nullref is a subtype of everything in anyref hierarchy
+assertSubtype('anyref', 'nullref');
+assertSubtype('eqref', 'nullref');
+assertSubtype('structref', 'nullref');
+assertSubtype('arrayref', 'nullref');
+assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(struct)']));
+assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(array i32)']));
+
+// nullref is not a subtype of any other hierarchy
+assertNotSubtype('funcref', 'nullref');
+assertNotSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(func)']));
+assertNotSubtype('externref', 'nullref');
+
+// nullfuncref is a subtype of everything in funcref hierarchy
+assertSubtype('funcref', 'nullfuncref');
+assertSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(func)']));
+
+// nullfuncref is not a subtype of any other hierarchy
+assertNotSubtype('anyref', 'nullfuncref');
+assertNotSubtype('eqref', 'nullfuncref');
+assertNotSubtype('structref', 'nullfuncref');
+assertNotSubtype('arrayref', 'nullfuncref');
+assertNotSubtype('externref', 'nullfuncref');
+assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(struct)']));
+assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(array i32)']));
+
+// nullexternref is a subtype of everything in externref hierarchy
+assertSubtype('externref', 'nullexternref');
+
+// nullexternref is not a subtype of any other hierarchy
+assertNotSubtype('anyref', 'nullexternref');
+assertNotSubtype('eqref', 'nullexternref');
+assertNotSubtype('structref', 'nullexternref');
+assertNotSubtype('arrayref', 'nullexternref');
+assertNotSubtype('funcref', 'nullexternref');
+assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(struct)']));
+assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(array i32)']));
+assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(func)']));