diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index b62a7b92e..6cfa65f62 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -5634,6 +5634,18 @@ class MLIRGenImpl return mlir::failure(); } + // a number, a string, a boolean or a bigint is no class to test against. A type of one + // (`type str = TypeOf<"">`) is: the test compares the types (tests/00instanceof.ts). + auto rightBaseType = mth.getBaseType(rightType); + if (!resultRightValue.getDefiningOp() + && (mth.isNumericType(rightBaseType) || isa(rightBaseType) + || isa(rightBaseType) || isa(rightBaseType))) + { + emitError(loc(binaryExpressionAST->right), "The right-hand side of an 'instanceof' expression must be a class, not '") + << to_print(rightType) << "'"; + return mlir::failure(); + } + rightType = mth.wideStorageType(rightType); if (isCppVTableClass(rightType) || isCppVTableClass(resultLeftfType)) diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index e92db2eb9..d98030733 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -2748,6 +2748,16 @@ add_test(NAME test-compile-interface-cast-empty set_tests_properties(test-compile-interface-cast-empty PROPERTIES FAIL_REGULAR_EXPRESSION "error:|Stack dump|Assertion failed") +# `instanceof` with a number, a string, a boolean or a bigint value on the right is an error: the +# test compared the two types. A type there (`type str = TypeOf<"">`) stays an extension. +add_test(NAME test-compile-diagnostic-location-instanceof-primitive + COMMAND $ --emit=obj --no-default-lib -mm=none + "${PROJECT_SOURCE_DIR}/test/tester/diagnostic-location/instanceof_primitive.ts" + -o "${CMAKE_CURRENT_BINARY_DIR}/diagnostic-location-instanceof-primitive.obj") +set_tests_properties(test-compile-diagnostic-location-instanceof-primitive + PROPERTIES PASS_REGULAR_EXPRESSION "instanceof_primitive\\.ts:8:24: error: The right-hand side of an 'instanceof' expression must be a class, not '3'" + FAIL_REGULAR_EXPRESSION "Stack dump|Assertion failed|instanceof_primitive\\.ts:7:") + # A @cpp class names the slots of a vtable made by C++ (tests/00cppvtable_class.ts), so what # would add a slot, run code of its own or ask the object what it is is an error: a slot off by one # would call the wrong C++ method, with no error at all. One whose methods have bodies implements diff --git a/tslang/test/tester/diagnostic-location/instanceof_primitive.ts b/tslang/test/tester/diagnostic-location/instanceof_primitive.ts new file mode 100644 index 000000000..e8b9e6465 --- /dev/null +++ b/tslang/test/tester/diagnostic-location/instanceof_primitive.ts @@ -0,0 +1,9 @@ +// A number on the right of `instanceof` is no class: the test compared the two types and +// was quietly true or false. + +type str = TypeOf<"">; + +function main() { + print("asd" instanceof str); + print(5 instanceof 3); +}