Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 28bfe64

Browse files
authoredAug 31, 2022
fix: Disallow expressions with void type & references for some operations (#2474)
1 parent 6c79e39 commit 28bfe64

File tree

6 files changed

+76
-2
lines changed

6 files changed

+76
-2
lines changed
 

‎src/builtins.ts

+19
Original file line numberDiff line numberDiff line change
@@ -2286,12 +2286,23 @@ function builtin_load(ctx: BuiltinContext): ExpressionRef {
22862286
var typeArguments = ctx.typeArguments;
22872287
var contextualType = ctx.contextualType;
22882288
var type = typeArguments![0];
2289+
22892290
var outType = (
22902291
contextualType != Type.auto &&
22912292
type.isIntegerValue &&
22922293
contextualType.isIntegerValue &&
22932294
contextualType.size > type.size
22942295
) ? contextualType : type;
2296+
2297+
if (!outType.isMemory) {
2298+
compiler.error(
2299+
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
2300+
ctx.reportNode.typeArgumentsRange, "load", outType.toString()
2301+
);
2302+
compiler.currentType = Type.void;
2303+
return module.unreachable();
2304+
}
2305+
22952306
var arg0 = compiler.compileExpression(operands[0], compiler.options.usizeType, Constraints.CONV_IMPLICIT);
22962307
var numOperands = operands.length;
22972308
var immOffset = 0;
@@ -2350,6 +2361,14 @@ function builtin_store(ctx: BuiltinContext): ExpressionRef {
23502361
: Constraints.CONV_IMPLICIT
23512362
);
23522363
var inType = compiler.currentType;
2364+
if (!inType.isMemory) {
2365+
compiler.error(
2366+
DiagnosticCode.Operation_0_cannot_be_applied_to_type_1,
2367+
ctx.reportNode.typeArgumentsRange, "store", inType.toString()
2368+
);
2369+
compiler.currentType = Type.void;
2370+
return module.unreachable();
2371+
}
23532372
if (
23542373
type.isIntegerValue &&
23552374
(

‎src/compiler.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -10094,10 +10094,13 @@ export class Compiler extends DiagnosticEmitter {
1009410094
// Needs to be true (i.e. not zero) when the ref is _not_ null,
1009510095
// which means `ref.is_null` returns false (i.e. zero).
1009610096
return module.unary(UnaryOp.EqzI32, module.ref_is_null(expr));
10097-
1009810097
}
10098+
case TypeKind.VOID:
1009910099
default: {
10100-
assert(false);
10100+
this.error(
10101+
DiagnosticCode.An_expression_of_type_0_cannot_be_tested_for_truthiness,
10102+
reportNode.range, type.toString()
10103+
);
1010110104
return module.i32(0);
1010210105
}
1010310106
}

‎src/diagnosticMessages.json

+1
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
"A class may only extend another class.": 1311,
121121
"A parameter property cannot be declared using a rest parameter.": 1317,
122122
"A default export can only be used in a module.": 1319,
123+
"An expression of type '{0}' cannot be tested for truthiness.": 1345,
123124
"An identifier or keyword cannot immediately follow a numeric literal.": 1351,
124125

125126
"Duplicate identifier '{0}'.": 2300,

‎src/types.ts

+20
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,26 @@ export class Type {
323323
return classReference != null && classReference.hasDecorator(DecoratorFlags.UNMANAGED);
324324
}
325325

326+
get isMemory(): bool {
327+
switch (this.kind) {
328+
case TypeKind.BOOL:
329+
case TypeKind.I8:
330+
case TypeKind.I16:
331+
case TypeKind.I32:
332+
case TypeKind.I64:
333+
case TypeKind.ISIZE:
334+
case TypeKind.U8:
335+
case TypeKind.U16:
336+
case TypeKind.U32:
337+
case TypeKind.U64:
338+
case TypeKind.USIZE:
339+
case TypeKind.F32:
340+
case TypeKind.F64:
341+
case TypeKind.V128: return true;
342+
}
343+
return false;
344+
}
345+
326346
/** Gets the corresponding non-nullable type. */
327347
get nonNullableType(): Type {
328348
if (this.isExternalReference) {

‎tests/compiler/issues/2473.json

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"asc_flags": [
3+
],
4+
"stderr": [
5+
"TS1345: An expression of type 'void' cannot be tested for truthiness.",
6+
"TS1345: An expression of type 'void' cannot be tested for truthiness.",
7+
"TS1345: An expression of type 'void' cannot be tested for truthiness.",
8+
"AS203: Operation 'store' cannot be applied to type 'void'.",
9+
"AS203: Operation 'load' cannot be applied to type 'void'.",
10+
"AS203: Operation 'load' cannot be applied to type 'externref'.",
11+
"AS203: Operation 'load' cannot be applied to type 'anyref'",
12+
"EOF"
13+
]
14+
}

‎tests/compiler/issues/2473.ts

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
const voidFn = (): void => {};
2+
3+
// TS1345: An expression of type 'void' cannot be tested for truthiness.
4+
voidFn() ? 1 : 0;
5+
6+
// TS1345: An expression of type 'void' cannot be tested for truthiness.
7+
if (voidFn()) {}
8+
9+
// TS1345: An expression of type 'void' cannot be tested for truthiness.
10+
!voidFn();
11+
12+
store<void>(8, voidFn());
13+
load<void>(8);
14+
load<externref>(8);
15+
load<anyref>(8);
16+
17+
ERROR("EOF");

0 commit comments

Comments
 (0)
Failed to load comments.