From b248254811e656fd053bef51e8dc704cb439ad01 Mon Sep 17 00:00:00 2001 From: dcode Date: Sat, 22 Apr 2023 18:58:58 +0200 Subject: [PATCH] Unify reference types (#2689) --- .github/workflows/test.yml | 2 +- cli/index.js | 4 +- src/builtins.ts | 36 ++-- src/common.ts | 41 +++-- src/compiler.ts | 137 +++++++++----- src/index-wasm.ts | 20 +- src/module.ts | 16 +- src/program.ts | 57 +++--- src/resolver.ts | 6 +- src/types.ts | 171 +++++++++--------- std/assembly/index.d.ts | 74 +++++--- std/assembly/reference.ts | 31 +++- std/assembly/shared/feature.ts | 2 + tests/compiler/bindings/esm.debug.js | 2 +- tests/compiler/bindings/raw.debug.js | 2 +- tests/compiler/features/gc.debug.wat | 2 +- tests/compiler/features/gc.ts | 14 +- .../features/reference-types.debug.wat | 50 +---- .../features/reference-types.release.wat | 2 +- tests/compiler/features/reference-types.ts | 2 - tests/compiler/issues/2473.json | 3 +- tests/compiler/issues/2473.ts | 3 +- tests/features.json | 5 - 23 files changed, 367 insertions(+), 315 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5e46805377..79091199fd 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -74,7 +74,7 @@ jobs: - uses: dcodeIO/setup-node-nvm@master with: node-mirror: https://nodejs.org/download/v8-canary/ - node-version: 19.0.0-v8-canary202209029fc5a9347b + node-version: 21.0.0-v8-canary20230419061e93e884 - name: Install dependencies run: npm ci --no-audit - name: Build diff --git a/cli/index.js b/cli/index.js index 5d92e648e8..91634a8c01 100644 --- a/cli/index.js +++ b/cli/index.js @@ -372,7 +372,7 @@ export async function main(argv, options) { let name = features[i].trim(); let flag = assemblyscript[`FEATURE_${toUpperSnakeCase(name)}`]; if (!flag) return prepareResult(Error(`Feature '${name}' is unknown.`)); - assemblyscript.disableFeature(compilerOptions, flag); + assemblyscript.setFeature(compilerOptions, flag, false); } } @@ -383,7 +383,7 @@ export async function main(argv, options) { let name = features[i].trim(); let flag = assemblyscript[`FEATURE_${toUpperSnakeCase(name)}`]; if (!flag) return prepareResult(Error(`Feature '${name}' is unknown.`)); - assemblyscript.enableFeature(compilerOptions, flag); + assemblyscript.setFeature(compilerOptions, flag, true); } } diff --git a/src/builtins.ts b/src/builtins.ts index 20cf2e044d..492b186600 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -3523,7 +3523,7 @@ function builtin_i31_new(ctx: BuiltinFunctionContext): ExpressionRef { ) return module.unreachable(); let operands = ctx.operands; let arg0 = compiler.compileExpression(operands[0], Type.i32, Constraints.ConvImplicit); - compiler.currentType = Type.i31ref; + compiler.currentType = Type.i31; return module.i31_new(arg0); } builtinFunctions.set(BuiltinNames.i31_new, builtin_i31_new); @@ -3536,7 +3536,7 @@ function builtin_i31_get(ctx: BuiltinFunctionContext): ExpressionRef { checkArgsRequired(ctx, 1) ) return module.unreachable(); let operands = ctx.operands; - let arg0 = compiler.compileExpression(operands[0], Type.i31ref, Constraints.ConvImplicit); + let arg0 = compiler.compileExpression(operands[0], Type.i31.asNullable(), Constraints.ConvImplicit); if (ctx.contextualType.is(TypeFlags.Unsigned)) { compiler.currentType = Type.u32; return module.i31_get(arg0, false); @@ -3653,14 +3653,14 @@ function builtin_assert(ctx: BuiltinFunctionContext): ExpressionRef { // TODO: also check for NaN in float assertions, as in `Boolean(NaN) -> false`? case TypeKind.F32: return module.if(module.binary(BinaryOp.EqF32, arg0, module.f32(0)), abort); case TypeKind.F64: return module.if(module.binary(BinaryOp.EqF64, arg0, module.f64(0)), abort); - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: - case TypeKind.Stringref: + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: + case TypeKind.String: case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: return module.if(module.ref_is_null(arg0), abort); @@ -3734,14 +3734,14 @@ function builtin_assert(ctx: BuiltinFunctionContext): ExpressionRef { ); return ret; } - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: - case TypeKind.Stringref: + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: + case TypeKind.String: case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: { diff --git a/src/common.ts b/src/common.ts index 8e03684d05..f5d6675edd 100644 --- a/src/common.ts +++ b/src/common.ts @@ -81,7 +81,9 @@ export const enum CommonFlags { // Other /** Is quoted. */ - Quoted = 1 << 30 + Quoted = 1 << 30, + /** Is internally nullable. */ + InternallyNullable = 1 << 31 } /** Path delimiter inserted between file system levels. */ @@ -126,17 +128,17 @@ export namespace CommonNames { export const f32 = "f32"; export const f64 = "f64"; export const v128 = "v128"; - export const funcref = "funcref"; - export const externref = "externref"; - export const anyref = "anyref"; - export const eqref = "eqref"; - export const structref = "structref"; - export const arrayref = "arrayref"; - export const i31ref = "i31ref"; - export const stringref = "stringref"; - export const stringview_wtf8 = "stringview_wtf8"; - export const stringview_wtf16 = "stringview_wtf16"; - export const stringview_iter = "stringview_iter"; + export const ref_func = "ref_func"; + export const ref_extern = "ref_extern"; + export const ref_any = "ref_any"; + export const ref_eq = "ref_eq"; + export const ref_struct = "ref_struct"; + export const ref_array = "ref_array"; + export const ref_i31 = "ref_i31"; + export const ref_string = "ref_string"; + export const ref_stringview_wtf8 = "ref_stringview_wtf8"; + export const ref_stringview_wtf16 = "ref_stringview_wtf16"; + export const ref_stringview_iter = "ref_stringview_iter"; export const i8x16 = "i8x16"; export const u8x16 = "u8x16"; export const i16x8 = "i16x8"; @@ -207,13 +209,14 @@ export namespace CommonNames { export const F32 = "F32"; export const F64 = "F64"; export const V128 = "V128"; - export const Funcref = "Funcref"; - export const Externref = "Externref"; - export const Anyref = "Anyref"; - export const Eqref = "Eqref"; - export const Structref = "Structref"; - export const Arrayref = "Arrayref"; - export const I31ref = "I31ref"; + export const RefFunc = "RefFunc"; + export const RefExtern = "RefExtern"; + export const RefAny = "RefAny"; + export const RefEq = "RefEq"; + export const RefStruct = "RefStruct"; + export const RefArray = "RefArray"; + export const RefI31 = "RefI31"; + export const RefString = "RefString"; export const String = "String"; export const RegExp = "RegExp"; export const Object = "Object"; diff --git a/src/compiler.ts b/src/compiler.ts index 25e094503a..7703f5de18 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -221,6 +221,12 @@ import { lowerRequiresExportRuntime } from "./bindings/js"; +/** Features enabled by default. */ +export const defaultFeatures = Feature.MutableGlobals + | Feature.SignExtension + | Feature.NontrappingF2I + | Feature.BulkMemory; + /** Compiler options. */ export class Options { constructor() { /* as internref */ } @@ -261,11 +267,8 @@ export class Options { tableBase: u32 = 0; /** Global aliases, mapping alias names as the key to internal names to be aliased as the value. */ globalAliases: Map | null = null; - /** Features to activate by default. These are the finished proposals. */ - features: Feature = Feature.MutableGlobals - | Feature.SignExtension - | Feature.NontrappingF2I - | Feature.BulkMemory; + /** Features to activate by default. */ + features: Feature = defaultFeatures; /** If true, disallows unsafe features in user code. */ noUnsafe: bool = false; /** If true, enables pedantic diagnostics. */ @@ -317,6 +320,27 @@ export class Options { return this.optimizeLevelHint > 0 || this.shrinkLevelHint > 0; } + /** Sets whether a feature is enabled. */ + setFeature(feature: Feature, on: bool = true): void { + if (on) { + // Enabling Stringref also enables GC + if (feature & Feature.Stringref) feature |= Feature.GC; + // Enabling GC also enables Reference Types + if (feature & Feature.GC) feature |= Feature.ReferenceTypes; + // Enabling Relaxed SIMD also enables SIMD + if (feature & Feature.RelaxedSimd) feature |= Feature.Simd; + this.features |= feature; + } else { + // Disabling Reference Types also disables GC + if (feature & Feature.ReferenceTypes) feature |= Feature.GC; + // Disabling GC also disables Stringref + if (feature & Feature.GC) feature |= Feature.Stringref; + // Disabling SIMD also disables Relaxed SIMD + if (feature & Feature.Simd) feature |= Feature.RelaxedSimd; + this.features &= ~feature; + } + } + /** Tests if a specific feature is activated. */ hasFeature(feature: Feature): bool { return (this.features & feature) != 0; @@ -1357,7 +1381,14 @@ export class Compiler extends DiagnosticEmitter { findDecorator(DecoratorKind.Inline, global.decoratorNodes)!.range, "inline" ); } - module.addGlobal(internalName, typeRef, true, this.makeZero(type)); + let internalType = type; + if (type.isExternalReference && !type.is(TypeFlags.Nullable)) { + // There is no default value for non-nullable external references, so + // make the global nullable internally and use `null`. + global.set(CommonFlags.InternallyNullable); + internalType = type.asNullable(); + } + module.addGlobal(internalName, internalType.toRef(), true, this.makeZero(internalType)); this.currentBody.push( module.global_set(internalName, initExpr) ); @@ -1757,7 +1788,7 @@ export class Compiler extends DiagnosticEmitter { // Implicitly return `this` if the flow falls through if (!flow.is(FlowFlags.Terminates)) { stmts.push( - module.local_get(thisLocal.index, this.options.sizeTypeRef) + module.local_get(thisLocal.index, thisLocal.type.toRef()) ); flow.set(FlowFlags.Returns | FlowFlags.ReturnsNonNull | FlowFlags.Terminates); } @@ -4854,17 +4885,17 @@ export class Compiler extends DiagnosticEmitter { module.binary(BinaryOp.EqI8x16, leftExpr, rightExpr) ); } - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: return module.ref_eq(leftExpr, rightExpr); - case TypeKind.Stringref: return module.string_eq(leftExpr, rightExpr); + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: return module.ref_eq(leftExpr, rightExpr); + case TypeKind.String: return module.string_eq(leftExpr, rightExpr); case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: { + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: { this.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, reportNode.range, @@ -4904,15 +4935,15 @@ export class Compiler extends DiagnosticEmitter { module.binary(BinaryOp.NeI8x16, leftExpr, rightExpr) ); } - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: { + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: { return module.unary(UnaryOp.EqzI32, module.ref_eq(leftExpr, rightExpr) ); } - case TypeKind.Stringref: { + case TypeKind.String: { return module.unary(UnaryOp.EqzI32, module.string_eq(leftExpr, rightExpr) ); @@ -4920,9 +4951,9 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: { + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: { this.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, reportNode.range, @@ -7332,10 +7363,12 @@ export class Compiler extends DiagnosticEmitter { ); } assert(localIndex >= 0); - if (localType.isNullableReference && flow.isLocalFlag(localIndex, LocalFlags.NonNull, false)) { - localType = localType.nonNullableType; + let isNonNull = flow.isLocalFlag(localIndex, LocalFlags.NonNull, false); + if (localType.isNullableReference && isNonNull && (!localType.isExternalReference || this.options.hasFeature(Feature.GC))) { + this.currentType = localType.nonNullableType; + } else { + this.currentType = localType; } - this.currentType = localType; if (target.parent != flow.targetFunction) { // TODO: closures @@ -7346,7 +7379,14 @@ export class Compiler extends DiagnosticEmitter { ); return module.unreachable(); } - return module.local_get(localIndex, localType.toRef()); + let expr = module.local_get(localIndex, localType.toRef()); + if (isNonNull && localType.isNullableExternalReference && this.options.hasFeature(Feature.GC)) { + // If the local's type is nullable, but its value is known to be non-null, propagate + // non-nullability info to Binaryen. Only applicable if GC is enabled, since without + // GC, here incl. typed function references, there is no nullability dimension. + expr = module.ref_as_nonnull(expr); + } + return expr; } case ElementKind.Global: { let global = target; @@ -7424,7 +7464,7 @@ export class Compiler extends DiagnosticEmitter { // TODO: Concrete function types currently map to first class functions implemented in // linear memory (on top of `usize`), leaving only generic `funcref` for use here. In the // future, once functions become Wasm GC objects, the actual signature type can be used. - this.currentType = Type.funcref; + this.currentType = Type.func; return module.ref_func(functionInstance.internalName, ensureType(functionInstance.type)); } let offset = this.ensureRuntimeFunction(functionInstance); @@ -9897,20 +9937,21 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.F32: return module.f32(0); case TypeKind.F64: return module.f64(0); case TypeKind.V128: return module.v128(v128_zero); - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.Stringref: + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.String: case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: { - // TODO: what if not nullable? - return module.ref_null(type.toRef()); + if (type.is(TypeFlags.Nullable)) return module.ref_null(type.toRef()); + assert(false); // TODO: check that refs are nullable in callers? + return module.unreachable(); } - case TypeKind.I31ref: { + case TypeKind.I31: { if (type.is(TypeFlags.Nullable)) return module.ref_null(type.toRef()); return module.i31_new(module.i32(0)); } @@ -9935,7 +9976,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.U64: return module.i64(1); case TypeKind.F32: return module.f32(1); case TypeKind.F64: return module.f64(1); - case TypeKind.I31ref: return module.i31_new(module.i32(1)); + case TypeKind.I31: return module.i31_new(module.i32(1)); } } @@ -9957,7 +9998,7 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.F32: return module.f32(-1); case TypeKind.F64: return module.f64(-1); case TypeKind.V128: return module.v128(v128_ones); - case TypeKind.I31ref: return module.i31_new(module.i32(-1)); + case TypeKind.I31: return module.i31_new(module.i32(-1)); } } @@ -10056,14 +10097,14 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.V128: { return module.unary(UnaryOp.AnyTrueV128, expr); } - case TypeKind.Funcref: - case TypeKind.Externref: - case TypeKind.Anyref: - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: - case TypeKind.Stringref: + case TypeKind.Func: + case TypeKind.Extern: + case TypeKind.Any: + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: + case TypeKind.String: case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: { diff --git a/src/index-wasm.ts b/src/index-wasm.ts index a43202657d..ec51de73da 100644 --- a/src/index-wasm.ts +++ b/src/index-wasm.ts @@ -23,7 +23,8 @@ import { import { Compiler, Options, - UncheckedBehavior + UncheckedBehavior, + defaultFeatures } from "./compiler"; import { @@ -201,15 +202,14 @@ export const FEATURE_RELAXED_SIMD = Feature.RelaxedSimd; export const FEATURE_EXTENDED_CONST = Feature.ExtendedConst; /** String references. */ export const FEATURE_STRINGREF = Feature.Stringref; - -/** Enables a specific feature. */ -export function enableFeature(options: Options, feature: Feature): void { - options.features |= feature; -} - -/** Disables a specific feature. */ -export function disableFeature(options: Options, feature: Feature): void { - options.features &= ~feature; +/** All features. */ +export const FEATURES_ALL = Feature.All; +/** Default features. */ +export const FEATURES_DEFAULT = defaultFeatures; + +/** Sets whether a specific feature is enabled. */ +export function setFeature(options: Options, feature: Feature, on: bool): void { + options.setFeature(feature, on); } /** Gives the compiler a hint at the optimize levels that will be used later on. */ diff --git a/src/module.ts b/src/module.ts index 6c9d527cb0..705750ec4a 100644 --- a/src/module.ts +++ b/src/module.ts @@ -3790,28 +3790,28 @@ function tryEnsureBasicType(type: Type): TypeRef { case TypeKind.F32: return TypeRef.F32; case TypeKind.F64: return TypeRef.F64; case TypeKind.V128: return TypeRef.V128; - case TypeKind.Funcref: { + case TypeKind.Func: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Func, type.is(TypeFlags.Nullable)); } - case TypeKind.Externref: { + case TypeKind.Extern: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Extern, type.is(TypeFlags.Nullable)); } - case TypeKind.Anyref: { + case TypeKind.Any: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Any, type.is(TypeFlags.Nullable)); } - case TypeKind.Eqref: { + case TypeKind.Eq: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Eq, type.is(TypeFlags.Nullable)); } - case TypeKind.Structref: { + case TypeKind.Struct: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Struct, type.is(TypeFlags.Nullable)); } - case TypeKind.Arrayref: { + case TypeKind.Array: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Array, type.is(TypeFlags.Nullable)); } - case TypeKind.I31ref: { + case TypeKind.I31: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.I31, type.is(TypeFlags.Nullable)); } - case TypeKind.Stringref: { + case TypeKind.String: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.String, type.is(TypeFlags.Nullable)); } case TypeKind.StringviewWTF8: { diff --git a/src/program.ts b/src/program.ts index 18ebd57a6d..829cffee05 100644 --- a/src/program.ts +++ b/src/program.ts @@ -1014,17 +1014,17 @@ export class Program extends DiagnosticEmitter { // compiler needs to check this condition whenever such a value is created // respectively stored or loaded. this.registerNativeType(CommonNames.v128, Type.v128); - this.registerNativeType(CommonNames.funcref, Type.funcref); - this.registerNativeType(CommonNames.externref, Type.externref); - this.registerNativeType(CommonNames.anyref, Type.anyref); - this.registerNativeType(CommonNames.eqref, Type.eqref); - this.registerNativeType(CommonNames.structref, Type.structref); - this.registerNativeType(CommonNames.arrayref, Type.arrayref); - this.registerNativeType(CommonNames.i31ref, Type.i31ref); - this.registerNativeType(CommonNames.stringref, Type.stringref); - this.registerNativeType(CommonNames.stringview_wtf8, Type.stringview_wtf8); - this.registerNativeType(CommonNames.stringview_wtf16, Type.stringview_wtf16); - this.registerNativeType(CommonNames.stringview_iter, Type.stringview_iter); + this.registerNativeType(CommonNames.ref_func, Type.func); + this.registerNativeType(CommonNames.ref_extern, Type.extern); + this.registerNativeType(CommonNames.ref_any, Type.any); + this.registerNativeType(CommonNames.ref_eq, Type.eq); + this.registerNativeType(CommonNames.ref_struct, Type.struct); + this.registerNativeType(CommonNames.ref_array, Type.array); + this.registerNativeType(CommonNames.ref_i31, Type.i31); + this.registerNativeType(CommonNames.ref_string, Type.string); + this.registerNativeType(CommonNames.ref_stringview_wtf8, Type.stringview_wtf8); + this.registerNativeType(CommonNames.ref_stringview_wtf16, Type.stringview_wtf16); + this.registerNativeType(CommonNames.ref_stringview_iter, Type.stringview_iter); // register compiler hints this.registerConstantInteger(CommonNames.ASC_TARGET, Type.i32, @@ -1288,14 +1288,17 @@ export class Program extends DiagnosticEmitter { this.registerWrapperClass(Type.f64, CommonNames.F64); if (options.hasFeature(Feature.Simd)) this.registerWrapperClass(Type.v128, CommonNames.V128); if (options.hasFeature(Feature.ReferenceTypes)) { - this.registerWrapperClass(Type.funcref, CommonNames.Funcref); - this.registerWrapperClass(Type.externref, CommonNames.Externref); + this.registerWrapperClass(Type.func, CommonNames.RefFunc); + this.registerWrapperClass(Type.extern, CommonNames.RefExtern); if (options.hasFeature(Feature.GC)) { - this.registerWrapperClass(Type.anyref, CommonNames.Anyref); - this.registerWrapperClass(Type.eqref, CommonNames.Eqref); - this.registerWrapperClass(Type.structref, CommonNames.Structref); - this.registerWrapperClass(Type.arrayref, CommonNames.Arrayref); - this.registerWrapperClass(Type.i31ref, CommonNames.I31ref); + this.registerWrapperClass(Type.any, CommonNames.RefAny); + this.registerWrapperClass(Type.eq, CommonNames.RefEq); + this.registerWrapperClass(Type.struct, CommonNames.RefStruct); + this.registerWrapperClass(Type.array, CommonNames.RefArray); + this.registerWrapperClass(Type.i31, CommonNames.RefI31); + } + if (options.hasFeature(Feature.Stringref)) { + this.registerWrapperClass(Type.string, CommonNames.RefString); } } @@ -1950,18 +1953,20 @@ export class Program extends DiagnosticEmitter { checkTypeSupported(type: Type, reportNode: Node): bool { switch (type.kind) { case TypeKind.V128: return this.checkFeatureEnabled(Feature.Simd, reportNode); - case TypeKind.Funcref: - case TypeKind.Externref: + case TypeKind.Func: + case TypeKind.Extern: + // Non-nullability is introduced by typed function references (here part of GC) + if (!type.is(TypeFlags.Nullable)) return this.checkFeatureEnabled(Feature.GC, reportNode); return this.checkFeatureEnabled(Feature.ReferenceTypes, reportNode); - case TypeKind.Anyref: - case TypeKind.Eqref: - case TypeKind.Structref: - case TypeKind.Arrayref: - case TypeKind.I31ref: { + case TypeKind.Any: + case TypeKind.Eq: + case TypeKind.Struct: + case TypeKind.Array: + case TypeKind.I31: { return this.checkFeatureEnabled(Feature.ReferenceTypes, reportNode) && this.checkFeatureEnabled(Feature.GC, reportNode); } - case TypeKind.Stringref: + case TypeKind.String: case TypeKind.StringviewWTF8: case TypeKind.StringviewWTF16: case TypeKind.StringviewIter: { diff --git a/src/resolver.ts b/src/resolver.ts index c54f555993..16bd967847 100644 --- a/src/resolver.ts +++ b/src/resolver.ts @@ -212,7 +212,7 @@ export class Resolver extends DiagnosticEmitter { } } if (node.isNullable) { - if (type.isInternalReference) return type.asNullable(); + if (type.isReference) return type.asNullable(); if (reportMode == ReportMode.Report) { this.error( DiagnosticCode.Type_0_cannot_be_nullable, @@ -290,7 +290,7 @@ export class Resolver extends DiagnosticEmitter { } let type = typeDefinition.type; if (node.isNullable) { - if (type.isInternalReference) return type.asNullable(); + if (type.isReference) return type.asNullable(); if (reportMode == ReportMode.Report) { this.error( DiagnosticCode.Type_0_cannot_be_nullable, @@ -338,7 +338,7 @@ export class Resolver extends DiagnosticEmitter { ); if (!type) return null; if (node.isNullable) { - if (type.isInternalReference) return type.asNullable(); + if (type.isReference) return type.asNullable(); if (reportMode == ReportMode.Report) { this.error( DiagnosticCode.Type_0_cannot_be_nullable, diff --git a/src/types.ts b/src/types.ts index cf97538bf6..4aef00a5b2 100644 --- a/src/types.ts +++ b/src/types.ts @@ -68,21 +68,21 @@ export const enum TypeKind { // references (keep in same order as in Binaryen) /** External reference. */ - Externref, + Extern, /** Function reference. */ - Funcref, + Func, /** Any reference. */ - Anyref, + Any, /** Equatable reference. */ - Eqref, + Eq, /** Struct reference. */ - Structref, + Struct, /** Array reference. */ - Arrayref, + Array, /** 31-bit integer reference. */ - I31ref, + I31, /** String reference. */ - Stringref, + String, /** WTF8 string view. */ StringviewWTF8, /** WTF16 string view. */ @@ -278,6 +278,11 @@ export class Type { return this.is(TypeFlags.External | TypeFlags.Reference); } + /** Tests if this type represents a nullable external object. */ + get isNullableExternalReference(): bool { + return this.is(TypeFlags.Nullable | TypeFlags.External | TypeFlags.Reference); + } + /** Gets the underlying class of this type, if any. */ getClass(): Class | null { return this.isInternalReference @@ -365,15 +370,15 @@ export class Type { /** Gets the corresponding non-nullable type. */ get nonNullableType(): Type { - if (this.isExternalReference) { - return this; // TODO - } - return assert(this._nonNullableType); // set either in ctor or asNullable + // Every type has a corresponding non-nullable type + return assert(this._nonNullableType); } /** Gets the corresponding nullable type, if applicable. */ get nullableType(): Type | null { - return this._nullableType; // set either in ctor or asNullable + return this.isReference + ? this.asNullable() // Every reference type has a corresponding nullable type + : null; // Other types do not have a nullable type } /** Computes the sign-extending shift in the target type. */ @@ -395,13 +400,13 @@ export class Type { /** Composes the respective nullable type of this type. */ asNullable(): Type { - assert(this.isInternalReference); + assert(this.isReference); let nullableType = this._nullableType; if (!nullableType) { assert(!this.isNullableReference); this._nullableType = nullableType = new Type(this.kind, this.flags | TypeFlags.Nullable, this.size); - nullableType.classReference = this.classReference; // either a class reference - nullableType.signatureReference = this.signatureReference; // or a function reference + nullableType.classReference = this.classReference; + nullableType.signatureReference = this.signatureReference; nullableType._nonNullableType = this; } return nullableType; @@ -457,7 +462,7 @@ export class Type { } else if (this.isExternalReference) { if ( this.kind == target.kind || - (target.kind == TypeKind.Anyref && this.kind != TypeKind.Externref) + (target.kind == TypeKind.Any && this.kind != TypeKind.Extern) ) { return true; } @@ -583,24 +588,8 @@ export class Type { return null; } - /** Converts this type to a string. */ - toString(validWat: bool = false): string { - const nullablePostfix = validWat ? "|null" : " | null"; - if (this.isReference) { - let classReference = this.getClass(); - if (classReference) { - return this.isNullableReference - ? classReference.internalName + nullablePostfix - : classReference.internalName; - } else { - let signatureReference = this.getSignature(); - if (signatureReference) { - return this.isNullableReference - ? `(${signatureReference.toString(validWat)})${nullablePostfix}` - : signatureReference.toString(validWat); - } - } - } + /** Converts this type's kind to a string. */ + kindToString(): string { switch (this.kind) { case TypeKind.Bool: return CommonNames.bool; case TypeKind.I8: return CommonNames.i8; @@ -616,22 +605,47 @@ export class Type { case TypeKind.F32: return CommonNames.f32; case TypeKind.F64: return CommonNames.f64; case TypeKind.V128: return CommonNames.v128; - case TypeKind.Funcref: return CommonNames.funcref; - case TypeKind.Externref: return CommonNames.externref; - case TypeKind.Anyref: return CommonNames.anyref; - case TypeKind.Eqref: return CommonNames.eqref; - case TypeKind.Structref: return CommonNames.structref; - case TypeKind.Arrayref: return CommonNames.arrayref; - case TypeKind.I31ref: return CommonNames.i31ref; - case TypeKind.Stringref: return CommonNames.stringref; - case TypeKind.StringviewWTF8: return CommonNames.stringview_wtf8; - case TypeKind.StringviewWTF16: return CommonNames.stringview_wtf16; - case TypeKind.StringviewIter: return CommonNames.stringview_iter; + case TypeKind.Func: return CommonNames.ref_func; + case TypeKind.Extern: return CommonNames.ref_extern; + case TypeKind.Any: return CommonNames.ref_any; + case TypeKind.Eq: return CommonNames.ref_eq; + case TypeKind.Struct: return CommonNames.ref_struct; + case TypeKind.Array: return CommonNames.ref_array; + case TypeKind.I31: return CommonNames.ref_i31; + case TypeKind.String: return CommonNames.ref_string; + case TypeKind.StringviewWTF8: return CommonNames.ref_stringview_wtf8; + case TypeKind.StringviewWTF16: return CommonNames.ref_stringview_wtf16; + case TypeKind.StringviewIter: return CommonNames.ref_stringview_iter; default: assert(false); case TypeKind.Void: return CommonNames.void_; } } + /** Converts this type to a string. */ + toString(validWat: bool = false): string { + const nullablePostfix = validWat ? "|null" : " | null"; + if (this.isReference) { + let classReference = this.getClass(); + if (classReference) { + return this.isNullableReference + ? classReference.internalName + nullablePostfix + : classReference.internalName; + } else { + let signatureReference = this.getSignature(); + if (signatureReference) { + return this.isNullableReference + ? `(${signatureReference.toString(validWat)})${nullablePostfix}` + : signatureReference.toString(validWat); + } else { + return this.isNullableReference + ? `${this.kindToString()}${nullablePostfix}}` + : this.kindToString(); + } + } + } + return this.kindToString(); + } + // Binaryen specific /** Converts this type to its respective type reference. */ @@ -651,28 +665,28 @@ export class Type { case TypeKind.F32: return TypeRef.F32; case TypeKind.F64: return TypeRef.F64; case TypeKind.V128: return TypeRef.V128; - case TypeKind.Funcref: { + case TypeKind.Func: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Func, this.is(TypeFlags.Nullable)); } - case TypeKind.Externref: { + case TypeKind.Extern: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Extern, this.is(TypeFlags.Nullable)); } - case TypeKind.Anyref: { + case TypeKind.Any: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Any, this.is(TypeFlags.Nullable)); } - case TypeKind.Eqref: { + case TypeKind.Eq: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Eq, this.is(TypeFlags.Nullable)); } - case TypeKind.Structref: { + case TypeKind.Struct: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Struct, this.is(TypeFlags.Nullable)); } - case TypeKind.Arrayref: { + case TypeKind.Array: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Array, this.is(TypeFlags.Nullable)); } - case TypeKind.I31ref: { + case TypeKind.I31: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.I31, this.is(TypeFlags.Nullable)); } - case TypeKind.Stringref: { + case TypeKind.String: { return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.String, this.is(TypeFlags.Nullable)); } case TypeKind.StringviewWTF8: { @@ -818,80 +832,69 @@ export class Type { TypeFlags.Value, 128 ); - /** Function reference. */ - static readonly funcref: Type = new Type(TypeKind.Funcref, + /** Non-nullable function reference (`ref func`). */ + static readonly func: Type = new Type(TypeKind.Func, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** External reference. */ - static readonly externref: Type = new Type(TypeKind.Externref, + /** Non-nullable external reference (`ref extern`). */ + static readonly extern: Type = new Type(TypeKind.Extern, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** Any reference. */ - static readonly anyref: Type = new Type(TypeKind.Anyref, + /** Non-nullable any reference (`ref any`). */ + static readonly any: Type = new Type(TypeKind.Any, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** Equatable reference. */ - static readonly eqref: Type = new Type(TypeKind.Eqref, + /** Non-nullable equatable reference (`ref eq`). */ + static readonly eq: Type = new Type(TypeKind.Eq, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** Struct reference. */ - static readonly structref: Type = new Type(TypeKind.Structref, + /** Non-nullable struct reference (`ref struct`). */ + static readonly struct: Type = new Type(TypeKind.Struct, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** Array reference. */ - static readonly arrayref: Type = new Type(TypeKind.Arrayref, + /** Non-nullable array reference (`ref array`). */ + static readonly array: Type = new Type(TypeKind.Array, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** 31-bit integer reference. */ - static readonly i31ref: Type = new Type(TypeKind.I31ref, + /** Non-nullable 31-bit integer reference (`ref i31`). */ + static readonly i31: Type = new Type(TypeKind.I31, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** String reference. */ - static readonly stringref: Type = new Type(TypeKind.Stringref, + /** Non-nullable string reference (`ref string`). */ + static readonly string: Type = new Type(TypeKind.String, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** WTF8 string view. */ + /** Non-nullable WTF8 string view reference (`ref stringview_wtf8`). */ static readonly stringview_wtf8: Type = new Type(TypeKind.StringviewWTF8, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** WTF16 string view. */ + /** Non-nullable WTF16 string view reference (`ref stringview_wtf16`). */ static readonly stringview_wtf16: Type = new Type(TypeKind.StringviewWTF16, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); - /** String iterator. */ + /** Non-nullable string iterator reference (`ref stringview_iter`). */ static readonly stringview_iter: Type = new Type(TypeKind.StringviewIter, TypeFlags.External | - TypeFlags.Nullable | TypeFlags.Reference, 0 ); diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index 13e59d0886..cbba3592aa 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -35,28 +35,50 @@ declare type f32 = number; declare type f64 = number; /** A 128-bit vector. */ declare type v128 = object; -/** Function reference. */ -declare type funcref = object | null; -/** External reference. */ -declare type externref = object | null; -/** Any reference. */ -declare type anyref = object | null; -/** Equatable reference. */ -declare type eqref = object | null; -/** Struct reference. */ -declare type structref = object | null; -/** Array reference. */ -declare type arrayref = object | null; -/** 31-bit integer reference. */ -declare type i31ref = object | null; -/** String reference. */ -declare type stringref = object | null; -/** WTF-8 string view. */ -declare type stringview_wtf8 = object | null; -/** WTF-16 string view. */ -declare type stringview_wtf16 = object | null; -/** String iterator. */ -declare type stringview_iter = object | null; +/** Non-nullable function reference. */ +declare type ref_func = object; +/** Canonical nullable function reference. */ +declare type funcref = ref_func | null; +/** Non-nullable external reference. */ +declare type ref_extern = object; +/** Canonical nullable external reference. */ +declare type externref = ref_extern | null; +/** Non-nullable any reference. */ +declare type ref_any = object; +/** Canonical nullable any reference. */ +declare type anyref = ref_any | null; +/** Non-nullable equatable reference. */ +declare type ref_eq = object; +/** Canonical nullable equatable reference. */ +declare type eqref = ref_eq | null; +/** Non-nullable struct reference. */ +declare type ref_struct = object; +/** Canonical nullable struct reference. */ +declare type structref = ref_struct | null; +/** Non-nullable array reference. */ +declare type ref_array = object; +/** Canonical nullable array reference. */ +declare type arrayref = ref_array | null; +/** Non-nullable 31-bit integer reference. */ +declare type ref_i31 = object; +/** Canonical nullable 31-bit integer reference. */ +declare type i31ref = ref_i31 | null; +/** Non-nullable string reference. */ +declare type ref_string = object; +/** Canonical nullable string reference. */ +declare type stringref = ref_string | null; +/** Non-nullable WTF-8 string view. */ +declare type ref_stringview_wtf8 = object; +/** Canonical nullable WTF-8 string view. */ +declare type stringview_wtf8 = ref_stringview_wtf8 | null; +/** Non-nullable WTF-16 string view. */ +declare type ref_stringview_wtf16 = object; +/** Canonical nullable WTF-16 string view. */ +declare type stringview_wtf16 = ref_stringview_wtf16 | null; +/** Non-nullable string iterator. */ +declare type ref_stringview_iter = object; +/** Canonical nullable string iterator. */ +declare type stringview_iter = ref_stringview_iter | null; // Compiler hints @@ -1640,10 +1662,10 @@ declare namespace f64x2 { } declare abstract class i31 { - /** Creates a new i31ref from the specified integer value. */ - static new(value: i32): i31ref; - /** Gets the integer value of an i31ref. */ - static get(i31expr: i31ref): i32; + /** Creates a new 31-bit integer reference from the specified integer value. */ + static new(value: i32): ref_i31; + /** Gets the integer value of an 31-bit integer reference. */ + static get(i31expr: ref_i31 | null): i32; } /** Macro type evaluating to the underlying native WebAssembly type. */ diff --git a/std/assembly/reference.ts b/std/assembly/reference.ts index 1c7b85cb13..148f456799 100644 --- a/std/assembly/reference.ts +++ b/std/assembly/reference.ts @@ -1,31 +1,48 @@ +// Canonical aliases +export type funcref = ref_func | null; +export type externref = ref_extern | null; +export type anyref = ref_any | null; +export type eqref = ref_eq | null; +export type i31ref = ref_i31 | null; +export type structref = ref_struct | null; +export type arrayref = ref_array | null; +export type stringref = ref_string | null; +export type stringview_wtf8 = ref_stringview_wtf8 | null; +export type stringview_wtf16 = ref_stringview_wtf16 | null; +export type stringview_iter = ref_stringview_iter | null; + @unmanaged abstract class Ref { } @final @unmanaged -export abstract class Funcref extends Ref { +export abstract class RefFunc extends Ref { +} + +@final @unmanaged +export abstract class RefExtern extends Ref { } @final @unmanaged -export abstract class Externref extends Ref { +export abstract class RefAny extends Ref { } @final @unmanaged -export abstract class Anyref extends Ref { +export abstract class RefEq extends Ref { } @final @unmanaged -export abstract class Eqref extends Ref { +export abstract class RefI31 extends Ref { } @final @unmanaged -export abstract class I31ref extends Ref { +export abstract class RefStruct extends Ref { } @final @unmanaged -export abstract class Structref extends Ref { +export abstract class RefArray extends Ref { } @final @unmanaged -export abstract class Arrayref extends Ref { +export abstract class RefString extends Ref { } diff --git a/std/assembly/shared/feature.ts b/std/assembly/shared/feature.ts index 19027742ed..1baa9ba3c9 100644 --- a/std/assembly/shared/feature.ts +++ b/std/assembly/shared/feature.ts @@ -34,6 +34,8 @@ export const enum Feature { ExtendedConst = 1 << 13, // see: https://github.com/WebAssembly/extended-const /** Reference typed strings. */ Stringref = 1 << 14, // see: https://github.com/WebAssembly/stringref + /** All features. */ + All = (1 << 15) - 1 } /** Gets the name of the specified feature one would specify on the command line. */ diff --git a/tests/compiler/bindings/esm.debug.js b/tests/compiler/bindings/esm.debug.js index 9fa680f811..9503ad5efb 100644 --- a/tests/compiler/bindings/esm.debug.js +++ b/tests/compiler/bindings/esm.debug.js @@ -23,7 +23,7 @@ async function instantiate(module, imports = {}) { Math.log ), "globalThis.globalThis": ( - // bindings/esm/immutableGlobalNested: externref + // bindings/esm/immutableGlobalNested: ref_extern | null} globalThis.globalThis ), "Date.getTimezoneOffset"() { diff --git a/tests/compiler/bindings/raw.debug.js b/tests/compiler/bindings/raw.debug.js index 06002860de..62227b542a 100644 --- a/tests/compiler/bindings/raw.debug.js +++ b/tests/compiler/bindings/raw.debug.js @@ -23,7 +23,7 @@ export async function instantiate(module, imports = {}) { Math.log ), "globalThis.globalThis": ( - // bindings/esm/immutableGlobalNested: externref + // bindings/esm/immutableGlobalNested: ref_extern | null} globalThis.globalThis ), "Date.getTimezoneOffset"() { diff --git a/tests/compiler/features/gc.debug.wat b/tests/compiler/features/gc.debug.wat index aa417e8f8a..51c77b6e32 100644 --- a/tests/compiler/features/gc.debug.wat +++ b/tests/compiler/features/gc.debug.wat @@ -27,7 +27,7 @@ (export "memory" (memory $0)) (export "_start" (func $~start)) (func $features/gc/test_i31 (type $none_=>_none) - (local $ref i31ref) + (local $ref (ref i31)) (local $val i32) (local $uval i32) i32.const 123 diff --git a/tests/compiler/features/gc.ts b/tests/compiler/features/gc.ts index 496e13d321..a21093b929 100644 --- a/tests/compiler/features/gc.ts +++ b/tests/compiler/features/gc.ts @@ -9,10 +9,10 @@ test_i31(); // constant globals -export const globalFunc: funcref = null; -export const globalExtern: externref = null; -export const globalAny: anyref = null; -export const globalEq: eqref = null; -export const globalI31: i31ref = null; -export const globalStruct: structref = null; -export const globalArray: arrayref = null; +export const globalFunc: ref_func | null = null; +export const globalExtern: ref_extern | null = null; +export const globalAny: ref_any | null = null; +export const globalEq: ref_eq | null = null; +export const globalI31: ref_i31 | null = null; +export const globalStruct: ref_struct | null = null; +export const globalArray: ref_array | null = null; diff --git a/tests/compiler/features/reference-types.debug.wat b/tests/compiler/features/reference-types.debug.wat index ebf7181563..d7dfc388c9 100644 --- a/tests/compiler/features/reference-types.debug.wat +++ b/tests/compiler/features/reference-types.debug.wat @@ -35,9 +35,8 @@ (export "nonNullReal" (global $features/reference-types/nonNullReal)) (export "memory" (memory $0)) (start $~start) - (func $features/reference-types/testLocal + (func $features/reference-types/testLocal (local $local funcref) - (local $localInit funcref) ref.null nofunc local.set $local local.get $local @@ -68,25 +67,9 @@ call $~lib/builtins/abort unreachable end - ref.null nofunc - local.set $localInit - local.get $localInit - ref.is_null - i32.eqz - i32.eqz - i32.eqz - if - i32.const 0 - i32.const 32 - i32.const 74 - i32.const 3 - call $~lib/builtins/abort - unreachable - end ) - (func $features/reference-types/testLocal + (func $features/reference-types/testLocal (local $local externref) - (local $localInit externref) ref.null noextern local.set $local local.get $local @@ -117,21 +100,6 @@ call $~lib/builtins/abort unreachable end - ref.null noextern - local.set $localInit - local.get $localInit - ref.is_null - i32.eqz - i32.eqz - i32.eqz - if - i32.const 0 - i32.const 32 - i32.const 74 - i32.const 3 - call $~lib/builtins/abort - unreachable - end ) (func $features/reference-types/someFunc nop @@ -288,8 +256,8 @@ call $~lib/builtins/abort unreachable end - call $features/reference-types/testLocal - call $features/reference-types/testLocal + call $features/reference-types/testLocal + call $features/reference-types/testLocal ref.func $features/reference-types/someFunc global.set $features/reference-types/funcGlobal global.get $features/reference-types/funcGlobal @@ -297,7 +265,7 @@ if i32.const 0 i32.const 32 - i32.const 83 + i32.const 81 i32.const 1 call $~lib/builtins/abort unreachable @@ -307,7 +275,7 @@ if i32.const 0 i32.const 32 - i32.const 85 + i32.const 83 i32.const 1 call $~lib/builtins/abort unreachable @@ -319,7 +287,7 @@ if i32.const 0 i32.const 32 - i32.const 88 + i32.const 86 i32.const 3 call $~lib/builtins/abort unreachable @@ -330,7 +298,7 @@ if (result funcref) i32.const 112 i32.const 32 - i32.const 97 + i32.const 95 i32.const 28 call $~lib/builtins/abort unreachable @@ -344,7 +312,7 @@ if (result externref) i32.const 112 i32.const 32 - i32.const 98 + i32.const 96 i32.const 28 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/features/reference-types.release.wat b/tests/compiler/features/reference-types.release.wat index c4a49f0622..02b8dd6151 100644 --- a/tests/compiler/features/reference-types.release.wat +++ b/tests/compiler/features/reference-types.release.wat @@ -104,7 +104,7 @@ if i32.const 1136 i32.const 1056 - i32.const 98 + i32.const 96 i32.const 28 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/features/reference-types.ts b/tests/compiler/features/reference-types.ts index 816c844c4d..050c9f1e3d 100644 --- a/tests/compiler/features/reference-types.ts +++ b/tests/compiler/features/reference-types.ts @@ -70,8 +70,6 @@ function testLocal(): void { assert(!local); local = null; assert(!local); - let localInit: T = null; - assert(!localInit); } testLocal(); testLocal(); diff --git a/tests/compiler/issues/2473.json b/tests/compiler/issues/2473.json index aafce99bbb..69747d89e4 100644 --- a/tests/compiler/issues/2473.json +++ b/tests/compiler/issues/2473.json @@ -7,8 +7,7 @@ "TS1345: An expression of type 'void' cannot be tested for truthiness.", "AS203: Operation 'store' cannot be applied to type 'void'.", "AS203: Operation 'load' cannot be applied to type 'void'.", - "AS203: Operation 'load' cannot be applied to type 'externref'.", - "AS203: Operation 'load' cannot be applied to type 'anyref'", + "AS203: Operation 'load' cannot be applied to type 'ref_extern'.", "EOF" ] } diff --git a/tests/compiler/issues/2473.ts b/tests/compiler/issues/2473.ts index 7d3d645a9f..6eb0af60fe 100644 --- a/tests/compiler/issues/2473.ts +++ b/tests/compiler/issues/2473.ts @@ -11,7 +11,6 @@ if (voidFn()) {} store(8, voidFn()); load(8); -load(8); -load(8); +load(8); ERROR("EOF"); diff --git a/tests/features.json b/tests/features.json index 4ba0c0b4c5..5c47772500 100644 --- a/tests/features.json +++ b/tests/features.json @@ -12,16 +12,13 @@ "--enable reference-types" ], "v8_flags": [ - "--experimental-wasm-reftypes" ] }, "gc": { "asc_flags": [ - "--enable reference-types", "--enable gc" ], "v8_flags": [ - "--experimental-wasm-reftypes", "--experimental-wasm-gc" ] }, @@ -30,7 +27,6 @@ "--enable exception-handling" ], "v8_flags": [ - "--experimental-wasm-eh" ] }, "simd": { @@ -38,7 +34,6 @@ "--enable simd" ], "v8_flags": [ - "--experimental-wasm-simd" ] }, "relaxed-simd": {