diff --git a/src/builtins.ts b/src/builtins.ts index dc61f365c0..0b91345de7 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2286,12 +2286,23 @@ function builtin_load(ctx: BuiltinContext): ExpressionRef { var typeArguments = ctx.typeArguments; var contextualType = ctx.contextualType; var type = typeArguments![0]; + var outType = ( contextualType != Type.auto && type.isIntegerValue && contextualType.isIntegerValue && contextualType.size > type.size ) ? contextualType : type; + + if (!outType.isMemory) { + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + ctx.reportNode.typeArgumentsRange, "load", outType.toString() + ); + compiler.currentType = Type.void; + return module.unreachable(); + } + var arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT); var numOperands = operands.length; var immOffset = 0; @@ -2350,6 +2361,14 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef { : Constraints.CONV_IMPLICIT ); var inType = compiler.currentType; + if (!inType.isMemory) { + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + ctx.reportNode.typeArgumentsRange, "store", inType.toString() + ); + compiler.currentType = Type.void; + return module.unreachable(); + } if ( type.isIntegerValue && ( diff --git a/src/compiler.ts b/src/compiler.ts index ada299256e..6e7c778de2 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -10056,10 +10056,13 @@ export class Compiler extends DiagnosticEmitter { // Needs to be true (i.e. not zero) when the ref is _not_ null, // which means `ref.is_null` returns false (i.e. zero). return module.unary(UnaryOp.EqzI32, module.ref_is_null(expr)); - } + case TypeKind.VOID: default: { - assert(false); + this.error( + DiagnosticCode.An_expression_of_type_0_cannot_be_tested_for_truthiness, + reportNode.range, type.toString() + ); return module.i32(0); } } diff --git a/src/diagnosticMessages.json b/src/diagnosticMessages.json index 99486b1396..befcbca429 100644 --- a/src/diagnosticMessages.json +++ b/src/diagnosticMessages.json @@ -118,6 +118,7 @@ "A class may only extend another class.": 1311, "A parameter property cannot be declared using a rest parameter.": 1317, "A default export can only be used in a module.": 1319, + "An expression of type '{0}' cannot be tested for truthiness.": 1345, "An identifier or keyword cannot immediately follow a numeric literal.": 1351, "Duplicate identifier '{0}'.": 2300, diff --git a/src/types.ts b/src/types.ts index 72839d13f4..a07375990b 100644 --- a/src/types.ts +++ b/src/types.ts @@ -323,6 +323,26 @@ export class Type { return classReference != null && classReference.hasDecorator(DecoratorFlags.UNMANAGED); } + get isMemory(): bool { + switch (this.kind) { + case TypeKind.BOOL: + case TypeKind.I8: + case TypeKind.I16: + case TypeKind.I32: + case TypeKind.I64: + case TypeKind.ISIZE: + case TypeKind.U8: + case TypeKind.U16: + case TypeKind.U32: + case TypeKind.U64: + case TypeKind.USIZE: + case TypeKind.F32: + case TypeKind.F64: + case TypeKind.V128: return true; + } + return false; + } + /** Gets the corresponding non-nullable type. */ get nonNullableType(): Type { if (this.isExternalReference) { diff --git a/tests/compiler/issues/2473.json b/tests/compiler/issues/2473.json new file mode 100644 index 0000000000..aafce99bbb --- /dev/null +++ b/tests/compiler/issues/2473.json @@ -0,0 +1,14 @@ +{ + "asc_flags": [ + ], + "stderr": [ + "TS1345: An expression of type 'void' cannot be tested for truthiness.", + "TS1345: An expression of type 'void' cannot be tested for truthiness.", + "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'", + "EOF" + ] +} diff --git a/tests/compiler/issues/2473.ts b/tests/compiler/issues/2473.ts new file mode 100644 index 0000000000..7d3d645a9f --- /dev/null +++ b/tests/compiler/issues/2473.ts @@ -0,0 +1,17 @@ +const voidFn = (): void => {}; + +// TS1345: An expression of type 'void' cannot be tested for truthiness. +voidFn() ? 1 : 0; + +// TS1345: An expression of type 'void' cannot be tested for truthiness. +if (voidFn()) {} + +// TS1345: An expression of type 'void' cannot be tested for truthiness. +!voidFn(); + +store(8, voidFn()); +load(8); +load(8); +load(8); + +ERROR("EOF");