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
2 changes: 1 addition & 1 deletion tslang/include/TypeScript/MLIRLogic/MLIRGenStore.h
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ struct InterfaceInfo

for (auto &field : fields)
{
tupleFields.push_back({field.id, field.type, false, mlir_ts::AccessLevel::Public});
tupleFields.push_back({field.id, field.type, field.isConditional, mlir_ts::AccessLevel::Public});
}

return mlir::success();
Expand Down
16 changes: 16 additions & 0 deletions tslang/lib/TypeScript/MLIRGenCast.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,22 @@ namespace mlirgen
if (std::find_if(fields.begin(), fields.end(),
[&](auto &item) { return item.id == interfaceField.id; }) == fields.end())
{
// the source has no field of this name at all - only reachable for a
// conditional (`?`) interface member (getVirtualTable's resolveField
// already rejects a missing non-conditional one, failing
// canCastTupleToInterface before this clone path even runs). Match the
// convention InterfaceSymbolRefOp's `optional` slot-count check already
// relies on for the non-clone path (see 00interface_optional_cast_order.ts):
// the field is simply ABSENT from the storage tuple, not present with a
// placeholder value - so skip it here rather than appending it. Appending it
// with any value/type would desync the clone's field COUNT from what
// interfaceVTableNameForObject's slot-index math and the interface's runtime
// "is this slot within the actual object's tuple size" check expect.
if (interfaceField.isConditional)
{
continue;
}

fields.push_back(interfaceField);
}
}
Expand Down
2 changes: 2 additions & 0 deletions tslang/test/tester/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,7 @@ add_test(NAME test-compile-00-object-annotated-method-params COMMAND test-runner
add_test(NAME test-compile-00-object-annotated-method-interleaved COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_interleaved.ts")
add_test(NAME test-compile-00-object-annotated-method-extends-interface COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_extends_interface.ts")
add_test(NAME test-compile-00-object-annotated-method-extends-interface-multilevel COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_extends_interface_multilevel.ts")
add_test(NAME test-compile-00-interface-optional-extends COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_optional_extends.ts")
add_test(NAME test-compile-00-interface-object-array COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_object_array.ts")
add_test(NAME test-compile-00-interface-generic COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_generic.ts")
add_test(NAME test-compile-00-interface-new COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_new.ts")
Expand Down Expand Up @@ -651,6 +652,7 @@ add_test(NAME test-jit-00-object-annotated-method-params COMMAND test-runner -ji
add_test(NAME test-jit-00-object-annotated-method-interleaved COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_interleaved.ts")
add_test(NAME test-jit-00-object-annotated-method-extends-interface COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_extends_interface.ts")
add_test(NAME test-jit-00-object-annotated-method-extends-interface-multilevel COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00object_annotated_method_extends_interface_multilevel.ts")
add_test(NAME test-jit-00-interface-optional-extends COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_optional_extends.ts")
add_test(NAME test-jit-00-interface-object-array COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_object_array.ts")
add_test(NAME test-jit-00-interface-generic COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_generic.ts")
add_test(NAME test-jit-00-interface-new COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00interface_new.ts")
Expand Down
38 changes: 38 additions & 0 deletions tslang/test/tester/tests/00interface_optional_extends.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Combines two previously-separate axes of interface coverage that had never
// been tested together: an optional member (00interface_optional_cast_order.ts
// - optional member's virtualIndex can get clobbered to -1 on the SHARED
// InterfaceInfo by whichever cast ran most recently) and `extends`
// (00object_annotated_method_extends_interface*.ts - inherited members need
// vtableOffset added to their own-interface-relative virtualIndex). The
// optional member here is declared on the BASE interface, so resolving it
// through the DERIVED interface's combined vtable exercises both the
// extends-offset math and the optional-member vtable-patch path at once.

function main() {
interface Base {
base: number;
opt?: number;
}

interface Derived extends Base {
derived: number;
}

let present: Derived = <Derived>{ base: 1, opt: 5, derived: 10 };
let missing: Derived = <Derived>{ base: 2, derived: 20 };

assert(present.base == 1);
assert(present.opt == 5);
assert(present.derived == 10);

assert(missing.base == 2);
assert(missing.opt == undefined);
assert(missing.derived == 20);

// re-read the providing object after the non-providing one was cast, to
// catch the shared-virtualIndex-clobber bug class if it resurfaces here
print(present.opt);
assert(present.opt == 5);

print("done.");
}
Loading