From 83e6b59543ca17f6c6b5b94df453ea23a1eb3b22 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 27 Aug 2022 10:52:08 +0300 Subject: [PATCH 1/4] init --- src/builtins.ts | 16 ++++++++++++++++ src/compiler.ts | 8 +++++++- src/diagnosticMessages.json | 1 + tests/compiler/issues/2473.json | 12 ++++++++++++ tests/compiler/issues/2473.ts | 13 +++++++++++++ 5 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/compiler/issues/2473.json create mode 100644 tests/compiler/issues/2473.ts diff --git a/src/builtins.ts b/src/builtins.ts index dc61f365c0..c29966b1b9 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2292,6 +2292,14 @@ function builtin_load(ctx: BuiltinContext): ExpressionRef { contextualType.isIntegerValue && contextualType.size > type.size ) ? contextualType : type; + if (outType == Type.void) { + 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 +2358,14 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef { : Constraints.CONV_IMPLICIT ); var inType = compiler.currentType; + if (inType == Type.void) { + 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 e937313480..6d139884a6 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -10056,7 +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: { + this.error( + DiagnosticCode.An_expression_of_type_0_cannot_be_tested_for_truthiness, + reportNode.range, "void" + ); + return module.i32(0); } default: { assert(false); 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/tests/compiler/issues/2473.json b/tests/compiler/issues/2473.json new file mode 100644 index 0000000000..e6eea3fdc7 --- /dev/null +++ b/tests/compiler/issues/2473.json @@ -0,0 +1,12 @@ +{ + "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'.", + "EOF" + ] +} diff --git a/tests/compiler/issues/2473.ts b/tests/compiler/issues/2473.ts new file mode 100644 index 0000000000..e5bfd12a88 --- /dev/null +++ b/tests/compiler/issues/2473.ts @@ -0,0 +1,13 @@ +// TS1345: An expression of type 'void' cannot be tested for truthiness. +((): void => {})() ? 1 : 0; + +// TS1345: An expression of type 'void' cannot be tested for truthiness. +if (((): void => {})()) {} + +// TS1345: An expression of type 'void' cannot be tested for truthiness. +!((): void => {})(); + +store(8, ((): void => {})()); +load(8); + +ERROR("EOF"); From 208b2d92988400f11eca1b6bc56ec171bc470e8b Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Sat, 27 Aug 2022 12:21:54 +0300 Subject: [PATCH 2/4] cache void expr --- tests/compiler/issues/2473.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/compiler/issues/2473.ts b/tests/compiler/issues/2473.ts index e5bfd12a88..c38f4717ac 100644 --- a/tests/compiler/issues/2473.ts +++ b/tests/compiler/issues/2473.ts @@ -1,13 +1,15 @@ +const voidFn = (): void => {}; + // TS1345: An expression of type 'void' cannot be tested for truthiness. -((): void => {})() ? 1 : 0; +voidFn() ? 1 : 0; // TS1345: An expression of type 'void' cannot be tested for truthiness. -if (((): void => {})()) {} +if (voidFn()) {} // TS1345: An expression of type 'void' cannot be tested for truthiness. -!((): void => {})(); +!voidFn(); -store(8, ((): void => {})()); +store(8, voidFn()); load(8); ERROR("EOF"); From c10ebcb0318a3a6ce4c4662a6040a85275a81756 Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 31 Aug 2022 20:48:29 +0300 Subject: [PATCH 3/4] generalize --- src/builtins.ts | 13 +++++++++++-- src/compiler.ts | 9 +++------ tests/compiler/issues/2473.json | 2 ++ tests/compiler/issues/2473.ts | 2 ++ 4 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index c29966b1b9..600370a605 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2286,13 +2286,18 @@ 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 == Type.void) { + + if ( + !outType.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE) || + outType.isAny(TypeFlags.EXTERNAL) + ) { compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, ctx.reportNode.typeArgumentsRange, "load", outType.toString() @@ -2300,6 +2305,7 @@ function builtin_load(ctx: BuiltinContext): ExpressionRef { 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; @@ -2358,7 +2364,10 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef { : Constraints.CONV_IMPLICIT ); var inType = compiler.currentType; - if (inType == Type.void) { + if ( + !inType.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE) || + inType.isAny(TypeFlags.EXTERNAL) + ) { compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, ctx.reportNode.typeArgumentsRange, "store", inType.toString() diff --git a/src/compiler.ts b/src/compiler.ts index f58caa8379..6e7c778de2 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -10057,17 +10057,14 @@ export class Compiler extends DiagnosticEmitter { // which means `ref.is_null` returns false (i.e. zero). return module.unary(UnaryOp.EqzI32, module.ref_is_null(expr)); } - case TypeKind.VOID: { + case TypeKind.VOID: + default: { this.error( DiagnosticCode.An_expression_of_type_0_cannot_be_tested_for_truthiness, - reportNode.range, "void" + reportNode.range, type.toString() ); return module.i32(0); } - default: { - assert(false); - return module.i32(0); - } } } diff --git a/tests/compiler/issues/2473.json b/tests/compiler/issues/2473.json index e6eea3fdc7..aafce99bbb 100644 --- a/tests/compiler/issues/2473.json +++ b/tests/compiler/issues/2473.json @@ -7,6 +7,8 @@ "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 index c38f4717ac..7d3d645a9f 100644 --- a/tests/compiler/issues/2473.ts +++ b/tests/compiler/issues/2473.ts @@ -11,5 +11,7 @@ if (voidFn()) {} store(8, voidFn()); load(8); +load(8); +load(8); ERROR("EOF"); From c3840a461a68ad192ae0d83bf20e78caded1a9ba Mon Sep 17 00:00:00 2001 From: MaxGraey Date: Wed, 31 Aug 2022 22:05:22 +0300 Subject: [PATCH 4/4] refactor. Add isMemory for Type --- src/builtins.ts | 10 ++-------- src/types.ts | 20 ++++++++++++++++++++ 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/src/builtins.ts b/src/builtins.ts index 600370a605..0b91345de7 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -2294,10 +2294,7 @@ function builtin_load(ctx: BuiltinContext): ExpressionRef { contextualType.size > type.size ) ? contextualType : type; - if ( - !outType.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE) || - outType.isAny(TypeFlags.EXTERNAL) - ) { + if (!outType.isMemory) { compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, ctx.reportNode.typeArgumentsRange, "load", outType.toString() @@ -2364,10 +2361,7 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef { : Constraints.CONV_IMPLICIT ); var inType = compiler.currentType; - if ( - !inType.isAny(TypeFlags.VALUE | TypeFlags.REFERENCE) || - inType.isAny(TypeFlags.EXTERNAL) - ) { + if (!inType.isMemory) { compiler.error( DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, ctx.reportNode.typeArgumentsRange, "store", inType.toString() 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) {