value_subtyping.js (7760B)
1 function simpleTypeSection(types) { 2 return types.map((x, i) => `(type \$${i} ${x})`).join('\n'); 3 } 4 5 function assertSubtype(superType, subType, types) { 6 types = types || []; 7 wasmEvalText(`(module 8 ${types} 9 (func 10 unreachable 11 (block (param ${subType}) 12 (block (param ${superType}) 13 drop 14 ) 15 ) 16 ) 17 )`); 18 } 19 20 function assertNotSubtype(superType, subType, types) { 21 assertErrorMessage(() => { 22 assertSubtype(superType, subType, types); 23 }, WebAssembly.CompileError, /type mismatch/); 24 } 25 26 // Primitive trivial subtyping 27 assertSubtype('i32', 'i32'); 28 assertSubtype('i64', 'i64'); 29 assertSubtype('f32', 'f32'); 30 assertSubtype('f64', 'f64'); 31 assertSubtype('eqref', 'eqref'); 32 assertSubtype('i31ref', 'i31ref'); 33 assertSubtype('funcref', 'funcref'); 34 35 // No subtyping relation between funcref, anyref, externref. These are our top 36 // types. 37 assertNotSubtype('funcref', 'anyref'); 38 assertNotSubtype('anyref', 'funcref'); 39 assertNotSubtype('funcref', 'externref'); 40 assertNotSubtype('externref', 'funcref'); 41 assertNotSubtype('externref', 'anyref'); 42 assertNotSubtype('anyref', 'externref'); 43 44 // eqref is a subtype of anyref 45 assertSubtype('anyref', 'eqref'); 46 47 // i31ref is a subtype of eqref 48 assertSubtype('anyref', 'i31ref'); 49 assertSubtype('eqref', 'i31ref'); 50 51 // structref is a subtype of eqref and anyref 52 assertSubtype('anyref', 'structref'); 53 assertSubtype('eqref', 'structref'); 54 55 // arrayref is a subtype of eqref and anyref 56 assertSubtype('anyref', 'arrayref'); 57 assertSubtype('eqref', 'arrayref'); 58 59 // Structs are subtypes of anyref, eqref, and structref 60 assertSubtype( 61 'anyref', 62 '(ref 0)', 63 simpleTypeSection(['(struct)'])); 64 assertSubtype( 65 'eqref', 66 '(ref 0)', 67 simpleTypeSection(['(struct)'])); 68 assertSubtype( 69 'structref', 70 '(ref 0)', 71 simpleTypeSection(['(struct)'])); 72 73 // Struct identity 74 assertSubtype( 75 '(ref 0)', 76 '(ref 1)', 77 simpleTypeSection(['(struct)', '(struct)'])); 78 assertSubtype( 79 '(ref 1)', 80 '(ref 0)', 81 simpleTypeSection(['(struct)', '(struct)'])); 82 83 // Self referential struct 84 assertSubtype( 85 '(ref 1)', 86 '(ref 0)', 87 simpleTypeSection(['(struct (field (ref 0)))', '(struct (field (ref 1)))'])); 88 89 // Mutually referential structs 90 assertSubtype( 91 '(ref 2)', 92 '(ref 0)', 93 `(rec 94 (type (struct (field (ref 1)))) 95 (type (struct (field (ref 0)))) 96 ) 97 (rec 98 (type (struct (field (ref 3)))) 99 (type (struct (field (ref 2)))) 100 )`); 101 102 // Struct subtypes can have extra fields 103 assertSubtype( 104 '(ref 0)', 105 '(ref 1)', 106 `(type (sub (struct))) 107 (type (sub 0 (struct (field i32))))`); 108 assertSubtype( 109 '(ref 0)', 110 '(ref 1)', 111 `(type (sub (struct))) 112 (type (sub 0 (struct (field i32) (field i32))))`); 113 114 // Struct supertypes cannot have extra fields 115 assertNotSubtype( 116 '(ref 0)', 117 '(ref 1)', 118 simpleTypeSection([ 119 '(struct (field i32))', 120 '(struct)'])); 121 122 // Struct field mutability must match 123 assertSubtype( 124 '(ref 0)', 125 '(ref 1)', 126 simpleTypeSection([ 127 '(struct (field (mut i32)))', 128 '(struct (field (mut i32)))'])); 129 assertSubtype( 130 '(ref 0)', 131 '(ref 1)', 132 simpleTypeSection([ 133 '(struct (field i32))', 134 '(struct (field i32))'])); 135 assertNotSubtype( 136 '(ref 0)', 137 '(ref 1)', 138 simpleTypeSection([ 139 '(struct (field (mut i32)))', 140 '(struct (field i32))'])); 141 assertNotSubtype( 142 '(ref 0)', 143 '(ref 1)', 144 simpleTypeSection([ 145 '(struct (field i32))', 146 '(struct (field (mut i32)))'])); 147 148 // Struct fields are invariant when mutable 149 assertSubtype( 150 '(ref 2)', 151 '(ref 3)', 152 simpleTypeSection([ 153 '(struct)', 154 '(struct)', 155 '(struct (field (mut (ref 0))))', 156 '(struct (field (mut (ref 1))))'])); 157 assertNotSubtype( 158 '(ref 2)', 159 '(ref 3)', 160 simpleTypeSection([ 161 '(struct)', 162 '(struct (field i32))', 163 '(struct (field (mut (ref 0))))', 164 '(struct (field (mut (ref 1))))'])); 165 166 // Struct fields are covariant when immutable 167 assertSubtype( 168 '(ref 2)', 169 '(ref 3)', 170 `(type (sub (struct))) 171 (type (sub 0 (struct (field i32)))) 172 (type (sub (struct (field (ref 0))))) 173 (type (sub 2 (struct (field (ref 1)))))`); 174 175 // Arrays are subtypes of anyref, eqref, and arrayref 176 assertSubtype( 177 'anyref', 178 '(ref 0)', 179 simpleTypeSection(['(array i32)'])); 180 assertSubtype( 181 'eqref', 182 '(ref 0)', 183 simpleTypeSection(['(array i32)'])); 184 assertSubtype( 185 'arrayref', 186 '(ref 0)', 187 simpleTypeSection(['(array i32)'])); 188 189 // Array identity 190 assertSubtype( 191 '(ref 0)', 192 '(ref 1)', 193 simpleTypeSection(['(array i32)', '(array i32)'])); 194 assertSubtype( 195 '(ref 1)', 196 '(ref 0)', 197 simpleTypeSection(['(array i32)', '(array i32)'])); 198 199 // Self referential array 200 assertSubtype( 201 '(ref 1)', 202 '(ref 0)', 203 simpleTypeSection(['(array (ref 0))', '(array (ref 1))'])); 204 205 // Mutually referential arrays 206 assertSubtype( 207 '(ref 2)', 208 '(ref 0)', 209 `(rec 210 (type (array (ref 1))) 211 (type (array (ref 0))) 212 ) 213 (rec 214 (type (array (ref 3))) 215 (type (array (ref 2))) 216 )`); 217 218 // Array mutability must match 219 assertSubtype( 220 '(ref 0)', 221 '(ref 1)', 222 simpleTypeSection([ 223 '(array (mut i32))', 224 '(array (mut i32))'])); 225 assertSubtype( 226 '(ref 0)', 227 '(ref 1)', 228 simpleTypeSection([ 229 '(array i32)', 230 '(array i32)'])); 231 assertNotSubtype( 232 '(ref 0)', 233 '(ref 1)', 234 simpleTypeSection([ 235 '(array (mut i32))', 236 '(array i32)'])); 237 assertNotSubtype( 238 '(ref 0)', 239 '(ref 1)', 240 simpleTypeSection([ 241 '(array i32)', 242 '(array (mut i32))'])); 243 244 // Array elements are invariant when mutable 245 assertSubtype( 246 '(ref 2)', 247 '(ref 3)', 248 simpleTypeSection([ 249 '(struct)', 250 '(struct)', 251 '(array (mut (ref 0)))', 252 '(array (mut (ref 1)))'])); 253 assertNotSubtype( 254 '(ref 2)', 255 '(ref 3)', 256 simpleTypeSection([ 257 '(struct)', 258 '(struct (field i32))', 259 '(array (mut (ref 0)))', 260 '(array (mut (ref 1)))'])); 261 262 // Array elements are covariant when immutable 263 assertSubtype( 264 '(ref 2)', 265 '(ref 3)', 266 simpleTypeSection([ 267 '(sub (struct))', 268 '(sub 0 (struct (field i32)))', 269 '(sub (array (ref 0)))', 270 '(sub 2 (array (ref 1)))'])); 271 272 // nullref is a subtype of everything in anyref hierarchy 273 assertSubtype('anyref', 'nullref'); 274 assertSubtype('eqref', 'nullref'); 275 assertSubtype('structref', 'nullref'); 276 assertSubtype('arrayref', 'nullref'); 277 assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(struct)'])); 278 assertSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(array i32)'])); 279 280 // nullref is not a subtype of any other hierarchy 281 assertNotSubtype('funcref', 'nullref'); 282 assertNotSubtype('(ref null 0)', 'nullref', simpleTypeSection(['(func)'])); 283 assertNotSubtype('externref', 'nullref'); 284 285 // nullfuncref is a subtype of everything in funcref hierarchy 286 assertSubtype('funcref', 'nullfuncref'); 287 assertSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(func)'])); 288 289 // nullfuncref is not a subtype of any other hierarchy 290 assertNotSubtype('anyref', 'nullfuncref'); 291 assertNotSubtype('eqref', 'nullfuncref'); 292 assertNotSubtype('structref', 'nullfuncref'); 293 assertNotSubtype('arrayref', 'nullfuncref'); 294 assertNotSubtype('externref', 'nullfuncref'); 295 assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(struct)'])); 296 assertNotSubtype('(ref null 0)', 'nullfuncref', simpleTypeSection(['(array i32)'])); 297 298 // nullexternref is a subtype of everything in externref hierarchy 299 assertSubtype('externref', 'nullexternref'); 300 301 // nullexternref is not a subtype of any other hierarchy 302 assertNotSubtype('anyref', 'nullexternref'); 303 assertNotSubtype('eqref', 'nullexternref'); 304 assertNotSubtype('structref', 'nullexternref'); 305 assertNotSubtype('arrayref', 'nullexternref'); 306 assertNotSubtype('funcref', 'nullexternref'); 307 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(struct)'])); 308 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(array i32)'])); 309 assertNotSubtype('(ref null 0)', 'nullexternref', simpleTypeSection(['(func)']));