chore(pass-style): make CopyArray compatible with ReadonlyArray#3061
chore(pass-style): make CopyArray compatible with ReadonlyArray#3061michaelfig wants to merge 1 commit intomasterfrom
CopyArray compatible with ReadonlyArray#3061Conversation
31f81e8 to
e6a4c16
Compare
e6a4c16 to
97a0744
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the CopyArray<T> type definition from Array<T> to ReadonlyArray<T> to better reflect that CopyArrays are hardened and immutable at runtime. This allows readonly arrays and tuples to be accepted as Passable, resolving issue #3060.
Changes:
- Changed
CopyArray<T>type fromArray<T>toReadonlyArray<T>in type definitions - Added type tests to verify readonly arrays and tuples are accepted as Passable
- Updated NEWS.md to document the type change
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/pass-style/src/types.d.ts | Changes CopyArray<T> from Array<T> to ReadonlyArray<T> to reflect immutability |
| packages/pass-style/src/types.test-d.ts | Adds type tests for readonly arrays, const tuples, and various array forms |
| packages/pass-style/NEWS.md | Documents the type change in the release notes |
The change is semantically correct - CopyArrays are hardened at runtime and should not be mutated. The type system should reflect this. However, there is a downstream impact on the patterns package that uses incorrect type annotations for mutable accumulators.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@copilot, can you specify a few examples of exactly where it is in "the patterns package that uses incorrect type annotations for mutable accumulators"? |
|
@michaelfig I've opened a new pull request, #3062, to work on those changes. Once the pull request is ready, I'll request review from you. |
packages/pass-style/src/types.d.ts
Outdated
| export type CopyArray<T extends Passable = any> = Array<T>; | ||
|
|
||
| /** | ||
| * A Passable and Readonly sequence of Passable values. | ||
| */ | ||
| export type CopyReadonlyArray<T extends Passable = any> = ReadonlyArray<T>; |
There was a problem hiding this comment.
Why introduce a new type? What breaks if CopyArray is instead updated to use ReadonlyArray rather than Array?
There was a problem hiding this comment.
Thanks for asking!
The breaking change is that there are some uses in the wild of CopyArray as the type of a mutable array, and then the code proceeds to mutate the array. If CopyArray = ReadonlyArray, the code fails to typecheck.
At this stage in the game, I'm very reluctant somewhat willing to introduce breaking changes.
There was a problem hiding this comment.
@copilot, for this endojs/endo repository, in *.js files containing JSDoc TypeScript types and *.ts TypeScript files, can you please identify all arrays that are declared to be of type CopyArray that are later mutated?
Use shell commands with intermediary files whenever possible to save your work and avoid consuming too much of your agent's context space.
There was a problem hiding this comment.
Besides the highly enthusiastic affirmations of my AI sycophant, I also see that a mutable CopyArray type is useful to enforce that all its elements are Passable.
There was a problem hiding this comment.
Having said all that, the friendly bots scoured Agoric/agoric-sdk and endojs/endo, and only @endo/patterns/src/patterns/patternMatchers.js uses a mutable CopyArray in its internals. What do you see as the best way forward?
There was a problem hiding this comment.
#3065 will fix the typing that makes it look like patternMatchers.js is attempting CopyArray mutation, and any mutability associated with Passable is itself a bug whose footprint I'd rather reduce than expand. So my preference is to land #3065 and then update this PR to tighten CopyArray without introducing a new type.
|
@michaelfig I've opened a new pull request, #3063, to work on those changes. Once the pull request is ready, I'll request review from you. |
03df212 to
d6fc8fd
Compare
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 2 out of 3 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| arr.slice(0, 1); | ||
| arr.shift(); | ||
| expectPassable(arr); | ||
|
|
||
| // Not so for CopyReadonlyArray. | ||
| const roArr: CopyReadonlyArray<number> = []; | ||
| // @ts-expect-error not mutable | ||
| roArr.push(1); | ||
| roArr.slice(0, 1); | ||
| // @ts-expect-error not mutable | ||
| roArr.shift(); | ||
| expectPassable(roArr); |
There was a problem hiding this comment.
Result from call to slice ignored.
| arr.slice(0, 1); | |
| arr.shift(); | |
| expectPassable(arr); | |
| // Not so for CopyReadonlyArray. | |
| const roArr: CopyReadonlyArray<number> = []; | |
| // @ts-expect-error not mutable | |
| roArr.push(1); | |
| roArr.slice(0, 1); | |
| // @ts-expect-error not mutable | |
| roArr.shift(); | |
| expectPassable(roArr); | |
| const slicedArr = arr.slice(0, 1); | |
| arr.shift(); | |
| expectPassable(arr); | |
| expectPassable(slicedArr); | |
| // Not so for CopyReadonlyArray. | |
| const roArr: CopyReadonlyArray<number> = []; | |
| // @ts-expect-error not mutable | |
| roArr.push(1); | |
| const slicedRoArr = roArr.slice(0, 1); | |
| // @ts-expect-error not mutable | |
| roArr.shift(); | |
| expectPassable(roArr); | |
| expectPassable(slicedRoArr); |
d6fc8fd to
e5684ea
Compare
e5684ea to
8d8a604
Compare
Closes: #3060
Description
This PR updates the CopyArray type definition from Array to ReadonlyArray to better reflect that CopyArrays are hardened and immutable at runtime. This allows readonly arrays and tuples to be accepted as Passable, resolving issue #3060.
Security Considerations
Types now reflect that
@endo/pass-style's Passable type doesn't requireCopyArraysto be mutable.Scaling Considerations
n/a
Documentation Considerations
If you typed a mutable array as a
CopyArray, Typescript will show errors if you try to mutate it directly, or call methods that would mutate it. You can achieve the original behavior by typing your array asPassable[].Testing Considerations
Type tests have been added.
Compatibility Considerations
Makes for better compatibility.
Upgrade Considerations
No runtime change, typing only.