diff --git a/tslang/lib/TypeScript/MLIRGenImpl.h b/tslang/lib/TypeScript/MLIRGenImpl.h index 87a5eac50..034bc0acc 100644 --- a/tslang/lib/TypeScript/MLIRGenImpl.h +++ b/tslang/lib/TypeScript/MLIRGenImpl.h @@ -1455,8 +1455,17 @@ class MLIRGenImpl // mutating methods silently did nothing (they mutated a copy nobody kept) // and `arr[i] = v` segfaulted (write into read-only constant data). // Force the same real-storage + widening path as `let` for this case too. + // + // A `const` already typed `!ts.array` (`const a: number[] = [1, 2]`, or an array + // returned by a call) needs it as well: push/pop/splice grow the array in place + // through a reference to it, and a bare SSA value has none. A ConstRef already + // aliases the storage it was read from, so it keeps that, and a narrowed view + // (addSafeCastStatement, a SafeCastOp) is the narrowed variable seen through + // another type, not an array of its own. MLIRTypeHelper mth(builder.getContext(), compileOptions); - needsIdentityStorage = mth.hasBoundMethodField(type) || isa(type); + needsIdentityStorage = mth.hasBoundMethodField(type) || isa(type) + || (isa(type) && !(varClass == VariableType::ConstRef) + && !(initial && initial.getDefiningOp())); if (needsIdentityStorage) { return mlir::success(); diff --git a/tslang/test/tester/CMakeLists.txt b/tslang/test/tester/CMakeLists.txt index c23b97214..819d36623 100644 --- a/tslang/test/tester/CMakeLists.txt +++ b/tslang/test/tester/CMakeLists.txt @@ -333,6 +333,7 @@ tslang_add_test(NAME test-compile-00-arrays3 COMMAND test-runner "${PROJECT_SOUR tslang_add_test(NAME test-compile-00-arrays4-push-pop COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array4_push_pop.ts") tslang_add_test(NAME test-compile-00-array-shift COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_shift.ts") tslang_add_test(NAME test-compile-00-array-splice COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_splice.ts") +tslang_add_test(NAME test-compile-00-const-array-push COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00const_array_push.ts") tslang_add_test(NAME test-compile-00-arrays5-deconstruct COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array5_deconst.ts") tslang_add_test(NAME test-compile-00-arrays6 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array6.ts") tslang_add_test(NAME test-compile-00-arrays7 COMMAND test-runner "${PROJECT_SOURCE_DIR}/test/tester/tests/00array7.ts") @@ -782,6 +783,7 @@ tslang_add_test(NAME test-jit-00-arrays3 COMMAND test-runner -jit "${PROJECT_SOU tslang_add_test(NAME test-jit-00-arrays4-push-pop COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array4_push_pop.ts") tslang_add_test(NAME test-jit-00-array-shift COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_shift.ts") tslang_add_test(NAME test-jit-00-array-splice COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array_splice.ts") +tslang_add_test(NAME test-jit-00-const-array-push COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00const_array_push.ts") tslang_add_test(NAME test-jit-00-arrays5-deconstruct COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array5_deconst.ts") tslang_add_test(NAME test-jit-00-arrays6 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array6.ts") tslang_add_test(NAME test-jit-00-arrays7 COMMAND test-runner -jit "${PROJECT_SOURCE_DIR}/test/tester/tests/00array7.ts") @@ -1546,6 +1548,7 @@ set(TSLANG_CORPUS 00array_shift.ts 00array_splice.ts 00array_view.ts + 00const_array_push.ts 00array.ts 00array2.ts 00array3.ts diff --git a/tslang/test/tester/tests/00const_array_push.ts b/tslang/test/tester/tests/00const_array_push.ts new file mode 100644 index 000000000..847f3283e --- /dev/null +++ b/tslang/test/tester/tests/00const_array_push.ts @@ -0,0 +1,39 @@ +// A const binding only forbids reassigning the name; the array it holds can still grow and +// shrink. An annotated const (`const a: number[]`) and a const holding a call's result used to +// be bare values, so push/pop/splice/length= had no array to change ("Can't get reference of +// the array"). +const g: number[] = [1, 2]; + +function make(): number[] { + return [7, 8]; +} + +function main() { + const a: number[] = [1, 2]; + a.push(3); + assert(a.length == 3, "push length"); + assert(a[2] == 3, "push value"); + + assert(a.pop() == 3, "pop value"); + a.unshift(0); + assert(a.length == 3, "unshift length"); + assert(a[0] == 0, "unshift value"); + + a.splice(1, 1); + assert(a.length == 2, "splice length"); + assert(a[1] == 2, "splice value"); + + a.length = 1; + assert(a.length == 1, "length set"); + + const c = make(); + c.push(9); + assert(c.length == 3, "call result length"); + assert(c[2] == 9, "call result value"); + + g.push(3); + assert(g.length == 3, "global length"); + assert(g[2] == 3, "global value"); + + print("done."); +}