Repository navigation
feat(ts): translate std's conversions of a reference - #386
Merged
Merged
Conversation
Quest-Claim: f1b2a94e0fae2077
`to_owned`, `clone_into`, `clone_from`, `binary_search`, `size_of_val`, `align_of_val`, `slice::from_mut`, `array::from_ref` and `from_mut`, an array's `AsRef`, `AsMut`, `Borrow`, and `BorrowMut` as a slice, `Cell::from_mut`, and `ptr::from_ref` and `from_mut`, for any `T` and for `[u8; N]`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… census Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…, and assign a Vec through a cell whole ptr::from_mut lowers as `&raw mut *r` of the place an alias names, so a pointer to a Vec or another object JS points at by an rt.Place is made as a borrow of it is. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as ready for review
November 1, 2026 15:06
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e is private Object.assign and cellIn copy only enumerable fields, so a write through a `&mut LazyCell` or `Cell::from_mut` of one left the old state in place. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… too Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
quest land removed this pull request from the queue: Conflicts with the base: ts/fixtures/lang/expected/harness.ts, ts/fixtures/lang/src/harness.rs, ts/fixtures/reject/census.md, ts/fixtures/reject/expected.txt |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as draft
November 1, 2026 18:40
|
Codex land fixer: quest land check: waiting for check launcher quest land check: check launcher did not become ready within 3600 seconds (written by Codex) |
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
marked this pull request as ready for review
November 1, 2026 23:19
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
kixelated
added a commit
that referenced
this pull request
Nov 2, 2026
Order the boxed-slice `clone_from` arm before #386's generic one, which refused `Box<[T]>` and `Box<str>` as a type whose `clone_from` is its own. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This was referenced Nov 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Completes quest/m3/ts-ref-conversions.md.
Problem
rust2-ts refused std's functions that take a reference and convert, copy, or measure what it points at, as "unsupported call", for every
T(reproduced foru32,[u8; 2],[u32; 2], and a struct):ToOwned::to_ownedandclone_into,Clone::clone_from,slice::binary_search,mem::size_of_valandalign_of_val,slice::from_mut,array::from_refandfrom_mut, an array'sAsRef,AsMut,Borrow, andBorrowMutas a slice,Cell::from_mut, andptr::from_refandfrom_mut.Approach
Copies.
to_ownedof a sizedTis a call ofClone::clone.clone_fromandclone_intolower in the MIR intercept as*self = source.clone(): clone, write through the borrowed place asmem::replacedoes, then drop the old value. A type whoseclone_fromis its own is refused, asslice::fillalready does;LinkedListkeeps its mapping.binary_search.rt.sliceBinarySearchis std's loop: no early exit, so a run of equal elements gives std'sOkindex, andErrthe insertion point. It compares withcmp_fn, so a crate's ownOrdis called on the same elements in the same order.Sizes.
size_of_valandalign_of_valare wasm32's layout ofT, or for a slice orstr, its length times the element's size.One-element slices and cells.
slice::from_mutandarray::from_mutgivert.sliceOfPlace, a length-1Proxyover anrt.Place, so a whole write lands where the&mutpoints:rt.Place;[u8; N]usesrt.bytesPlace, which reads the view and writes the bytes in place;Cell::from_mutuses the same places throughrt.cellOfPlace. An object no place names (a parameter) goes throughrt.cellIn, which reads a copy and writes in place, a JS array taking the new length, since aCellonly moves or copies its value out.from_refand arrays as slices.array::from_refmaps likeslice::from_ref.AsRef,AsMut,Borrow, andBorrowMutof an array as a slice are the array itself, andlendleaves them,to_owned, and the intercepted calls untouched.Pointers.
ptr::from_refmaps asNonNull::fromdoes. A[u8; N]given as the view of its bytes becomesrt.byteSliceFromof it, so it compares by buffer and offset.ptr::from_mutlowers as&raw mut *rof the place the alias names, through the sameRvalue::RawPtrlowering and checks, so a pointer to aVecis thert.Placeof its slot. The pointer analysis treats both likeNonNull::from.Rebinding.
pointer::rebindsnow returns which arguments a call may give another value, not how many leading ones:clone_fromand the threefrom_muts their first,clone_intoits second. So a raw pointer to a variable that one of them replaces is refused, as onemem::replacereplaces already is.Still refused, each with a span:
slice::from_mutof a&mut u8: a&mut [u8]is anrt.ByteSlice, which can't view oneu8'srt.Place.slice::from_mutof a&mutto an object no place in the function names. A slice element write replaces the slot. Copying it into the object instead would makemem::replace(&mut s[0], v)return the object it just overwrote.size_of_valof a trait object.Cell::from_mutof aLazyCell,LazyLock, orLocalKey, and a whole write through a&mutto one. Their runtime classes keep state in private fields, whichObject.assignandrt.cellIndon't copy, soTranslator::write_innow refuses them as it already didrt.PollFn. The plain write through a&mutwas silently wrong on main too.Tests
conversions::conversionsin the lang fixture runs differentially against native wasm32 foru8,u32,u64past 2^53,String,Option<u16>,[u8; 0],[u8; 1],[u8; 3],[u8; 40],[u32; 2],Vec<u32>andVec<u8>of 0 to 3 elements, a struct, and a type that logs its clones and drops. It covers:fillanditer_mut;binary_searchover sorted runs with duplicates, at lengths 0 to 24;strpast ASCII,usize,u128, a tuple with padding,Option<u32>,[u16; 3], a struct, aString, and();ptr::eqoffrom_refpointers to byte arrays and objects.The
u8case skipsslice::from_mut, which is refused.An early-exit
binary_searchin the runtime gives 103 differences. The reject fixture gains the three refusals, aclone_fromofVec<Reused>, a raw pointer outlivingclone_from,clone_into, andCell::from_mutof its variable, and whole writes into aLazyCell, aLazyLock, and aLocalKey.Impact
rt.sliceBinarySearch,rt.sliceOfPlace,rt.bytesPlace,rt.cellOfPlace, andrt.cellIn. No breaking change, so noMIGRATE.mdentry.rt.sliceView's internalViewnow takes any indexable, sosliceOfPlacereuses it.Alternatives
Proxyslice that writes an opaque object in place (replaceIn): dropped, sincemem::replaceon its element reads the object, then overwrites it, returning the new value. Refused instead; see the follow-up.[view]for a[u8; N]: dropped, since a whole store into a&mut [[u8; N]]element replaces the slot, not the bytes.binary_search_by,_by_key, andpartition_pointtoo: left for a follow-up to keep this to the quest's list.Follow-ups
Quests added to m3:
slice::from_mutandarray::from_mutof a&mut u8, and of an object no place names.binary_search_by,binary_search_by_key, andpartition_pointthrough the same search.Decisions
Settled by the maintainer on 2026-11-01, the first two as recommended:
slice::from_mutof an object behind a parameter.mem::replaceon the element.The follow-up quest records (c) as the path to lift it.
The binary-search family.
binary_search_by,_by_key, andpartition_pointfor their own quest, as done here. Recommended.clone_fromandclone_intoof a vector, which std does into the allocation it has.clone_from_clones.clone_fromas std's body does, reusing the allocation.clone_from_clonesin its own PR first.clone_fromandclone_intobeyond "avoids reallocation if possible", so under the 2026-11-01 "std's guarantees only" rule a capacity of at least the length is correct. A clone's exact capacity, 3 where native reads 10, is not a divergence.ts/README.mdnow says so, and a test that reads capacity after these checks it against std's guarantees.Review
Codex
gpt-6.1-sol, medium effort, viaquest review --base origin/main:Round 1 on
f20d00c4f88e171371631318d6ac064bdb84a857, two findings, both fixed:rebindsomittedclone_from,clone_into's second argument, andCell::from_mut. It now returns argument indices, with reject cases.rt.cellInleft aVec's trailing elements. It now assigns arrays whole, withVec<u32>andVec<u8>differential cases. This also surfaced theptr::from_mutof a&mut Vec, now lowered as&raw mut *r.Round 2 on
ce7e2b77bd87a7dfe64fa1621cb7ace34a772934: no findings.Round 3 on
499130e6d05a03b631a581934928f5b5d82750e3(after merging main):Cell::from_mutof aLazyCelllost its private state. Fixed inwrite_inforLazyCellandLazyLock, with reject cases.Round 4 on
a8083227f133bc2a35c31077e9e72b1fac7b574e:LocalKeyhas the same private state. Fixed the same way, with a reject case.Round 5 on
d42d0e1ced7fb9440b802f93ad86423315a0e8b4: no findings.Skipped on
11030f842d9329639ea4424c50b371ddf1751431as trivial: merges oforigin/mainat8e6a7219(feat(ts): hold std's capacity guarantees for Vec, VecDeque, and BinaryHeap, with pushes untouched #372, fix(ffi): build the C++ test on Windows, and print paths as escape_ascii does #388, chore(quest): finish Kotlin bindings on Android in the nightly #389, feat(ts): translate the rest of a guard's methods #392, fix(uniffi): port current binding ownership fixes #364, feat(ts): translate hashbrown's HashMap, HashSet, and HashTable as std's maps, with std's capacity #398, feat(ts): translate BufMut's provided writes through a &mut or a Box #401, feat(ts): translate a guard's downgrade, leak, and whole byte-array map #402, and quest PRs), whose conflicts were only the lang harness list, keeping both sides' cases, and generated snapshots, regenerated; and one sentence ints/README.mdrecording decision 3. No source changed.Local checks:
just cipassed on11030f84.(written by Claude Opus 5.5)
🤖 Generated with Claude Code