Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions tslang/lib/TypeScript/MLIRGenImpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -3619,10 +3619,10 @@ class MLIRGenImpl
auto isConst = false;
mlir::Attribute value;
isConst = isConstValue(constVal);
if (isConst)
// null and undefined are const values too, but not literals a discriminant field can hold
auto constantOp = isConst ? constVal.getDefiningOp<mlir_ts::ConstantOp>() : mlir_ts::ConstantOp();
if (constantOp)
{
auto constantOp = constVal.getDefiningOp<mlir_ts::ConstantOp>();
assert(constantOp);
auto valueAttr = constantOp.getValueAttr();

MLIRCodeLogic mcl(builder, compileOptions);
Expand All @@ -3633,6 +3633,11 @@ class MLIRGenImpl
if (auto tupleType = dyn_cast<mlir_ts::TupleType>(unionSubType))
{
auto fieldIndex = tupleType.getIndex(fieldNameAttr);
if (fieldIndex < 0)
{
continue;
}

auto fieldType = tupleType.getType(fieldIndex);
if (auto literalType = dyn_cast<mlir_ts::LiteralType>(fieldType))
{
Expand All @@ -3657,6 +3662,11 @@ class MLIRGenImpl
if (auto interfaceInfo = getInterfaceInfoByFullName(interfaceType.getName().getValue()))
{
auto fieldInfo = interfaceInfo->findField(fieldNameAttr);
if (!fieldInfo)
{
continue;
}

if (auto literalType = dyn_cast<mlir_ts::LiteralType>(fieldInfo->type))
{
if (literalType.getValue() == valueAttr)
Expand Down
3 changes: 3 additions & 0 deletions tslang/test/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ tslang_add_test(NAME test-compile-00-safe-cast-typeof COMMAND test-runner "${PRO
tslang_add_test(NAME test-compile-00-safe-cast-while COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_while.ts")
tslang_add_test(NAME test-compile-01-safe-cast-while COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/01safe_cast_while.ts")
tslang_add_test(NAME test-compile-00-safe-cast-field-access COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_field_access.ts")
tslang_add_test(NAME test-compile-00-safe-cast-null-field COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_null_field.ts")
tslang_add_test(NAME test-compile-00-safe-cast-bug COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_bug.ts")
tslang_add_test(NAME test-compile-00-optional COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00optional.ts")
tslang_add_test(NAME test-compile-01-optional COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/01optional.ts")
Expand Down Expand Up @@ -968,6 +969,7 @@ tslang_add_test(NAME test-jit-00-safe-cast-typeof COMMAND test-runner -jit "${PR
tslang_add_test(NAME test-jit-00-safe-cast-while COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_while.ts")
tslang_add_test(NAME test-jit-01-safe-cast-while COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/01safe_cast_while.ts")
tslang_add_test(NAME test-jit-00-safe-cast-field-access COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_field_access.ts")
tslang_add_test(NAME test-jit-00-safe-cast-null-field COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_null_field.ts")
tslang_add_test(NAME test-jit-00-safe-cast-bug COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00safe_cast_bug.ts")
tslang_add_test(NAME test-jit-00-optional COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00optional.ts")
tslang_add_test(NAME test-jit-01-optional COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/01optional.ts")
Expand Down Expand Up @@ -1749,6 +1751,7 @@ set(TSLANG_CORPUS
00reference_ref_deref.ts
00safe_cast_bug.ts
00safe_cast_field_access.ts
00safe_cast_null_field.ts
00safe_cast_typeof.ts
00safe_cast_while.ts
00safe_cast.ts
Expand Down
51 changes: 51 additions & 0 deletions tslang/test/tester/tests/00safe_cast_null_field.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// A field of a union-typed object compared with null or undefined. The discriminated-union
// narrowing took null and undefined for literal constants and crashed the compiler (#231).

interface Circle {
kind: "circle";
r: number | null;
}

interface Square {
kind: "square";
r: number | null;
}

type Shape = Circle | Square;

function hasR(s: Shape) {
if (s.r !== null) {
return true;
}

return false;
}

function hasRUndef(s: Shape) {
if (s.r === undefined) {
return false;
}

return true;
}

function kind(s: Shape) {
// a real literal must still narrow
if (s.kind === "circle") {
return 1;
}

return 2;
}

function main() {
const c: Circle = { kind: "circle", r: 1 };
const q: Square = { kind: "square", r: null };
assert(hasR(c));
assert(!hasR(q));
assert(hasRUndef(c));
assert(kind(c) == 1);
assert(kind(q) == 2);

print("done.");
}
Loading