From 8cd50cef89ac6f384c8ed580e2bd0e368ce5c025 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Wed, 4 Nov 2026 08:41:53 -0800 Subject: [PATCH 1/6] chore(quest): claim quest/m2/ts-model/from-iterator.md Quest-Claim: d89718ab643757e7 From fb877835dff2326917fd7f3c90636409b35869e2 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Wed, 4 Nov 2026 09:02:45 -0800 Subject: [PATCH 2/6] feat(ts): collect into and iterate a crate's own collections through std's adaptors std's `collect` into the crate's own `FromIterator` type, and into a `Result` or `Option` of one, calls its `from_iter`; `flat_map`, `flatten`, `chain`, `zip`, `extend`, and the rest that take an `IntoIterator` iterate the crate's own collection by its `into_iter`. Drops moq-net model's census from 78 to 71. Co-Authored-By: Claude Opus 5.5 --- quest/m2/ts-model/README.md | 3 +- quest/m2/ts-model/from-iterator.md | 14 - ts/Cargo.lock | 4 + ts/README.md | 4 + ts/fixtures/lang/collects/Cargo.toml | 14 + .../lang/collects/expected/collects.Bag.ts | 380 ++++++++++++++++++ .../lang/collects/expected/collects.Count.ts | 22 + .../lang/collects/expected/collects.Down.ts | 44 ++ .../lang/collects/expected/collects.Item.ts | 29 ++ .../lang/collects/expected/collects.Stack.ts | 49 +++ .../lang/collects/expected/collects.ts | 356 ++++++++++++++++ .../lang/collects/expected/core/bool.ts | 12 + .../lang/collects/expected/core/option.ts | 28 ++ ts/fixtures/lang/collects/expected/harness.ts | 46 +++ ts/fixtures/lang/collects/expected/lib.ts | 14 + ts/fixtures/lang/collects/src/collects.rs | 283 +++++++++++++ ts/fixtures/lang/collects/src/lib.rs | 23 ++ ts/fixtures/lang/collects/ts.toml | 2 + ts/src/lower/iter.rs | 36 +- ts/tests/fixtures.rs | 1 + 20 files changed, 1347 insertions(+), 17 deletions(-) delete mode 100644 quest/m2/ts-model/from-iterator.md create mode 100644 ts/fixtures/lang/collects/Cargo.toml create mode 100644 ts/fixtures/lang/collects/expected/collects.Bag.ts create mode 100644 ts/fixtures/lang/collects/expected/collects.Count.ts create mode 100644 ts/fixtures/lang/collects/expected/collects.Down.ts create mode 100644 ts/fixtures/lang/collects/expected/collects.Item.ts create mode 100644 ts/fixtures/lang/collects/expected/collects.Stack.ts create mode 100644 ts/fixtures/lang/collects/expected/collects.ts create mode 100644 ts/fixtures/lang/collects/expected/core/bool.ts create mode 100644 ts/fixtures/lang/collects/expected/core/option.ts create mode 100644 ts/fixtures/lang/collects/expected/harness.ts create mode 100644 ts/fixtures/lang/collects/expected/lib.ts create mode 100644 ts/fixtures/lang/collects/src/collects.rs create mode 100644 ts/fixtures/lang/collects/src/lib.rs create mode 100644 ts/fixtures/lang/collects/ts.toml diff --git a/quest/m2/ts-model/README.md b/quest/m2/ts-model/README.md index f8c75378a..77f695aaa 100644 --- a/quest/m2/ts-model/README.md +++ b/quest/m2/ts-model/README.md @@ -45,7 +45,7 @@ Decided with the maintainer on 2026-10-27, from a census of the model's 22 publi - The end-to-end work stays here: the model's roots, its differential harness, and the `frames.ts` workload. moq writes the binding files `model.toml` names, in its own tree. -The census at the pin on 2026-11-04: 78 refusals. `Timestamp` alone refuses nothing, and +The census at the pin on 2026-11-04: 71 refusals. `Timestamp` alone refuses nothing, and the [model fixture](/ts/README.md#tests)'s harness runs it against native moq-net at the pin; each case it adds as a type translates. Every other root reaches the rest of the model, so each child below unblocks all of them together. The rest is moq's, for its @@ -58,7 +58,6 @@ there, as does the `unsafe` slice of `model/frame.rs`'s `Filled`. ## Required - [Writes through a crate's DerefMut](/quest/m2/ts-model/guard-writes.md) - `*guard = value` through kio's lock guards -- [Iterators into a crate's own collections](/quest/m2/ts-model/from-iterator.md) - `collect`, `flat_map`, and `flatten` through moq-pattern's `Patterns` - [std's impls through a reference](/quest/m2/ts-model/reference-impls.md) - `<&[u8] as AsRef<[u8]>>::as_ref` - [Bytes from an owner that drops](/quest/m2/ts-model/bytes-owner.md) - `Bytes::from_owner` of a frame's segment - [rangemap](/quest/m2/ts-model/rangemap.md) - B-tree ranges by a borrowed key, and std's iterators in a crate's fields diff --git a/quest/m2/ts-model/from-iterator.md b/quest/m2/ts-model/from-iterator.md deleted file mode 100644 index f437b1990..000000000 --- a/quest/m2/ts-model/from-iterator.md +++ /dev/null @@ -1,14 +0,0 @@ -# [S] Iterators into a crate's own collections - -## Goal - -[rust2-ts](/ts/README.md) translates std's iterator adaptors where a crate's own type is -the collection: `collect` into a type with a `FromIterator` impl, and `flat_map` and -`flatten` over a type with an `IntoIterator` impl, proven by differential tests against -native Rust, including drops and laziness. - -## Plan - -moq-pattern's `Patterns` reaches all three seven times at the pin, from moq-net's -`auth.rs` and `model/origin.rs` and from `Patterns::rebase` itself. The crate's impls -translate already; what is missing is std's adaptor calling them. diff --git a/ts/Cargo.lock b/ts/Cargo.lock index 716de715c..ea1392743 100644 --- a/ts/Cargo.lock +++ b/ts/Cargo.lock @@ -222,6 +222,10 @@ version = "0.0.0" name = "lang-collections-fixture" version = "0.0.0" +[[package]] +name = "lang-collects-fixture" +version = "0.0.0" + [[package]] name = "lang-combinators-fixture" version = "0.0.0" diff --git a/ts/README.md b/ts/README.md index 043a77111..241df841a 100644 --- a/ts/README.md +++ b/ts/README.md @@ -386,6 +386,10 @@ each item's fields go into them in order, as `rs.tupleExtend(t, it, [rs.vecPart( rs.STRING_PART])`. The crate's own `Default + Extend` collection keeps the defaults stable Rust can't override: it reserves nothing, and takes each item by its `extend` of `Some(item)`, through `rs.ownPart`. Any other collection in one is refused. +The crate's own collection is collected by its own `FromIterator`, which `collect` and a +`collect` into a `Result` or an `Option` of it call with the iterator, as std's do, and std's +adaptors that take an `IntoIterator`, such as `flat_map`, `flatten`, `chain`, `zip`, and +`extend`, iterate it by its own `into_iter`. `clone` of one of std's iterators or adaptors is its `rs.Iter`'s `clone`, which reads on from where the original was, independently of it, as std's `Clone` does; one over a hash diff --git a/ts/fixtures/lang/collects/Cargo.toml b/ts/fixtures/lang/collects/Cargo.toml new file mode 100644 index 000000000..a8f892979 --- /dev/null +++ b/ts/fixtures/lang/collects/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "lang-collects-fixture" +description = "A part of the language rust2-ts translates, exercised against native Rust" +version = "0.0.0" +edition.workspace = true +license.workspace = true +publish = false + +[lib] +# The cdylib is the native side of the differential test, built for wasm32. +crate-type = ["lib", "cdylib"] + +[lints] +workspace = true diff --git a/ts/fixtures/lang/collects/expected/collects.Bag.ts b/ts/fixtures/lang/collects/expected/collects.Bag.ts new file mode 100644 index 000000000..d1ef06b79 --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Bag.ts @@ -0,0 +1,380 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import type * as Item from "./collects.Item.ts"; + +/** + * The crate's own collection, which reads its items only up to the first 0, dropping + * that one and leaving the rest in the iterator, which drops as `from_iter` returns. + */ +export class Bag { + items: rs.Vec; + + constructor(items: rs.Vec) { + this.items = items; + } + + [Symbol.dispose](): void { + rs.dropVec(this.items); + } +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Filter_iter_Rev_slice_Iter_u8_collects_collects_closure1_collects_collects_closure2(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Rev_slice_Iter_u8_collects_chains_closure2(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Skip_slice_Iter_u8_collects_chains_closure1(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_chains_closure0(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_chains_closure3(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_collects_closure0(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure0_closure0(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure2_closure0(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure4_closure0(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_Skip_vec_IntoIter_collects_Item(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + const _0: Bag = new Bag(items); + rs.drop(iter2); + return _0; +} + +export function fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure4_Result_never_u8(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure5_Option_never(iter: rs.Iter): Bag { + const iter2: rs.Iter = iter; + const items: rs.Vec = new rs.Vec(); + const iter3: rs.Iter = iter2; + while (true) { + const _8: Item.Item | rs.Done = iter3.next(); + if (_8 === rs.DONE) { + break; + } + const item: Item.Item = _8; + if (!(item.v === 0)) { + items.items.push(item); + } else { + item[Symbol.dispose](); + break; + } + } + const _17: Item.Item | undefined = rs.sliceFirst(rs.sliceFrom(items.items)); + if (_17 !== undefined) { + const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); + const part = items.items.length; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; + const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + _25.value.items.push(_26); + rs.refMutRelease(_25); + } + return new Bag(items); +} + +export function intoIter$iter_IntoIterator(self: Bag): rs.Iter { + return rs.vecIntoIter(self.items, rs.drop); +} + +export function intoIter$iter_IntoIterator_ref(self: Bag): rs.Iter { + return rs.iterSlice(self.items.items); +} + +//# sourceMappingURL=collects.Bag.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.Count.ts b/ts/fixtures/lang/collects/expected/collects.Count.ts new file mode 100644 index 000000000..c9ba1b0ef --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Count.ts @@ -0,0 +1,22 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import * as Down from "./collects.Down.ts"; + +/** What counts down from `n`, by the crate's own iterator. */ +export interface Count { + n: rs.u8; + log: rs.RefCell>; +} + +export function intoIter$iter_IntoIterator(self: Count): Down.Down { + const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); + const arg = self.n; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; + const _6: string = rs.fmtFormat(["count ", args2[0]]); + _5.value.items.push(_6); + rs.refMutRelease(_5); + return new Down.Down(self.n, self.log); +} + +//# sourceMappingURL=collects.Count.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.Down.ts b/ts/fixtures/lang/collects/expected/collects.Down.ts new file mode 100644 index 000000000..6d06a808e --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Down.ts @@ -0,0 +1,44 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; + +/** The crate's own iterator, which logs each read and its drop. */ +export class Down { + n: rs.u8; + log: rs.RefCell>; + + constructor(n: rs.u8, log: rs.RefCell>) { + this.n = n; + this.log = log; + } + + [Symbol.dispose](): void { + drop$ops_Drop(this); + } +} + +export function next$iter_Iterator(self: Down): rs.u8 | rs.Done { + const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); + const arg = self.n; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; + const _6: string = rs.fmtFormat(["next ", args2[0]]); + _5.value.items.push(_6); + rs.refMutRelease(_5); + const _15: rs.u8 | undefined = rs.u8CheckedSub(self.n, 1); + if (_15 !== undefined) { + self.n = _15; + return self.n; + } + return rs.DONE; +} + +export function drop$ops_Drop(self: Down): void { + const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); + const arg = self.n; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; + const _6: string = rs.fmtFormat(["down dropped at ", args2[0]]); + _5.value.items.push(_6); + rs.refMutRelease(_5); +} + +//# sourceMappingURL=collects.Down.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.Item.ts b/ts/fixtures/lang/collects/expected/collects.Item.ts new file mode 100644 index 000000000..17b0d1fba --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Item.ts @@ -0,0 +1,29 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; + +/** Logs its byte as it drops. */ +export class Item { + v: rs.u8; + log: rs.RefCell>; + + constructor(v: rs.u8, log: rs.RefCell>) { + this.v = v; + this.log = log; + } + + [Symbol.dispose](): void { + drop$ops_Drop(this); + } +} + +export function drop$ops_Drop(self: Item): void { + const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); + const arg = self.v; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; + const _6: string = rs.fmtFormat(["drop ", args2[0]]); + _5.value.items.push(_6); + rs.refMutRelease(_5); +} + +//# sourceMappingURL=collects.Item.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.Stack.ts b/ts/fixtures/lang/collects/expected/collects.Stack.ts new file mode 100644 index 000000000..c0dc36d81 --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Stack.ts @@ -0,0 +1,49 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import * as Down from "./collects.Down.ts"; +import type * as Item from "./collects.Item.ts"; + +/** + * The crate's own collection of any type, which keeps its items in reverse and counts + * them, so a `collect` that skipped it would differ. + */ +export class Stack { + items: rs.VecOf; + count: rs.usize; + + constructor(items: rs.VecOf, count: rs.usize) { + this.items = items; + this.count = count; + } + + [Symbol.dispose](): void { + rs.dropVec(this.items as rs.Vec); + } +} + +export function fromIter$iter_FromIterator_collects_Item_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_collects_closure8(iter: rs.Iter): Stack { + const items: rs.Vec = rs.iterToVec(iter, undefined, 8, true); + rs.sliceReverse(rs.sliceFrom(items.items)); + return new Stack(items, items.items.length); +} + +export function fromIter$iter_FromIterator_u16_u16_iter_Map_slice_Iter_u8_collects_collects_closure7(iter: rs.Iter): Stack { + const items: rs.Vec = rs.iterToVec(iter, undefined, 2, true); + rs.sliceReverse(rs.sliceFrom(items.items)); + return new Stack(items, items.items.length); +} + +export function fromIter$iter_FromIterator_u8_u8_collects_Down(iter: Down.Down): Stack { + const items: rs.ByteVec = rs.iterToByteVec(rs.iterFrom(iter, Down.next$iter_Iterator, rs.drop), "next"); + rs.byteSliceView(rs.byteVecSlice(items)).reverse(); + return new Stack(items, items.length); +} + +export function fromIter$iter_FromIterator_u8_u8_iter_Take_mut_collects_Down(iter: rs.Iter): Stack { + const items: rs.ByteVec = rs.iterToByteVec(iter, "next"); + rs.byteSliceView(rs.byteVecSlice(items)).reverse(); + return new Stack(items, items.length); +} + +//# sourceMappingURL=collects.Stack.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.ts b/ts/fixtures/lang/collects/expected/collects.ts new file mode 100644 index 000000000..16b386944 --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.ts @@ -0,0 +1,356 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import * as Bag from "./collects.Bag.ts"; +import * as Count from "./collects.Count.ts"; +import * as Down from "./collects.Down.ts"; +import * as Item from "./collects.Item.ts"; +import * as Stack from "./collects.Stack.ts"; +import { then$0bmzd6l } from "./core/bool.ts"; +import { map$1hm93qk as option_map$1hm93qk, map$0a0rmxp as option_map$0a0rmxp, mapOr$0vxw5sq as option_mapOr$0vxw5sq } from "./core/option.ts"; +import { put } from "./harness.ts"; + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$Option_ref_collects_Item(out: rs.ByteVec, log: rs.RefCell>, values: Item.Item | undefined): void { + const part = rs.iterToByteVec(rs.iterMap(rs.iterOption(values), (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$array0_ref_collects_Item(out: rs.ByteVec, log: rs.RefCell>, values: Item.Item[]): void { + const part = rs.iterToByteVec(rs.iterMap(rs.iterSlice(values), (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$iter_Chain_slice_Iter_collects_Item_slice_Iter_collects_Item(out: rs.ByteVec, log: rs.RefCell>, values: rs.Iter): void { + const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$iter_Flatten_option_Iter_collects_Bag(out: rs.ByteVec, log: rs.RefCell>, values: rs.Iter): void { + const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { + return item.v; + }), "next"); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$iter_Skip_iter_Flatten_slice_Iter_collects_Bag(out: rs.ByteVec, log: rs.RefCell>, values: rs.Iter): void { + const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { + return item.v; + }), "next"); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$iter_StepBy_iter_FlatMap_iter_Rev_ops_Range_usize_ref_collects_Bag_collects_flattens_closure5(out: rs.ByteVec, log: rs.RefCell>, values: rs.Iter): void { + const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { + return item.v; + }), "next"); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$iter_Take_slice_Iter_collects_Item(out: rs.ByteVec, log: rs.RefCell>, values: rs.Iter): void { + const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$ref_Vec_collects_Item(out: rs.ByteVec, log: rs.RefCell>, values: rs.Vec): void { + const part = rs.iterToByteVec(rs.iterMap(rs.iterSlice(values.items), (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** What `values` reads, each at most `limit`, and the log. */ +export function write$ref_collects_Bag(out: rs.ByteVec, log: rs.RefCell>, values: Bag.Bag): void { + const part = rs.iterToByteVec(rs.iterMap(Bag.intoIter$iter_IntoIterator_ref(values), (item: Item.Item): rs.u8 => { + return item.v; + }), undefined, true); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args2[0]])); + const _29: rs.RefCell> = rs.refCellBorrowMut(log); + put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); + rs.refMutRelease(_29); +} + +/** + * `collect` into the crate's collections, which read their source lazily up to its first + * 0, and into a `Result` or an `Option` of one, which stops at its first `Err` or `None`. + */ +export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { + const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); + const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { + const _6: rs.RefCell> = rs.refCellBorrowMut(log); + const args12: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; + const _7: string = rs.fmtFormat(["make ", args12[0]]); + _6.value.items.push(_7); + rs.refMutRelease(_6); + return new Item.Item(v, log); + }; + const k: rs.usize = kind >> 3 as rs.usize; + const _12: rs.u8 = rs.u8Rem(kind, 8); + if (_12 === 0) { + const bag: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_collects_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_214: rs.u8): Item.Item => { + return item(_214); + })); + write$ref_collects_Bag(out, log, bag); + bag[Symbol.dispose](); + } else if (_12 === 1) { + const bag2: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Filter_iter_Rev_slice_Iter_u8_collects_collects_closure1_collects_collects_closure2(rs.iterMap(rs.iterFilter(rs.iterRev(rs.iterSlice(rs.byteSliceView(data))), (_212: rs.u8): boolean => { + return rs.u8Rem(_212, 3) !== 1; + }), (_213: rs.u8): Item.Item => { + return item(_213); + })); + const _31: rs.Iter = rs.iterTake(rs.iterSlice(bag2.items.items), k); + write$iter_Take_slice_Iter_collects_Item(out, log, _31); + bag2[Symbol.dispose](); + } else if (_12 === 2) { + const bag3: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Skip_vec_IntoIter_collects_Item(rs.iterSkip(rs.vecIntoIter(rs.iterToVec(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_211: rs.u8): Item.Item => { + return item(_211); + }), undefined, 8, true), rs.drop), k, rs.drop)); + write$ref_collects_Bag(out, log, bag3); + bag3[Symbol.dispose](); + } else if (_12 === 3) { + const bag4: rs.Result = rs.iterCollectResult(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_210: rs.u8): rs.Result => { + const v6: rs.u8 = _210; + if (!(240 <= v6)) { + return rs.Ok(item(v6)); + } + return rs.Err(v6); + }), (values: rs.Iter) => Bag.fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure4_Result_never_u8(values), rs.drop); + if (bag4.ok) { + const bag5: Bag.Bag = bag4.value; + write$ref_collects_Bag(out, log, bag5); + bag5[Symbol.dispose](); + } else { + const arg4 = bag4.error; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg4, f)]; + put(out, rs.fmtFormat(["err ", args2[0]])); + } + } else if (_12 === 4) { + const bag6: Bag.Bag | undefined = rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_28: rs.u8): Item.Item | undefined => { + const v5: rs.u8 = _28; + return then$0bmzd6l(v5 < 240, (): Item.Item => { + return item(v5); + }); + }), (values: rs.Iter) => Bag.fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure5_Option_never(values), rs.drop); + const part4 = option_map$0a0rmxp(bag6, (bag7: Bag.Bag): rs.usize => { + return bag7.items.items.length; + }); + const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part4, f, rs.usizeDebug)]; + put(out, rs.fmtFormat([args4[0]])); + const _89: rs.Iter = rs.iterFlatten(rs.iterOption(bag6), (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator_ref(value), true); + write$iter_Flatten_option_Iter_collects_Bag(out, log, _89); + rs.drop(bag6); + } else if (_12 === 5) { + const stack: Stack.Stack = Stack.fromIter$iter_FromIterator_u16_u16_iter_Map_slice_Iter_u8_collects_collects_closure7(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): rs.u16 => { + return rs.u16Mul(_2 as rs.u16, 3); + })); + const part3 = stack.items as rs.Vec; + const _105: rs.Fmt = (f: rs.Formatter) => rs.fmtList(part3.items, f, rs.u16Debug); + const arg3 = stack.count; + const args6: rs.Fmt[] = [_105, (f: rs.Formatter) => rs.usizeDisplay(arg3, f)]; + put(out, rs.fmtFormat([args6[0], " ", args6[1]])); + const stack2: Stack.Stack = Stack.fromIter$iter_FromIterator_collects_Item_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_collects_closure8(rs.iterMap(rs.iterTake(rs.iterSlice(rs.byteSliceView(data)), k), (_22: rs.u8): Item.Item => { + return item(_22); + })); + write$ref_Vec_collects_Item(out, log, stack2.items as rs.Vec); + stack2[Symbol.dispose](); + } else if (_12 === 6) { + const n: rs.u8 = option_mapOr$0vxw5sq(rs.byteSliceFirst(data), 0, (v2: rs.u8): rs.u8 => { + return rs.u8Rem(v2, 9); + }); + const stack3: Stack.Stack = Stack.fromIter$iter_FromIterator_u8_u8_collects_Down(new Down.Down(n, log)); + const part = stack3.items as rs.ByteVec; + const _133: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug); + const arg = stack3.count; + const args8: rs.Fmt[] = [_133, (f: rs.Formatter) => rs.usizeDisplay(arg, f)]; + put(out, rs.fmtFormat([args8[0], " ", args8[1]])); + const down: Down.Down = new Down.Down(n, log); + const stack4: Stack.Stack = Stack.fromIter$iter_FromIterator_u8_u8_iter_Take_mut_collects_Down(rs.iterTake(rs.iterFrom(down, Down.next$iter_Iterator), k)); + const _153: rs.u8 | undefined = rs.iterToOption(Down.next$iter_Iterator(down)); + const part2 = stack4.items as rs.ByteVec; + const _156: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug); + const arg2 = stack4.count; + const args10: rs.Fmt[] = [_156, (f: rs.Formatter) => rs.usizeDisplay(arg2, f), (f: rs.Formatter) => rs.fmtOption(_153, f, rs.u8Debug)]; + put(out, rs.fmtFormat([args10[0], " ", args10[1], " ", args10[2]])); + down[Symbol.dispose](); + } + write$array0_ref_collects_Item(out, log, []); +} + +/** + * `flat_map` and `flatten` over the crate's collections, by value and by reference, and + * over one whose iterator is the crate's own, read only so far. + */ +export function flattens(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { + const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); + const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { + const _6: rs.RefCell> = rs.refCellBorrowMut(log); + const args8: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; + const _7: string = rs.fmtFormat(["make ", args8[0]]); + _6.value.items.push(_7); + rs.refMutRelease(_6); + return new Item.Item(v, log); + }; + const k: rs.usize = kind >> 3 as rs.usize; + const _11: rs.u8 = rs.u8Rem(kind, 8); + if (_11 === 0) { + const it: rs.Iter = rs.iterFlatMap(rs.byteSliceChunks(data, 3), (chunk3: rs.ByteSlice): Bag.Bag => { + return Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure0_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(chunk3)), (_28: rs.u8): Item.Item => { + return item(_28); + })); + }, (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator(value), true); + const front: rs.Vec = rs.iterToVec(rs.iterTake(rs.iterBorrow(it), k, rs.drop), "next", 8); + const back: rs.u8 | undefined = option_map$1hm93qk(rs.iterToOption(it.nextBack()), (item3: Item.Item): rs.u8 => { + const _013: rs.u8 = item3.v; + item3[Symbol.dispose](); + return _013; + }); + const _27: rs.RefCell> = rs.refCellBorrowMut(log); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(back, f, rs.u8Debug)]; + const _29: string = rs.fmtFormat(["back ", args2[0]]); + _27.value.items.push(_29); + rs.refMutRelease(_27); + rs.drop(it); + write$ref_Vec_collects_Item(out, log, front); + rs.dropVec(front); + } else if (_11 === 1) { + const bags: rs.Vec = rs.iterToVec(rs.iterMap(rs.byteSliceChunks(data, 2), (chunk2: rs.ByteSlice): Bag.Bag => { + return Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure2_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(chunk2)), (_26: rs.u8): Item.Item => { + return item(_26); + })); + }), undefined, 12, true); + const _50: rs.Iter = rs.iterSkip(rs.iterFlatten(rs.iterSlice(bags.items), (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator_ref(value), true), k); + write$iter_Skip_iter_Flatten_slice_Iter_collects_Bag(out, log, _50); + const _57: rs.Iter = rs.iterFlatten(rs.vecIntoIter(bags, rs.drop), (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator(value), true); + const found: Item.Item | undefined = rs.iterFind(_57, (item2: Item.Item): boolean => { + return (item2.v as rs.usize) === k; + }, rs.drop); + rs.drop(_57); + write$Option_ref_collects_Item(out, log, found); + rs.drop(found); + } else if (_11 === 2) { + const bags2: rs.Vec = rs.iterToVec(rs.iterMap(rs.byteSliceChunks(data, 2), (chunk: rs.ByteSlice): Bag.Bag => { + return Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_flattens_closure4_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(chunk)), (_24: rs.u8): Item.Item => { + return item(_24); + })); + }), undefined, 12, true); + const _72: rs.Iter = rs.iterStepBy(rs.iterFlatMap(rs.iterRev(new rs.Range(0, bags2.items.length)), (i: rs.usize): Bag.Bag => { + return bags2.items[rs.idx(bags2.items, i)]; + }, (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator_ref(value), true), rs.usizeAdd(k, 1)); + write$iter_StepBy_iter_FlatMap_iter_Rev_ops_Range_usize_ref_collects_Bag_collects_flattens_closure5(out, log, _72); + rs.dropVec(bags2); + } else if (_11 === 3) { + const part2 = rs.iterToByteVec(rs.iterTake(rs.iterFlatMap(rs.iterSlice(rs.byteSliceView(data)), (_23: rs.u8): Count.Count => { + return { n: rs.u8Rem(_23, 5), log }; + }, (value: Count.Count) => rs.iterFrom(Count.intoIter$iter_IntoIterator(value), Down.next$iter_Iterator, rs.drop), true), k), "next"); + const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args4[0]])); + } else if (_11 === 4) { + const part = rs.iterFold(rs.iterFlatten(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): Count.Count => { + return { n: rs.u8Rem(_2, 4), log }; + }), (value: Count.Count) => rs.iterFrom(Count.intoIter$iter_IntoIterator(value), Down.next$iter_Iterator, rs.drop), true), 0, (sum2: rs.u32, v3: rs.u8): rs.u32 => { + return rs.u32Add(sum2, v3 as rs.u32); + }, true); + const args6: rs.Fmt[] = [(f: rs.Formatter) => rs.u32Display(part, f)]; + put(out, rs.fmtFormat([args6[0]])); + } + write$array0_ref_collects_Item(out, log, []); +} + +/** `chain`, `zip`, and `extend` of the crate's collections. */ +export function chains(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { + const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); + const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { + const _6: rs.RefCell> = rs.refCellBorrowMut(log); + const args6: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; + const _7: string = rs.fmtFormat(["make ", args6[0]]); + _6.value.items.push(_7); + rs.refMutRelease(_6); + return new Item.Item(v, log); + }; + const k: rs.usize = kind >> 1 as rs.usize; + if (rs.u8Rem(kind, 2) === 0) { + const bag: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_chains_closure0(rs.iterMap(rs.iterTake(rs.iterSlice(rs.byteSliceView(data)), k), (_26: rs.u8): Item.Item => { + return item(_26); + })); + const other: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Skip_slice_Iter_u8_collects_chains_closure1(rs.iterMap(rs.iterSkip(rs.iterSlice(rs.byteSliceView(data)), k), (_210: rs.u8): Item.Item => { + return item(_210); + })); + const _27: rs.Iter = rs.iterChain(rs.iterSlice(bag.items.items), Bag.intoIter$iter_IntoIterator_ref(other)); + write$iter_Chain_slice_Iter_collects_Item_slice_Iter_collects_Item(out, log, _27); + const items: rs.Vec = rs.iterToVec(rs.iterChain(Bag.intoIter$iter_IntoIterator(bag), Bag.intoIter$iter_IntoIterator(other)), "fold", 8, true); + const more: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Rev_slice_Iter_u8_collects_chains_closure2(rs.iterMap(rs.iterRev(rs.iterSlice(rs.byteSliceView(data))), (_211: rs.u8): Item.Item => { + return item(_211); + })); + rs.iterExtend(items, Bag.intoIter$iter_IntoIterator(more), "fold", 8, true); + write$ref_Vec_collects_Item(out, log, items); + rs.dropVec(items); + } else { + const bag2: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_chains_closure3(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): Item.Item => { + return item(_2); + })); + const part = rs.iterToVec(rs.iterMap(rs.iterZip(rs.iterSlice(rs.byteSliceView(data)), rs.iterFrom(Count.intoIter$iter_IntoIterator({ n: 4, log }), Down.next$iter_Iterator, rs.drop)), (_24: [rs.u8, rs.u8]): [rs.u8, rs.u8] => { + return [_24[0], _24[1]] as [rs.u8, rs.u8]; + }), "next", 2); + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(part.items, f, (value: [rs.u8, rs.u8], f: rs.Formatter) => rs.fmtTuple([(f: rs.Formatter) => rs.u8Debug(value[0], f), (f: rs.Formatter) => rs.u8Debug(value[1], f)], f))]; + put(out, rs.fmtFormat([args2[0]])); + const part2 = rs.iterToByteVec(rs.iterMap(rs.iterZip(new rs.Range(0, k), Bag.intoIter$iter_IntoIterator(bag2), "len", undefined, rs.drop), (_25: [rs.usize, Item.Item]): rs.u8 => { + const item2: Item.Item = _25[1]; + const _04: rs.u8 = item2.v; + item2[Symbol.dispose](); + return _04; + }), "fold", true); + const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)]; + put(out, rs.fmtFormat([args4[0]])); + } + write$array0_ref_collects_Item(out, log, []); +} + +//# sourceMappingURL=collects.ts.map diff --git a/ts/fixtures/lang/collects/expected/core/bool.ts b/ts/fixtures/lang/collects/expected/core/bool.ts new file mode 100644 index 000000000..65738a9fe --- /dev/null +++ b/ts/fixtures/lang/collects/expected/core/bool.ts @@ -0,0 +1,12 @@ +// Generated by rust2-ts. Do not edit. + +import type * as Item from "../collects.Item.ts"; + +export function then$0bmzd6l(self: boolean, f: () => Item.Item): Item.Item | undefined { + if (!self) { + return undefined; + } + return f(); +} + +//# sourceMappingURL=bool.ts.map diff --git a/ts/fixtures/lang/collects/expected/core/option.ts b/ts/fixtures/lang/collects/expected/core/option.ts new file mode 100644 index 000000000..c27e0b933 --- /dev/null +++ b/ts/fixtures/lang/collects/expected/core/option.ts @@ -0,0 +1,28 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "../rs.ts"; +import type * as Bag from "../collects.Bag.ts"; +import type * as Item from "../collects.Item.ts"; + +export function map$1hm93qk(self: Item.Item | undefined, f: (a0: Item.Item) => rs.u8): rs.u8 | undefined { + if (self === undefined) { + return undefined; + } + return f(self); +} + +export function map$0a0rmxp(self: Bag.Bag | undefined, f: (a0: Bag.Bag) => rs.usize): rs.usize | undefined { + if (self === undefined) { + return undefined; + } + return f(self); +} + +export function mapOr$0vxw5sq(self: rs.u8 | undefined, default_: rs.u8, f: (a0: rs.u8) => rs.u8): rs.u8 { + if (self === undefined) { + return default_; + } + return f(self); +} + +//# sourceMappingURL=option.ts.map diff --git a/ts/fixtures/lang/collects/expected/harness.ts b/ts/fixtures/lang/collects/expected/harness.ts new file mode 100644 index 000000000..610e5cf7d --- /dev/null +++ b/ts/fixtures/lang/collects/expected/harness.ts @@ -0,0 +1,46 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import { cases } from "./lib.ts"; + +/** Run one case. */ +export function run(input: rs.ByteSlice): rs.ByteVec { + const out: rs.ByteVec = new rs.ByteVec(); + if (!(input.length >= 3)) { + return out; + } + const cases_: rs.Vec<[string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]> = cases(); + cases_.items[rs.idx(cases_.items, rs.usizeRem(((input.data[input.start] << 8) | input.data[input.start + 1]) as rs.usize, cases_.items.length))][1](input.data[input.start + 2], new rs.ByteSlice(input.data, input.start + 3, input.length - 3), out); + return out; +} + +/** + * The first two bytes, as one big-endian number, that pick the case named `name`, which + * `lang.ts` targets by. + */ +export function op(name: string): rs.u16 { + const _11: rs.usize | undefined = rs.iterPosition(rs.iterSlice(cases().items), (_2: [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]): boolean => { + return _2[0] === name; + }); + if (_11 !== undefined) { + const _20: rs.Result = rs.u16TryFrom(_11); + if (_20.ok) { + if ((_20.value >> 8) !== 255) { + return _20.value; + } + } + const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtPad(f, name)]; + rs.panicFmt(["case ", args4[0], " is past what two bytes pick"]); + } else { + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtPad(f, name)]; + rs.panicFmt(["no case ", args2[0]]); + } +} + +/** Write `s` and the byte no UTF-8 holds, which ends it. */ +export function put(out: rs.ByteVec, s: string): void { + rs.byteVecExtendFromSlice(out, rs.stringAsBytes(s)); + rs.byteVecPush(out, 255); +} + +//# sourceMappingURL=harness.ts.map diff --git a/ts/fixtures/lang/collects/expected/lib.ts b/ts/fixtures/lang/collects/expected/lib.ts new file mode 100644 index 000000000..ac3ae47b0 --- /dev/null +++ b/ts/fixtures/lang/collects/expected/lib.ts @@ -0,0 +1,14 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import { collects, flattens, chains } from "./collects.ts"; + +/** + * Each case's name and what it runs. The first two bytes, big-endian, pick one modulo + * their count, so a case added at the end moves no other. + */ +export function cases(): rs.Vec<[string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]> { + return rs.vecFrom([["collects::collects", collects as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["collects::flattens", flattens as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["collects::chains", chains as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]]); +} + +//# sourceMappingURL=lib.ts.map diff --git a/ts/fixtures/lang/collects/src/collects.rs b/ts/fixtures/lang/collects/src/collects.rs new file mode 100644 index 000000000..143376486 --- /dev/null +++ b/ts/fixtures/lang/collects/src/collects.rs @@ -0,0 +1,283 @@ +//! The crate's own collections, which std's adaptors reach by their `FromIterator` and +//! `IntoIterator` impls: `collect`, and `collect` into a `Result` or an `Option` of one; +//! `flat_map` and `flatten` over them, by value and by reference, and over one whose +//! iterator is the crate's own; and `chain`, `zip`, and `Vec::extend` of one. Each item +//! logs as it is made, read, and dropped, so the log shows what each reads, how far, and +//! when what it left drops. + +use std::cell::RefCell; + +use crate::harness::put; + +type Log = RefCell>; + +/// Logs its byte as it drops. +struct Item<'a> { + v: u8, + log: &'a Log, +} + +impl Drop for Item<'_> { + fn drop(&mut self) { + self.log.borrow_mut().push(format!("drop {}", self.v)); + } +} + +/// The crate's own collection, which reads its items only up to the first 0, dropping +/// that one and leaving the rest in the iterator, which drops as `from_iter` returns. +struct Bag<'a> { + items: Vec>, +} + +impl<'a> FromIterator> for Bag<'a> { + fn from_iter>>(iter: I) -> Self { + let mut iter = iter.into_iter(); + let mut items = Vec::new(); + for item in iter.by_ref() { + if item.v == 0 { + break; + } + items.push(item); + } + if let Some(item) = items.first() { + item.log.borrow_mut().push(format!("bag of {}", items.len())); + } + Bag { items } + } +} + +impl<'a> IntoIterator for Bag<'a> { + type Item = Item<'a>; + type IntoIter = std::vec::IntoIter>; + + fn into_iter(self) -> Self::IntoIter { + self.items.into_iter() + } +} + +impl<'a, 'b> IntoIterator for &'b Bag<'a> { + type Item = &'b Item<'a>; + type IntoIter = std::slice::Iter<'b, Item<'a>>; + + fn into_iter(self) -> Self::IntoIter { + self.items.iter() + } +} + +/// The crate's own collection of any type, which keeps its items in reverse and counts +/// them, so a `collect` that skipped it would differ. +struct Stack { + items: Vec, + count: usize, +} + +impl FromIterator for Stack { + fn from_iter>(iter: I) -> Self { + let mut items: Vec = iter.into_iter().collect(); + items.reverse(); + let count = items.len(); + Stack { items, count } + } +} + +/// What counts down from `n`, by the crate's own iterator. +struct Count<'a> { + n: u8, + log: &'a Log, +} + +impl<'a> IntoIterator for Count<'a> { + type Item = u8; + type IntoIter = Down<'a>; + + fn into_iter(self) -> Down<'a> { + self.log.borrow_mut().push(format!("count {}", self.n)); + Down { + n: self.n, + log: self.log, + } + } +} + +/// The crate's own iterator, which logs each read and its drop. +struct Down<'a> { + n: u8, + log: &'a Log, +} + +impl Iterator for Down<'_> { + type Item = u8; + + fn next(&mut self) -> Option { + self.log.borrow_mut().push(format!("next {}", self.n)); + self.n = self.n.checked_sub(1)?; + Some(self.n) + } +} + +impl Drop for Down<'_> { + fn drop(&mut self) { + self.log.borrow_mut().push(format!("down dropped at {}", self.n)); + } +} + +/// What `values` reads, each at most `limit`, and the log. +fn write<'a>(out: &mut Vec, log: &Log, values: impl IntoIterator>) { + let values: Vec = values.into_iter().map(|item| item.v).collect(); + put(out, &format!("{values:?}")); + put(out, &log.borrow_mut().drain(..).collect::>().join(", ")); +} + +/// What makes an `Item` of each byte, logging it, and how far a case reads. +macro_rules! setup { + ($log:ident, $item:ident, $k:ident = $kind:ident >> $shift:literal) => { + let $log = Log::default(); + let $item = |v: u8| { + $log.borrow_mut().push(format!("make {v}")); + Item { v, log: &$log } + }; + let $k = usize::from($kind >> $shift); + }; +} + +/// `collect` into the crate's collections, which read their source lazily up to its first +/// 0, and into a `Result` or an `Option` of one, which stops at its first `Err` or `None`. +pub fn collects(kind: u8, data: &[u8], out: &mut Vec) { + setup!(log, item, k = kind >> 3); + match kind % 8 { + 0 => { + let bag: Bag = data.iter().map(|&v| item(v)).collect(); + write(out, &log, &bag); + } + 1 => { + let bag = data + .iter() + .rev() + .filter(|&&v| v % 3 != 1) + .map(|&v| item(v)) + .collect::(); + write(out, &log, bag.items.iter().take(k)); + } + 2 => { + let items: Vec = data.iter().map(|&v| item(v)).collect(); + let bag: Bag = items.into_iter().skip(k).collect(); + write(out, &log, &bag); + } + 3 => { + let bag: Result = data + .iter() + .map(|&v| match v { + 0xf0.. => Err(v), + _ => Ok(item(v)), + }) + .collect(); + match bag { + Ok(bag) => write(out, &log, &bag), + Err(e) => put(out, &format!("err {e}")), + } + } + 4 => { + let bag: Option = data.iter().map(|&v| (v < 0xf0).then(|| item(v))).collect(); + let len = bag.as_ref().map(|bag| bag.items.len()); + put(out, &format!("{len:?}")); + write(out, &log, bag.iter().flatten()); + } + // The crate's own generic collection. + 5 => { + let stack: Stack = data.iter().map(|&v| u16::from(v) * 3).collect(); + put(out, &format!("{:?} {}", stack.items, stack.count)); + let stack: Stack = data.iter().take(k).map(|&v| item(v)).collect(); + write(out, &log, &stack.items); + } + // Of the crate's own iterator, by value and borrowed. + 6 => { + let n = data.first().map_or(0, |v| v % 9); + let stack: Stack = Down { n, log: &log }.collect(); + put(out, &format!("{:?} {}", stack.items, stack.count)); + let mut down = Down { n, log: &log }; + let stack: Stack = down.by_ref().take(k).collect(); + put(out, &format!("{:?} {} {:?}", stack.items, stack.count, down.next())); + } + _ => {} + } + write(out, &log, []); +} + +/// `flat_map` and `flatten` over the crate's collections, by value and by reference, and +/// over one whose iterator is the crate's own, read only so far. +pub fn flattens(kind: u8, data: &[u8], out: &mut Vec) { + setup!(log, item, k = kind >> 3); + match kind % 8 { + // Read up to `k`, then from the back. + 0 => { + let mut it = data + .chunks(3) + .flat_map(|chunk| chunk.iter().map(|&v| item(v)).collect::()); + let front: Vec = it.by_ref().take(k).collect(); + let back = it.next_back().map(|item| item.v); + log.borrow_mut().push(format!("back {back:?}")); + drop(it); + write(out, &log, &front); + } + 1 => { + let bags: Vec = data + .chunks(2) + .map(|chunk| chunk.iter().map(|&v| item(v)).collect()) + .collect(); + write(out, &log, bags.iter().flatten().skip(k)); + let found = bags.into_iter().flatten().find(|item| usize::from(item.v) == k); + write(out, &log, found.as_ref()); + } + 2 => { + let bags: Vec = data + .chunks(2) + .map(|chunk| chunk.iter().map(|&v| item(v)).collect()) + .collect(); + write(out, &log, (0..bags.len()).rev().flat_map(|i| &bags[i]).step_by(k + 1)); + } + // The crate's own iterator, which drops where std's adaptor ends. + 3 => { + let counts: Vec = data + .iter() + .flat_map(|&v| Count { n: v % 5, log: &log }) + .take(k) + .collect(); + put(out, &format!("{counts:?}")); + } + 4 => { + let counts = data.iter().map(|&v| Count { n: v % 4, log: &log }); + let sum = counts.flatten().fold(0u32, |sum, v| sum + u32::from(v)); + put(out, &format!("{sum}")); + } + _ => {} + } + write(out, &log, []); +} + +/// `chain`, `zip`, and `extend` of the crate's collections. +pub fn chains(kind: u8, data: &[u8], out: &mut Vec) { + setup!(log, item, k = kind >> 1); + match kind % 2 { + 0 => { + let bag: Bag = data.iter().take(k).map(|&v| item(v)).collect(); + let other: Bag = data.iter().skip(k).map(|&v| item(v)).collect(); + write(out, &log, bag.items.iter().chain(&other)); + let mut items: Vec = bag.into_iter().chain(other).collect(); + let more: Bag = data.iter().rev().map(|&v| item(v)).collect(); + items.extend(more); + write(out, &log, &items); + } + _ => { + let bag: Bag = data.iter().map(|&v| item(v)).collect(); + let pairs: Vec<(u8, u8)> = data + .iter() + .zip(Count { n: 4, log: &log }) + .map(|(&a, b)| (a, b)) + .collect(); + put(out, &format!("{pairs:?}")); + let zipped: Vec = (0..k).zip(bag).map(|(_, item)| item.v).collect(); + put(out, &format!("{zipped:?}")); + } + } + write(out, &log, []); +} diff --git a/ts/fixtures/lang/collects/src/lib.rs b/ts/fixtures/lang/collects/src/lib.rs new file mode 100644 index 000000000..2ef26d686 --- /dev/null +++ b/ts/fixtures/lang/collects/src/lib.rs @@ -0,0 +1,23 @@ +//! A part of the language the driver translates, exercised against native Rust: what +//! each of its modules says. + +mod collects; +#[path = "../../harness.rs"] +pub mod harness; +#[cfg(target_arch = "wasm32")] +#[path = "../../../wasm.rs"] +mod wasm; +#[cfg(target_arch = "wasm32")] +use harness::run as entry; + +use harness::Case; + +/// Each case's name and what it runs. The first two bytes, big-endian, pick one modulo +/// their count, so a case added at the end moves no other. +fn cases() -> Vec<(&'static str, Case)> { + vec![ + ("collects::collects", collects::collects), + ("collects::flattens", collects::flattens), + ("collects::chains", collects::chains), + ] +} diff --git a/ts/fixtures/lang/collects/ts.toml b/ts/fixtures/lang/collects/ts.toml new file mode 100644 index 000000000..d4f3cf963 --- /dev/null +++ b/ts/fixtures/lang/collects/ts.toml @@ -0,0 +1,2 @@ +package = "lang-collects-fixture" +roots = ["harness::run", "harness::op"] diff --git a/ts/src/lower/iter.rs b/ts/src/lower/iter.rs index 0f9bdd8cb..0a4ca63bd 100644 --- a/ts/src/lower/iter.rs +++ b/ts/src/lower/iter.rs @@ -514,6 +514,21 @@ fn own_collect<'tcx>( Some((vec, Expr::Sym(b.t.instance(instance)))) } +/// The crate's own impl of `tr::name`, a function of std's trait `tr`, for `args`, the type +/// it is for first, as a value: its `FromIterator` or `IntoIterator`, which std's adaptors +/// call. +fn own_impl<'tcx>(b: &mut Body<'_, '_, 'tcx>, tr: &str, name: &str, args: &[Ty<'tcx>], span: Span) -> Option { + let tcx = b.t.tcx; + // Over parameters, only a census's instance, which never runs, would call it. + if args.iter().any(|t| t.has_param() || t.has_aliases()) { + return None; + } + let f = super::collections::trait_fn(tcx, tr, name); + let args = tcx.mk_args_from_iter(args.iter().map(|&t| ty::GenericArg::from(t))); + let instance = Instance::try_resolve(tcx, b.t.typing_env_pub(), f, args).ok()??; + b.t.own(instance.def_id()).then(|| b.fn_value(f, args, span)) +} + /// Whether `ty` holds, by value rather than through a reference, an iterator of the crate with a /// method in `BY_VALUE` of its own, which std's consumers call where they take it. fn folds_own<'tcx>(b: &Body<'_, '_, 'tcx>, ty: Ty<'tcx>) -> bool { @@ -792,6 +807,10 @@ fn peeled_into_iter<'tcx>(b: &mut Body<'_, '_, 'tcx>, ty: Ty<'tcx>, value: Expr, None => value, }); } + // The crate's own collection, by its own `IntoIterator`, as the iterator that makes. + if let Some(into) = own_impl(b, "IntoIterator", "into_iter", &[ty], span) { + return into_iter(b, iter_of(b.t, ty)?, into.call(vec![value]), span); + } // What drops each item of one that owns them. let each = |b: &mut Body<'_, '_, 'tcx>, elem: Ty<'tcx>, mut args: Vec| { if owned && b.t.drops(elem) { @@ -1166,6 +1185,12 @@ pub fn call<'tcx>( }; return Some(Expr::rs("iterToOption", [item].into_iter().chain(none).collect())); } + // Into the crate's own collection, its `from_iter` of the iterator, as std's `collect` is. + if name == "collect" + && let Some(from_iter) = own_impl(b, "FromIterator", "from_iter", &[targ(1)?, item, targ(0)?], span) + { + return Some(from_iter.call(vec![first])); + } let recv = into_iter(b, self_ty, first, span)?; // `rs.iter(recv, ...args)`, or `peekable` of a `Peekable`'s own. let method = |name: &str, args: Vec| { @@ -2052,6 +2077,13 @@ fn collect<'tcx>( span: Span, ) -> Option { let tcx = b.t.tcx; + // The crate's own collection's `from_iter` of `iter`, which is the value of `from` but for + // the crate's own iterator, which `rs.iterFrom` wraps. + if own_next(b, from.peel_refs()).is_none() + && let Some(from_iter) = own_impl(b, "FromIterator", "from_iter", &[ty, item, from], span) + { + return Some(from_iter.call(vec![iter])); + } // `()`'s reads every item, each a `()` too, by `for_each`, which folds: from `undefined`, // so the result is typed as `()` is. if ty.is_unit() { @@ -2164,10 +2196,12 @@ fn collect<'tcx>( } /// Whether `ty`, collected through a `GenericShunt`, is given it: a tuple, whose `Extend` -/// is, or a `Result` or `Option` of one, which shunts it again. +/// is, the crate's own collection, whose `FromIterator` is, or a `Result` or `Option` of +/// one, which shunts it again. fn sees_shunt<'tcx>(t: &Translator<'_, 'tcx>, ty: Ty<'tcx>) -> bool { match ty.kind() { ty::Tuple(_) => true, + ty::Adt(adt, _) if t.own(adt.did()) => true, ty::Adt(_, args) if matches!(t.std_of(ty), Some(Std::Result | Std::Option)) => sees_shunt(t, args.type_at(0)), _ => false, } diff --git a/ts/tests/fixtures.rs b/ts/tests/fixtures.rs index b47fc389f..bbc881451 100644 --- a/ts/tests/fixtures.rs +++ b/ts/tests/fixtures.rs @@ -442,6 +442,7 @@ mod lang { chars, chunks, clones, + collects, collections, combinators, constants, From 8f3600e1dba53230a127bfb94777cbe49cf56001 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Wed, 4 Nov 2026 09:45:20 -0800 Subject: [PATCH 3/6] fix(ts): read a collect's GenericShunt on past an Err or None, as std's does std's `GenericShunt::next` reads on after a residual and replaces it, dropping the old one. The runtime's shunts stopped for good at the first, which a crate's own `FromIterator` that reads again can observe. Co-Authored-By: Claude Opus 5.5 --- .../lang/collects/expected/collects.Tries.ts | 36 ++++++ .../lang/collects/expected/collects.ts | 121 ++++++++++++------ .../lang/collects/expected/core/option.ts | 8 ++ ts/fixtures/lang/collects/src/collects.rs | 32 ++++- ts/runtime/rs/iter.ts | 28 ++-- ts/src/lower/iter.rs | 9 +- 6 files changed, 181 insertions(+), 53 deletions(-) create mode 100644 ts/fixtures/lang/collects/expected/collects.Tries.ts diff --git a/ts/fixtures/lang/collects/expected/collects.Tries.ts b/ts/fixtures/lang/collects/expected/collects.Tries.ts new file mode 100644 index 000000000..e08bd553e --- /dev/null +++ b/ts/fixtures/lang/collects/expected/collects.Tries.ts @@ -0,0 +1,36 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; +import type * as Item from "./collects.Item.ts"; + +/** + * The crate's own collection of the first three reads of its iterator, which reads on past + * a `None`, as nothing stops it from doing. + */ +export class Tries { + _0: rs.Vec; + + constructor(_0: rs.Vec) { + this._0 = _0; + } + + [Symbol.dispose](): void { + rs.dropVec(this._0); + } +} + +export function fromIter$iter_FromIterator_collects_Item_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure11_Option_never(iter: rs.Iter): Tries { + const iter2: rs.Iter = iter; + return new Tries(rs.iterToVec(rs.iterMap(new rs.Range(0, 3), (_2: rs.i32): Item.Item | undefined => { + return rs.iterToOption(iter2.next()); + }), undefined, 8, true)); +} + +export function fromIter$iter_FromIterator_u8_u8_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure10_Result_never_collects_Item(iter: rs.Iter): Tries { + const iter2: rs.Iter = iter; + return new Tries(rs.iterToVec(rs.iterMap(new rs.Range(0, 3), (_2: rs.i32): rs.u8 | undefined => { + return rs.iterToOption(iter2.next()); + }), undefined, 2, true)); +} + +//# sourceMappingURL=collects.Tries.ts.map diff --git a/ts/fixtures/lang/collects/expected/collects.ts b/ts/fixtures/lang/collects/expected/collects.ts index 16b386944..e8910eaf4 100644 --- a/ts/fixtures/lang/collects/expected/collects.ts +++ b/ts/fixtures/lang/collects/expected/collects.ts @@ -6,8 +6,9 @@ import * as Count from "./collects.Count.ts"; import * as Down from "./collects.Down.ts"; import * as Item from "./collects.Item.ts"; import * as Stack from "./collects.Stack.ts"; +import * as Tries from "./collects.Tries.ts"; import { then$0bmzd6l } from "./core/bool.ts"; -import { map$1hm93qk as option_map$1hm93qk, map$0a0rmxp as option_map$0a0rmxp, mapOr$0vxw5sq as option_mapOr$0vxw5sq } from "./core/option.ts"; +import { map$1hm93qk as option_map$1hm93qk, map$1yttib1 as option_map$1yttib1, map$0a0rmxp as option_map$0a0rmxp, mapOr$0vxw5sq as option_mapOr$0vxw5sq } from "./core/option.ts"; import { put } from "./harness.ts"; /** What `values` reads, each at most `limit`, and the log. */ @@ -126,8 +127,8 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { const _6: rs.RefCell> = rs.refCellBorrowMut(log); - const args12: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; - const _7: string = rs.fmtFormat(["make ", args12[0]]); + const args18: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; + const _7: string = rs.fmtFormat(["make ", args18[0]]); _6.value.items.push(_7); rs.refMutRelease(_6); return new Item.Item(v, log); @@ -135,91 +136,127 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const k: rs.usize = kind >> 3 as rs.usize; const _12: rs.u8 = rs.u8Rem(kind, 8); if (_12 === 0) { - const bag: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_collects_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_214: rs.u8): Item.Item => { - return item(_214); + const bag: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_collects_collects_closure0(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_218: rs.u8): Item.Item => { + return item(_218); })); write$ref_collects_Bag(out, log, bag); bag[Symbol.dispose](); } else if (_12 === 1) { - const bag2: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Filter_iter_Rev_slice_Iter_u8_collects_collects_closure1_collects_collects_closure2(rs.iterMap(rs.iterFilter(rs.iterRev(rs.iterSlice(rs.byteSliceView(data))), (_212: rs.u8): boolean => { - return rs.u8Rem(_212, 3) !== 1; - }), (_213: rs.u8): Item.Item => { - return item(_213); + const bag2: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Filter_iter_Rev_slice_Iter_u8_collects_collects_closure1_collects_collects_closure2(rs.iterMap(rs.iterFilter(rs.iterRev(rs.iterSlice(rs.byteSliceView(data))), (_216: rs.u8): boolean => { + return rs.u8Rem(_216, 3) !== 1; + }), (_217: rs.u8): Item.Item => { + return item(_217); })); const _31: rs.Iter = rs.iterTake(rs.iterSlice(bag2.items.items), k); write$iter_Take_slice_Iter_collects_Item(out, log, _31); bag2[Symbol.dispose](); } else if (_12 === 2) { - const bag3: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Skip_vec_IntoIter_collects_Item(rs.iterSkip(rs.vecIntoIter(rs.iterToVec(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_211: rs.u8): Item.Item => { - return item(_211); + const bag3: Bag.Bag = Bag.fromIter$iter_FromIterator_collects_Item_iter_Skip_vec_IntoIter_collects_Item(rs.iterSkip(rs.vecIntoIter(rs.iterToVec(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_215: rs.u8): Item.Item => { + return item(_215); }), undefined, 8, true), rs.drop), k, rs.drop)); write$ref_collects_Bag(out, log, bag3); bag3[Symbol.dispose](); } else if (_12 === 3) { - const bag4: rs.Result = rs.iterCollectResult(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_210: rs.u8): rs.Result => { - const v6: rs.u8 = _210; - if (!(240 <= v6)) { - return rs.Ok(item(v6)); + const bag4: rs.Result = rs.iterCollectResult(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_214: rs.u8): rs.Result => { + const v8: rs.u8 = _214; + if (!(240 <= v8)) { + return rs.Ok(item(v8)); } - return rs.Err(v6); + return rs.Err(v8); }), (values: rs.Iter) => Bag.fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure4_Result_never_u8(values), rs.drop); if (bag4.ok) { const bag5: Bag.Bag = bag4.value; write$ref_collects_Bag(out, log, bag5); bag5[Symbol.dispose](); } else { - const arg4 = bag4.error; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg4, f)]; + const arg5 = bag4.error; + const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg5, f)]; put(out, rs.fmtFormat(["err ", args2[0]])); } } else if (_12 === 4) { - const bag6: Bag.Bag | undefined = rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_28: rs.u8): Item.Item | undefined => { - const v5: rs.u8 = _28; - return then$0bmzd6l(v5 < 240, (): Item.Item => { - return item(v5); + const bag6: Bag.Bag | undefined = rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_212: rs.u8): Item.Item | undefined => { + const v7: rs.u8 = _212; + return then$0bmzd6l(v7 < 240, (): Item.Item => { + return item(v7); }); }), (values: rs.Iter) => Bag.fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure5_Option_never(values), rs.drop); - const part4 = option_map$0a0rmxp(bag6, (bag7: Bag.Bag): rs.usize => { + const part6 = option_map$0a0rmxp(bag6, (bag7: Bag.Bag): rs.usize => { return bag7.items.items.length; }); - const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part4, f, rs.usizeDebug)]; + const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part6, f, rs.usizeDebug)]; put(out, rs.fmtFormat([args4[0]])); const _89: rs.Iter = rs.iterFlatten(rs.iterOption(bag6), (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator_ref(value), true); write$iter_Flatten_option_Iter_collects_Bag(out, log, _89); rs.drop(bag6); } else if (_12 === 5) { - const stack: Stack.Stack = Stack.fromIter$iter_FromIterator_u16_u16_iter_Map_slice_Iter_u8_collects_collects_closure7(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): rs.u16 => { - return rs.u16Mul(_2 as rs.u16, 3); + const stack: Stack.Stack = Stack.fromIter$iter_FromIterator_u16_u16_iter_Map_slice_Iter_u8_collects_collects_closure7(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_210: rs.u8): rs.u16 => { + return rs.u16Mul(_210 as rs.u16, 3); })); - const part3 = stack.items as rs.Vec; - const _105: rs.Fmt = (f: rs.Formatter) => rs.fmtList(part3.items, f, rs.u16Debug); - const arg3 = stack.count; - const args6: rs.Fmt[] = [_105, (f: rs.Formatter) => rs.usizeDisplay(arg3, f)]; + const part5 = stack.items as rs.Vec; + const _105: rs.Fmt = (f: rs.Formatter) => rs.fmtList(part5.items, f, rs.u16Debug); + const arg4 = stack.count; + const args6: rs.Fmt[] = [_105, (f: rs.Formatter) => rs.usizeDisplay(arg4, f)]; put(out, rs.fmtFormat([args6[0], " ", args6[1]])); - const stack2: Stack.Stack = Stack.fromIter$iter_FromIterator_collects_Item_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_collects_closure8(rs.iterMap(rs.iterTake(rs.iterSlice(rs.byteSliceView(data)), k), (_22: rs.u8): Item.Item => { - return item(_22); + const stack2: Stack.Stack = Stack.fromIter$iter_FromIterator_collects_Item_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_collects_closure8(rs.iterMap(rs.iterTake(rs.iterSlice(rs.byteSliceView(data)), k), (_211: rs.u8): Item.Item => { + return item(_211); })); write$ref_Vec_collects_Item(out, log, stack2.items as rs.Vec); stack2[Symbol.dispose](); } else if (_12 === 6) { - const n: rs.u8 = option_mapOr$0vxw5sq(rs.byteSliceFirst(data), 0, (v2: rs.u8): rs.u8 => { - return rs.u8Rem(v2, 9); + const n: rs.u8 = option_mapOr$0vxw5sq(rs.byteSliceFirst(data), 0, (v4: rs.u8): rs.u8 => { + return rs.u8Rem(v4, 9); }); const stack3: Stack.Stack = Stack.fromIter$iter_FromIterator_u8_u8_collects_Down(new Down.Down(n, log)); - const part = stack3.items as rs.ByteVec; - const _133: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug); - const arg = stack3.count; - const args8: rs.Fmt[] = [_133, (f: rs.Formatter) => rs.usizeDisplay(arg, f)]; + const part3 = stack3.items as rs.ByteVec; + const _133: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part3), f, rs.u8Debug); + const arg2 = stack3.count; + const args8: rs.Fmt[] = [_133, (f: rs.Formatter) => rs.usizeDisplay(arg2, f)]; put(out, rs.fmtFormat([args8[0], " ", args8[1]])); const down: Down.Down = new Down.Down(n, log); const stack4: Stack.Stack = Stack.fromIter$iter_FromIterator_u8_u8_iter_Take_mut_collects_Down(rs.iterTake(rs.iterFrom(down, Down.next$iter_Iterator), k)); const _153: rs.u8 | undefined = rs.iterToOption(Down.next$iter_Iterator(down)); - const part2 = stack4.items as rs.ByteVec; - const _156: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug); - const arg2 = stack4.count; - const args10: rs.Fmt[] = [_156, (f: rs.Formatter) => rs.usizeDisplay(arg2, f), (f: rs.Formatter) => rs.fmtOption(_153, f, rs.u8Debug)]; + const part4 = stack4.items as rs.ByteVec; + const _156: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part4), f, rs.u8Debug); + const arg3 = stack4.count; + const args10: rs.Fmt[] = [_156, (f: rs.Formatter) => rs.usizeDisplay(arg3, f), (f: rs.Formatter) => rs.fmtOption(_153, f, rs.u8Debug)]; put(out, rs.fmtFormat([args10[0], " ", args10[1], " ", args10[2]])); down[Symbol.dispose](); + } else { + const tries: rs.Result, Item.Item> = rs.iterCollectResult(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): rs.Result => { + const v2: rs.u8 = _2; + if (!(rs.u8Rem(v2, 3) === 0)) { + return rs.Ok(v2); + } + return rs.Err(item(v2)); + }), (values: rs.Iter) => Tries.fromIter$iter_FromIterator_u8_u8_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure10_Result_never_collects_Item(values), undefined, rs.drop); + if (tries.ok) { + const part = tries.value._0; + const args12: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(part.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug))]; + put(out, rs.fmtFormat([args12[0]])); + } else { + const e2: Item.Item = tries.error; + const arg = e2.v; + const args14: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; + put(out, rs.fmtFormat(["err ", args14[0]])); + e2[Symbol.dispose](); + } + const part2 = option_map$1yttib1(rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_22: rs.u8): Item.Item | undefined => { + const v3: rs.u8 = _22; + return then$0bmzd6l(rs.u8Rem(v3, 3) !== 0, (): Item.Item => { + return item(v3); + }); + }), (values: rs.Iter) => Tries.fromIter$iter_FromIterator_collects_Item_collects_Item_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure11_Option_never(values), rs.drop), (_29: Tries.Tries): rs.Vec => { + const values3: rs.Vec = _29._0; + const _05: rs.Vec = rs.iterToVec(rs.iterMap(rs.iterSlice(values3.items), (item2: Item.Item | undefined): rs.u8 | undefined => { + return option_map$1hm93qk(item2, (item3: Item.Item): rs.u8 => { + return item3.v; + }); + }), undefined, 2, true); + rs.dropVec(values3); + return _05; + }); + const args16: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part2, f, (value: rs.Vec, f: rs.Formatter) => rs.fmtList(value.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug)))]; + put(out, rs.fmtFormat([args16[0]])); } write$array0_ref_collects_Item(out, log, []); } diff --git a/ts/fixtures/lang/collects/expected/core/option.ts b/ts/fixtures/lang/collects/expected/core/option.ts index c27e0b933..1a98e08bd 100644 --- a/ts/fixtures/lang/collects/expected/core/option.ts +++ b/ts/fixtures/lang/collects/expected/core/option.ts @@ -3,6 +3,7 @@ import * as rs from "../rs.ts"; import type * as Bag from "../collects.Bag.ts"; import type * as Item from "../collects.Item.ts"; +import type * as Tries from "../collects.Tries.ts"; export function map$1hm93qk(self: Item.Item | undefined, f: (a0: Item.Item) => rs.u8): rs.u8 | undefined { if (self === undefined) { @@ -11,6 +12,13 @@ export function map$1hm93qk(self: Item.Item | undefined, f: (a0: Item.Item) => r return f(self); } +export function map$1yttib1(self: Tries.Tries | undefined, f: (a0: Tries.Tries) => rs.Vec): rs.Vec | undefined { + if (self === undefined) { + return undefined; + } + return f(self); +} + export function map$0a0rmxp(self: Bag.Bag | undefined, f: (a0: Bag.Bag) => rs.usize): rs.usize | undefined { if (self === undefined) { return undefined; diff --git a/ts/fixtures/lang/collects/src/collects.rs b/ts/fixtures/lang/collects/src/collects.rs index 143376486..1fdb11a8b 100644 --- a/ts/fixtures/lang/collects/src/collects.rs +++ b/ts/fixtures/lang/collects/src/collects.rs @@ -80,6 +80,17 @@ impl FromIterator for Stack { } } +/// The crate's own collection of the first three reads of its iterator, which reads on past +/// a `None`, as nothing stops it from doing. +struct Tries(Vec>); + +impl FromIterator for Tries { + fn from_iter>(iter: I) -> Self { + let mut iter = iter.into_iter(); + Tries((0..3).map(|_| iter.next()).collect()) + } +} + /// What counts down from `n`, by the crate's own iterator. struct Count<'a> { n: u8, @@ -198,7 +209,26 @@ pub fn collects(kind: u8, data: &[u8], out: &mut Vec) { let stack: Stack = down.by_ref().take(k).collect(); put(out, &format!("{:?} {} {:?}", stack.items, stack.count, down.next())); } - _ => {} + // Into a `Result` or an `Option` of one that reads on past an `Err` or a `None`, which + // keeps the last `Err`, dropping the one it replaces. + _ => { + let tries: Result, Item> = data + .iter() + .map(|&v| if v % 3 == 0 { Err(item(v)) } else { Ok(v) }) + .collect(); + match tries { + Ok(Tries(values)) => put(out, &format!("{values:?}")), + Err(e) => put(out, &format!("err {}", e.v)), + } + let tries: Option> = data.iter().map(|&v| (v % 3 != 0).then(|| item(v))).collect(); + let values = tries.map(|Tries(values)| { + values + .iter() + .map(|item| item.as_ref().map(|item| item.v)) + .collect::>() + }); + put(out, &format!("{values:?}")); + } } write(out, &log, []); } diff --git a/ts/runtime/rs/iter.ts b/ts/runtime/rs/iter.ts index acc32c383..3cb3e55b0 100644 --- a/ts/runtime/rs/iter.ts +++ b/ts/runtime/rs/iter.ts @@ -1691,11 +1691,12 @@ function toByteVec(it: Iter, take?: Take, trusted = false): ByteVec { } /** - * `collect` of `Result`s: the first error, or every value collected by `into`, which drops - * the iterator. On an error, what it collected drops by `drop`. + * `collect` of `Result`s: the last error `into` read, or every value collected by `into`, + * which drops the iterator. On an error, what it collected drops by `drop`, and an error a + * later one replaced by `dropError`. */ -export function iterCollectResult(it: Iter>, into: (values: Iter) => C, drop?: Drop): Result { - const shunt = new ResultShunt(it); +export function iterCollectResult(it: Iter>, into: (values: Iter) => C, drop?: Drop, dropError?: Drop): Result { + const shunt = new ResultShunt(it, dropError); const values = into(shunt); if (shunt.error === undefined) return Ok(values); const error = Err(shunt.error.value); @@ -4928,16 +4929,25 @@ export function peekableNextIfEq(p: Peekable, expected: U, eq: (a: T, b return peekableNextIf(p, (item: T) => eq(item, expected), none); } -/** What `iterCollectResult` collects from: values until the first error, which it keeps. */ +/** + * What `iterCollectResult` collects from: values until an error, which it keeps. Read + * again, it reads on, as std's does, and a later error replaces it, which drops by `dropError`. + */ class ResultShunt extends Adaptor, U> { error: { value: E } | undefined; + private readonly dropError: Drop | undefined; + + constructor(inner: Iter>, dropError: Drop | undefined) { + super(inner); + this.dropError = dropError; + } /** std's, by `try_for_each`, which folds its iterator. */ next(): U | Done { - if (this.error !== undefined) return DONE; const item = this.inner.folded().next(); if (item === DONE) return DONE; if (item.ok) return item.value; + if (this.error !== undefined) this.dropError?.(this.error.value); this.error = { value: item.error }; return DONE; } @@ -4947,7 +4957,10 @@ class ResultShunt extends Adaptor, U> { } } -/** What `iterCollectOption` collects from: values until the first `None`, which is `itemNone`. */ +/** + * What `iterCollectOption` collects from: values until a `None`, which is `itemNone`. Read + * again, it reads on, as std's does. + */ class OptionShunt extends Adaptor { none = false; private readonly itemNone: None | undefined; @@ -4958,7 +4971,6 @@ class OptionShunt extends Adaptor { } next(): U | Done { - if (this.none) return DONE; const item = this.inner.folded().next(); if (item === DONE) return DONE; if (item !== this.itemNone) return item as U; diff --git a/ts/src/lower/iter.rs b/ts/src/lower/iter.rs index 0a4ca63bd..3e7026ff2 100644 --- a/ts/src/lower/iter.rs +++ b/ts/src/lower/iter.rs @@ -2135,7 +2135,8 @@ fn collect<'tcx>( }); } match std { - // The values, collected as the `Ok` or `Some` type is, until the first `Err` or `None`. + // The values, collected as the `Ok` or `Some` type is, until an `Err` or `None`, the last + // the collection read. std @ (Std::Result | Std::Option) => { let ty::Adt(_, item_args) = item.kind() else { return None; @@ -2167,7 +2168,11 @@ fn collect<'tcx>( let dropper = b.t.dropper(args.type_at(0), span); let collected = vec![iter, Expr::Lambda(vec![param], Box::new(values))]; Some(match std { - Std::Result => Expr::rs("iterCollectResult", tail(collected, vec![dropper])), + // A later error replaces an earlier one, which then drops. + Std::Result => { + let error = b.t.dropper(args.type_at(1), span); + Expr::rs("iterCollectResult", tail(collected, vec![dropper, error])) + } // The items' `None`, and the result's, each `rs.None` where `undefined` is a value. _ => { let nones = [value, args.type_at(0)].map(|t| b.t.none(t)); From 6ab8673c869bc1d9caed3a9caa625f7dd93fb964 Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Wed, 4 Nov 2026 09:55:58 -0800 Subject: [PATCH 4/6] test(ts): pass the error's dropper to a Result collect in task's snapshot Co-Authored-By: Claude Opus 5.5 --- ts/fixtures/task/expected/drops/iters.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ts/fixtures/task/expected/drops/iters.ts b/ts/fixtures/task/expected/drops/iters.ts index d930f6de5..67f3ab3a9 100644 --- a/ts/fixtures/task/expected/drops/iters.ts +++ b/ts/fixtures/task/expected/drops/iters.ts @@ -350,7 +350,7 @@ export function collected(log: Log.Log, id: rs.u32): void { return rs.Ok(g2); } return rs.Err(g2); - }), (values: rs.Iter) => rs.iterToVec(values, "next", 8, false, 8), lib_drop$Vec_model_Guard); + }), (values: rs.Iter) => rs.iterToVec(values, "next", 8, false, 8), lib_drop$Vec_model_Guard, rs.drop); const part = results.ok; const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtBool(part, f)]; Log.note(log, rs.fmtFormat(["result ", args4[0]])); From 89f73a2deca09880bc028ad02472e08c8c78a25e Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Wed, 4 Nov 2026 11:54:40 -0800 Subject: [PATCH 5/6] quest: the model census at the bumped moq pin, after this PR Co-Authored-By: Claude Opus 5.5 --- quest/m2/ts-model/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quest/m2/ts-model/README.md b/quest/m2/ts-model/README.md index 92cab7963..06b4b9d75 100644 --- a/quest/m2/ts-model/README.md +++ b/quest/m2/ts-model/README.md @@ -45,7 +45,7 @@ Decided with the maintainer on 2026-10-27, from a census of the model's 22 publi - The end-to-end work stays here: the model's roots, its differential harness, and the `frames.ts` workload. moq writes the binding files `model.toml` names, in its own tree. -The census at the pin on 2026-11-04: 62 refusals. `Timestamp` alone refuses nothing, and +The census at the pin on 2026-11-04: 82 refusals. `Timestamp` alone refuses nothing, and the [model fixture](/ts/README.md#tests)'s harness runs it against native moq-net at the pin; each case it adds as a type translates. Every other root reaches the rest of the model, so each child below unblocks all of them together. The rest is moq's, for its From ae2e09fd7a60d45b9a8479d708cd0194d6e39d6f Mon Sep 17 00:00:00 2001 From: quest fixer Date: Wed, 4 Nov 2026 12:41:52 -0800 Subject: [PATCH 6/6] test(ts): regenerate collects snapshots against base --- .../lang/collects/expected/collects.Bag.ts | 36 +++------ .../lang/collects/expected/collects.Count.ts | 3 +- .../lang/collects/expected/collects.Down.ts | 6 +- .../lang/collects/expected/collects.Item.ts | 3 +- .../lang/collects/expected/collects.ts | 78 +++++++------------ ts/fixtures/lang/collects/expected/harness.ts | 6 +- 6 files changed, 46 insertions(+), 86 deletions(-) diff --git a/ts/fixtures/lang/collects/expected/collects.Bag.ts b/ts/fixtures/lang/collects/expected/collects.Bag.ts index d1ef06b79..22a74de35 100644 --- a/ts/fixtures/lang/collects/expected/collects.Bag.ts +++ b/ts/fixtures/lang/collects/expected/collects.Bag.ts @@ -40,8 +40,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Filter_it if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -69,8 +68,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Rev_slice if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -98,8 +96,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Skip_slic if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -127,8 +124,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_iter_Take_slic if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -156,8 +152,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -185,8 +180,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -214,8 +208,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -243,8 +236,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -272,8 +264,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Map_slice_Iter_u8_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -301,8 +292,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_Skip_vec_IntoIter_ if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -332,8 +322,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericSh if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } @@ -361,8 +350,7 @@ export function fromIter$iter_FromIterator_collects_Item_iter_adapters_GenericSh if (_17 !== undefined) { const _25: rs.RefCell> = rs.refCellBorrowMut(_17.log); const part = items.items.length; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.usizeDisplay(part, f)]; - const _26: string = rs.fmtFormat(["bag of ", args2[0]]); + const _26: string = rs.fmtFormat(["bag of ", (f: rs.Formatter) => rs.usizeDisplay(part, f)]); _25.value.items.push(_26); rs.refMutRelease(_25); } diff --git a/ts/fixtures/lang/collects/expected/collects.Count.ts b/ts/fixtures/lang/collects/expected/collects.Count.ts index c9ba1b0ef..de9bd14c4 100644 --- a/ts/fixtures/lang/collects/expected/collects.Count.ts +++ b/ts/fixtures/lang/collects/expected/collects.Count.ts @@ -12,8 +12,7 @@ export interface Count { export function intoIter$iter_IntoIterator(self: Count): Down.Down { const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); const arg = self.n; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; - const _6: string = rs.fmtFormat(["count ", args2[0]]); + const _6: string = rs.fmtFormat(["count ", (f: rs.Formatter) => rs.u8Display(arg, f)]); _5.value.items.push(_6); rs.refMutRelease(_5); return new Down.Down(self.n, self.log); diff --git a/ts/fixtures/lang/collects/expected/collects.Down.ts b/ts/fixtures/lang/collects/expected/collects.Down.ts index 6d06a808e..7274f72f7 100644 --- a/ts/fixtures/lang/collects/expected/collects.Down.ts +++ b/ts/fixtures/lang/collects/expected/collects.Down.ts @@ -20,8 +20,7 @@ export class Down { export function next$iter_Iterator(self: Down): rs.u8 | rs.Done { const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); const arg = self.n; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; - const _6: string = rs.fmtFormat(["next ", args2[0]]); + const _6: string = rs.fmtFormat(["next ", (f: rs.Formatter) => rs.u8Display(arg, f)]); _5.value.items.push(_6); rs.refMutRelease(_5); const _15: rs.u8 | undefined = rs.u8CheckedSub(self.n, 1); @@ -35,8 +34,7 @@ export function next$iter_Iterator(self: Down): rs.u8 | rs.Done { export function drop$ops_Drop(self: Down): void { const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); const arg = self.n; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; - const _6: string = rs.fmtFormat(["down dropped at ", args2[0]]); + const _6: string = rs.fmtFormat(["down dropped at ", (f: rs.Formatter) => rs.u8Display(arg, f)]); _5.value.items.push(_6); rs.refMutRelease(_5); } diff --git a/ts/fixtures/lang/collects/expected/collects.Item.ts b/ts/fixtures/lang/collects/expected/collects.Item.ts index 17b0d1fba..b60b3d9d8 100644 --- a/ts/fixtures/lang/collects/expected/collects.Item.ts +++ b/ts/fixtures/lang/collects/expected/collects.Item.ts @@ -20,8 +20,7 @@ export class Item { export function drop$ops_Drop(self: Item): void { const _5: rs.RefCell> = rs.refCellBorrowMut(self.log); const arg = self.v; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; - const _6: string = rs.fmtFormat(["drop ", args2[0]]); + const _6: string = rs.fmtFormat(["drop ", (f: rs.Formatter) => rs.u8Display(arg, f)]); _5.value.items.push(_6); rs.refMutRelease(_5); } diff --git a/ts/fixtures/lang/collects/expected/collects.ts b/ts/fixtures/lang/collects/expected/collects.ts index e8910eaf4..770453d88 100644 --- a/ts/fixtures/lang/collects/expected/collects.ts +++ b/ts/fixtures/lang/collects/expected/collects.ts @@ -16,8 +16,7 @@ export function write$Option_ref_collects_Item(out: rs.ByteVec, log: rs.RefCell< const part = rs.iterToByteVec(rs.iterMap(rs.iterOption(values), (item: Item.Item): rs.u8 => { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -28,8 +27,7 @@ export function write$array0_ref_collects_Item(out: rs.ByteVec, log: rs.RefCell< const part = rs.iterToByteVec(rs.iterMap(rs.iterSlice(values), (item: Item.Item): rs.u8 => { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -40,8 +38,7 @@ export function write$iter_Chain_slice_Iter_collects_Item_slice_Iter_collects_It const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -52,8 +49,7 @@ export function write$iter_Flatten_option_Iter_collects_Bag(out: rs.ByteVec, log const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { return item.v; }), "next"); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -64,8 +60,7 @@ export function write$iter_Skip_iter_Flatten_slice_Iter_collects_Bag(out: rs.Byt const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { return item.v; }), "next"); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -76,8 +71,7 @@ export function write$iter_StepBy_iter_FlatMap_iter_Rev_ops_Range_usize_ref_coll const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { return item.v; }), "next"); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -88,8 +82,7 @@ export function write$iter_Take_slice_Iter_collects_Item(out: rs.ByteVec, log: r const part = rs.iterToByteVec(rs.iterMap(values, (item: Item.Item): rs.u8 => { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -100,8 +93,7 @@ export function write$ref_Vec_collects_Item(out: rs.ByteVec, log: rs.RefCell { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -112,8 +104,7 @@ export function write$ref_collects_Bag(out: rs.ByteVec, log: rs.RefCell { return item.v; }), undefined, true); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part), f, rs.u8Debug)])); const _29: rs.RefCell> = rs.refCellBorrowMut(log); put(out, rs.strsJoin(rs.iterToVec(rs.vecDrain(_29.value, undefined), "fold", 12, true).items, ", ")); rs.refMutRelease(_29); @@ -127,8 +118,7 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { const _6: rs.RefCell> = rs.refCellBorrowMut(log); - const args18: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; - const _7: string = rs.fmtFormat(["make ", args18[0]]); + const _7: string = rs.fmtFormat(["make ", (f: rs.Formatter) => rs.u8Display(v, f)]); _6.value.items.push(_7); rs.refMutRelease(_6); return new Item.Item(v, log); @@ -170,8 +160,7 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void bag5[Symbol.dispose](); } else { const arg5 = bag4.error; - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg5, f)]; - put(out, rs.fmtFormat(["err ", args2[0]])); + put(out, rs.fmtFormat(["err ", (f: rs.Formatter) => rs.u8Display(arg5, f)])); } } else if (_12 === 4) { const bag6: Bag.Bag | undefined = rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_212: rs.u8): Item.Item | undefined => { @@ -183,8 +172,7 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const part6 = option_map$0a0rmxp(bag6, (bag7: Bag.Bag): rs.usize => { return bag7.items.items.length; }); - const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part6, f, rs.usizeDebug)]; - put(out, rs.fmtFormat([args4[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtOption(part6, f, rs.usizeDebug)])); const _89: rs.Iter = rs.iterFlatten(rs.iterOption(bag6), (value: Bag.Bag) => Bag.intoIter$iter_IntoIterator_ref(value), true); write$iter_Flatten_option_Iter_collects_Bag(out, log, _89); rs.drop(bag6); @@ -195,8 +183,8 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const part5 = stack.items as rs.Vec; const _105: rs.Fmt = (f: rs.Formatter) => rs.fmtList(part5.items, f, rs.u16Debug); const arg4 = stack.count; - const args6: rs.Fmt[] = [_105, (f: rs.Formatter) => rs.usizeDisplay(arg4, f)]; - put(out, rs.fmtFormat([args6[0], " ", args6[1]])); + const args25 = [_105, (f: rs.Formatter) => rs.usizeDisplay(arg4, f)]; + put(out, rs.fmtFormat([args25[0], " ", args25[1]])); const stack2: Stack.Stack = Stack.fromIter$iter_FromIterator_collects_Item_collects_Item_iter_Map_iter_Take_slice_Iter_u8_collects_collects_closure8(rs.iterMap(rs.iterTake(rs.iterSlice(rs.byteSliceView(data)), k), (_211: rs.u8): Item.Item => { return item(_211); })); @@ -210,16 +198,16 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const part3 = stack3.items as rs.ByteVec; const _133: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part3), f, rs.u8Debug); const arg2 = stack3.count; - const args8: rs.Fmt[] = [_133, (f: rs.Formatter) => rs.usizeDisplay(arg2, f)]; - put(out, rs.fmtFormat([args8[0], " ", args8[1]])); + const args23 = [_133, (f: rs.Formatter) => rs.usizeDisplay(arg2, f)]; + put(out, rs.fmtFormat([args23[0], " ", args23[1]])); const down: Down.Down = new Down.Down(n, log); const stack4: Stack.Stack = Stack.fromIter$iter_FromIterator_u8_u8_iter_Take_mut_collects_Down(rs.iterTake(rs.iterFrom(down, Down.next$iter_Iterator), k)); const _153: rs.u8 | undefined = rs.iterToOption(Down.next$iter_Iterator(down)); const part4 = stack4.items as rs.ByteVec; const _156: rs.Fmt = (f: rs.Formatter) => rs.fmtList(rs.byteVecView(part4), f, rs.u8Debug); const arg3 = stack4.count; - const args10: rs.Fmt[] = [_156, (f: rs.Formatter) => rs.usizeDisplay(arg3, f), (f: rs.Formatter) => rs.fmtOption(_153, f, rs.u8Debug)]; - put(out, rs.fmtFormat([args10[0], " ", args10[1], " ", args10[2]])); + const args24 = [_156, (f: rs.Formatter) => rs.usizeDisplay(arg3, f), (f: rs.Formatter) => rs.fmtOption(_153, f, rs.u8Debug)]; + put(out, rs.fmtFormat([args24[0], " ", args24[1], " ", args24[2]])); down[Symbol.dispose](); } else { const tries: rs.Result, Item.Item> = rs.iterCollectResult(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): rs.Result => { @@ -231,13 +219,11 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void }), (values: rs.Iter) => Tries.fromIter$iter_FromIterator_u8_u8_iter_adapters_GenericShunt_iter_Map_slice_Iter_u8_collects_collects_closure10_Result_never_collects_Item(values), undefined, rs.drop); if (tries.ok) { const part = tries.value._0; - const args12: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(part.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug))]; - put(out, rs.fmtFormat([args12[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(part.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug))])); } else { const e2: Item.Item = tries.error; const arg = e2.v; - const args14: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(arg, f)]; - put(out, rs.fmtFormat(["err ", args14[0]])); + put(out, rs.fmtFormat(["err ", (f: rs.Formatter) => rs.u8Display(arg, f)])); e2[Symbol.dispose](); } const part2 = option_map$1yttib1(rs.iterCollectOption(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_22: rs.u8): Item.Item | undefined => { @@ -255,8 +241,7 @@ export function collects(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void rs.dropVec(values3); return _05; }); - const args16: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(part2, f, (value: rs.Vec, f: rs.Formatter) => rs.fmtList(value.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug)))]; - put(out, rs.fmtFormat([args16[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtOption(part2, f, (value: rs.Vec, f: rs.Formatter) => rs.fmtList(value.items, f, (value: rs.u8 | undefined, f: rs.Formatter) => rs.fmtOption(value, f, rs.u8Debug)))])); } write$array0_ref_collects_Item(out, log, []); } @@ -269,8 +254,7 @@ export function flattens(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { const _6: rs.RefCell> = rs.refCellBorrowMut(log); - const args8: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; - const _7: string = rs.fmtFormat(["make ", args8[0]]); + const _7: string = rs.fmtFormat(["make ", (f: rs.Formatter) => rs.u8Display(v, f)]); _6.value.items.push(_7); rs.refMutRelease(_6); return new Item.Item(v, log); @@ -290,8 +274,7 @@ export function flattens(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void return _013; }); const _27: rs.RefCell> = rs.refCellBorrowMut(log); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtOption(back, f, rs.u8Debug)]; - const _29: string = rs.fmtFormat(["back ", args2[0]]); + const _29: string = rs.fmtFormat(["back ", (f: rs.Formatter) => rs.fmtOption(back, f, rs.u8Debug)]); _27.value.items.push(_29); rs.refMutRelease(_27); rs.drop(it); @@ -327,16 +310,14 @@ export function flattens(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void const part2 = rs.iterToByteVec(rs.iterTake(rs.iterFlatMap(rs.iterSlice(rs.byteSliceView(data)), (_23: rs.u8): Count.Count => { return { n: rs.u8Rem(_23, 5), log }; }, (value: Count.Count) => rs.iterFrom(Count.intoIter$iter_IntoIterator(value), Down.next$iter_Iterator, rs.drop), true), k), "next"); - const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args4[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)])); } else if (_11 === 4) { const part = rs.iterFold(rs.iterFlatten(rs.iterMap(rs.iterSlice(rs.byteSliceView(data)), (_2: rs.u8): Count.Count => { return { n: rs.u8Rem(_2, 4), log }; }), (value: Count.Count) => rs.iterFrom(Count.intoIter$iter_IntoIterator(value), Down.next$iter_Iterator, rs.drop), true), 0, (sum2: rs.u32, v3: rs.u8): rs.u32 => { return rs.u32Add(sum2, v3 as rs.u32); }, true); - const args6: rs.Fmt[] = [(f: rs.Formatter) => rs.u32Display(part, f)]; - put(out, rs.fmtFormat([args6[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.u32Display(part, f)])); } write$array0_ref_collects_Item(out, log, []); } @@ -346,8 +327,7 @@ export function chains(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { const log: rs.RefCell> = new rs.RefCell(new rs.Vec()); const item: (a0: rs.u8) => Item.Item = (v: rs.u8): Item.Item => { const _6: rs.RefCell> = rs.refCellBorrowMut(log); - const args6: rs.Fmt[] = [(f: rs.Formatter) => rs.u8Display(v, f)]; - const _7: string = rs.fmtFormat(["make ", args6[0]]); + const _7: string = rs.fmtFormat(["make ", (f: rs.Formatter) => rs.u8Display(v, f)]); _6.value.items.push(_7); rs.refMutRelease(_6); return new Item.Item(v, log); @@ -376,16 +356,14 @@ export function chains(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { const part = rs.iterToVec(rs.iterMap(rs.iterZip(rs.iterSlice(rs.byteSliceView(data)), rs.iterFrom(Count.intoIter$iter_IntoIterator({ n: 4, log }), Down.next$iter_Iterator, rs.drop)), (_24: [rs.u8, rs.u8]): [rs.u8, rs.u8] => { return [_24[0], _24[1]] as [rs.u8, rs.u8]; }), "next", 2); - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(part.items, f, (value: [rs.u8, rs.u8], f: rs.Formatter) => rs.fmtTuple([(f: rs.Formatter) => rs.u8Debug(value[0], f), (f: rs.Formatter) => rs.u8Debug(value[1], f)], f))]; - put(out, rs.fmtFormat([args2[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(part.items, f, (value: [rs.u8, rs.u8], f: rs.Formatter) => rs.fmtTuple([(f: rs.Formatter) => rs.u8Debug(value[0], f), (f: rs.Formatter) => rs.u8Debug(value[1], f)], f))])); const part2 = rs.iterToByteVec(rs.iterMap(rs.iterZip(new rs.Range(0, k), Bag.intoIter$iter_IntoIterator(bag2), "len", undefined, rs.drop), (_25: [rs.usize, Item.Item]): rs.u8 => { const item2: Item.Item = _25[1]; const _04: rs.u8 = item2.v; item2[Symbol.dispose](); return _04; }), "fold", true); - const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)]; - put(out, rs.fmtFormat([args4[0]])); + put(out, rs.fmtFormat([(f: rs.Formatter) => rs.fmtList(rs.byteVecView(part2), f, rs.u8Debug)])); } write$array0_ref_collects_Item(out, log, []); } diff --git a/ts/fixtures/lang/collects/expected/harness.ts b/ts/fixtures/lang/collects/expected/harness.ts index 610e5cf7d..d3614fb27 100644 --- a/ts/fixtures/lang/collects/expected/harness.ts +++ b/ts/fixtures/lang/collects/expected/harness.ts @@ -29,11 +29,9 @@ export function op(name: string): rs.u16 { return _20.value; } } - const args4: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtPad(f, name)]; - rs.panicFmt(["case ", args4[0], " is past what two bytes pick"]); + rs.panicFmt(["case ", (f: rs.Formatter) => rs.fmtPad(f, name), " is past what two bytes pick"]); } else { - const args2: rs.Fmt[] = [(f: rs.Formatter) => rs.fmtPad(f, name)]; - rs.panicFmt(["no case ", args2[0]]); + rs.panicFmt(["no case ", (f: rs.Formatter) => rs.fmtPad(f, name)]); } }