From d0103b1a75637e9e9fbf40fc1d7e5f6e708ee81a Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 1 Nov 2026 07:58:43 -0800 Subject: [PATCH 1/2] chore(quest): claim quest/m3/ts-fresh-type-params.md Quest-Claim: 7ae749b636ce6223 From 14826b48e36b49ec593b9a08b4534bc940c0f2ea Mon Sep 17 00:00:00 2001 From: Luke Curley <432854+kixelated@users.noreply.github.com> Date: Sun, 1 Nov 2026 09:48:08 -0800 Subject: [PATCH 2/2] feat(ts): judge whole writes fresh in a body generic over a type Std's code and the body see inside a type parameter's value only through its bounds, so Trace no longer counts one as hiding a part std could store, as holding parts in place, or as showing pointers to a deep origin search. A parameter left no drop glue by its bounds, as Copy does, drops no crate code. Co-Authored-By: Claude Opus 5.5 --- quest/m3/README.md | 1 - quest/m3/ts-fresh-type-params.md | 19 - ts/fixtures/lang/expected/lengths.Tagged.ts | 6 + ts/fixtures/lang/expected/lengths.ts | 886 +++++++++++++++----- ts/fixtures/lang/expected/lib.ts | 39 + ts/fixtures/lang/src/lengths.rs | 78 +- ts/fixtures/reject/census.md | 22 +- ts/fixtures/reject/expected.txt | 4 + ts/fixtures/reject/src/lib.rs | 94 +++ ts/fixtures/reject/ts.toml | 4 + ts/src/lower/mir/holders.rs | 48 +- ts/src/lower/mir/mod.rs | 21 +- 12 files changed, 952 insertions(+), 270 deletions(-) delete mode 100644 quest/m3/ts-fresh-type-params.md diff --git a/quest/m3/README.md b/quest/m3/README.md index 2f5429677..fc0aa471f 100644 --- a/quest/m3/README.md +++ b/quest/m3/README.md @@ -22,7 +22,6 @@ generic std gap is planned here even when moq never calls it. - [Placeholders written to a crate's own fmt::Write](/quest/m3/ts-fmt-calls.md) - `write!` with placeholders into a crate's own writer translates, its `write_str` seeing each call std makes - [Waiting: type-check in process with tsrs](/quest/m3/ts-tsrs.md) - rust2-ts checks bindings through tsrs instead of `tsc` once it is a stable library - [Drop order in std's folds and iterators](/quest/m3/ts-drop-order.md) - the values that drop still refused in std's consumers, flattens, and collects drop as std's do -- [Fresh writes in a body generic over a type](/quest/m3/ts-fresh-type-params.md) - a whole write into fresh memory holding a type parameter's values fills it, as one generic over a length alone does - [std's conversions of a reference](/quest/m3/ts-ref-conversions.md) - `to_owned`, `clone_from`, `binary_search`, `size_of_val`, `from_ref`/`from_mut`, and `AsRef`/`Borrow` as a slice translate - [Waiting: a slice object for a mutable part of other values](/quest/m3/ts-slice-object.md) - waits on a moq profile showing the `Proxy` view's traps matter, then decides on an `rt.ByteSlice`-like form - [Port the workflow guard to kixelated/quest](/quest/m3/quest-workflow-guard.md) - quest's environment guard parses YAML as this repository's does diff --git a/quest/m3/ts-fresh-type-params.md b/quest/m3/ts-fresh-type-params.md deleted file mode 100644 index 3e13b3291..000000000 --- a/quest/m3/ts-fresh-type-params.md +++ /dev/null @@ -1,19 +0,0 @@ -# [M] Fresh writes in a body generic over a type - -## Goal - -[rust2-ts](/ts/README.md) judges a whole write fresh in a function generic over a type -parameter as it does in one generic over a length alone: `slot.write(..)` through -`iter_mut` over `[MaybeUninit<([T; N], (u8, u8))>; 3]` fills the slot, so a later -`&raw mut` to a part of it translates instead of being refused. - -## Plan - -Found while landing [Judging writes in a body generic over a const](https://github.com/moq-dev/rust2/pull/359): -the lang fixture's `lengths::filled` stays fresh only over `[u8; N]`, `[u32; N]`, and -`[[u8; N]; N]`. `Trace::runs_own_code` counts every `ty::Param` as code std's iterators may -run, so a std call given a type holding `T` keeps what it is given. A parameter whose -bounds call nothing, as `T: Copy`, runs none of the crate's code; decide from the bounds -in the body's typing environment, as `Trace::inert` does for std's own impls. - -Public API: the translator's output. diff --git a/ts/fixtures/lang/expected/lengths.Tagged.ts b/ts/fixtures/lang/expected/lengths.Tagged.ts index 80860db90..4e5e2c82d 100644 --- a/ts/fixtures/lang/expected/lengths.Tagged.ts +++ b/ts/fixtures/lang/expected/lengths.Tagged.ts @@ -1,6 +1,7 @@ // Generated by rust2-ts. Do not edit. import * as rt from "./rt.ts"; +import { put$lengths_Put_u32 as lengths_put$lengths_Put_u32 } from "./lengths.ts"; export class Tagged { _0: T; @@ -12,4 +13,9 @@ export class Tagged { } } +export function put$lengths_Put_u32(self: Tagged, out: rt.ByteVec): void { + lengths_put$lengths_Put_u32(self._0, out); + rt.byteVecPush(out, self._1); +} + //# sourceMappingURL=lengths.Tagged.ts.map diff --git a/ts/fixtures/lang/expected/lengths.ts b/ts/fixtures/lang/expected/lengths.ts index 83a3dd69f..35449235b 100644 --- a/ts/fixtures/lang/expected/lengths.ts +++ b/ts/fixtures/lang/expected/lengths.ts @@ -1,7 +1,7 @@ // Generated by rust2-ts. Do not edit. import * as rt from "./rt.ts"; -import { copy$Option_lengths_Tagged_array0_u32, copy$Option_lengths_Tagged_array0_u8, copy$Option_lengths_Tagged_array17_u32, copy$Option_lengths_Tagged_array17_u8, copy$Option_lengths_Tagged_array1_u32, copy$Option_lengths_Tagged_array1_u8, copy$Option_lengths_Tagged_array3_u32, copy$Option_lengths_Tagged_array3_u8, copy$array_array0_u8, copy$array_array17_u8, copy$array_array1_u8, copy$array_array3_u8, copy$array_u32, copy$array_u8, copy$mem_MaybeUninit_tuple2_array0_array0_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array0_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array0_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_array17_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_array1_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_array3_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_u8_tuple2_u8_u8 } from "./lib.ts"; +import { copy$Option_lengths_Tagged_array0_u32, copy$Option_lengths_Tagged_array0_u8, copy$Option_lengths_Tagged_array17_u32, copy$Option_lengths_Tagged_array17_u8, copy$Option_lengths_Tagged_array1_u32, copy$Option_lengths_Tagged_array1_u8, copy$Option_lengths_Tagged_array3_u32, copy$Option_lengths_Tagged_array3_u8, copy$array_array0_u8, copy$array_array17_u8, copy$array_array1_u8, copy$array_array3_u8, copy$array_lengths_Tagged_u32, copy$array_u32, copy$array_u8, copy$mem_MaybeUninit_tuple2_array0_array0_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array0_lengths_Tagged_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array0_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array0_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_array17_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_lengths_Tagged_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array17_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_array1_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_lengths_Tagged_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array1_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_array3_u8_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_lengths_Tagged_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_u32_tuple2_u8_u8, copy$mem_MaybeUninit_tuple2_array3_u8_tuple2_u8_u8 } from "./lib.ts"; import { unwrapOr$0r2bmpr as option_unwrapOr$0r2bmpr } from "./core/option.ts"; import * as lengths_Tagged from "./lengths.Tagged.ts"; @@ -36,17 +36,20 @@ export function each$0(data: rt.ByteSlice, out: rt.ByteVec): void { })]).map(copy$array_u8), out); retagged$0(rows, out); recloned$u32_0(wide, out); - filledBytes$0(data, rt.bytesFromFn(0, (i3: rt.usize): rt.u8 => { + filled$u8_0(data, rt.bytesFromFn(0, (i3: rt.usize): rt.u8 => { return i3 & 0xff; }), out); - filledWords$0(data, rt.arrayFromFn(0, (i4: rt.usize): rt.u32 => { + filled$u32_0(data, rt.arrayFromFn(0, (i4: rt.usize): rt.u32 => { return rt.u32Mul(16909060, i4 as rt.u32); }), out); - filledRows$0(data, rt.arrayFromFn(0, (i5: rt.usize): Uint8Array => { + filled$array0_u8_0(data, rt.arrayFromFn(0, (i5: rt.usize): Uint8Array => { return rt.bytesFromFn(0, (j: rt.usize): rt.u8 => { return rt.usizeAdd(rt.usizeMul(i5, 0), j) & 0xff; }); }), out); + filled$lengths_Tagged_u32_0(data, rt.arrayFromFn(0, (i6: rt.usize): lengths_Tagged.Tagged => { + return new lengths_Tagged.Tagged(rt.u32Mul(i6 as rt.u32, 257), ~(i6 & 0xff) & 0xff); + }), out); swapped$u8_0(data, rows, out); swapped$u32_0(data, wide, out); } @@ -68,17 +71,20 @@ export function each$1(data: rt.ByteSlice, out: rt.ByteVec): void { })]).map(copy$array_u8), out); retagged$1(rows, out); recloned$u32_1(wide, out); - filledBytes$1(data, rt.bytesFromFn(1, (i3: rt.usize): rt.u8 => { + filled$u8_1(data, rt.bytesFromFn(1, (i3: rt.usize): rt.u8 => { return i3 & 0xff; }), out); - filledWords$1(data, rt.arrayFromFn(1, (i4: rt.usize): rt.u32 => { + filled$u32_1(data, rt.arrayFromFn(1, (i4: rt.usize): rt.u32 => { return rt.u32Mul(16909060, i4 as rt.u32); }), out); - filledRows$1(data, rt.arrayFromFn(1, (i5: rt.usize): Uint8Array => { + filled$array1_u8_1(data, rt.arrayFromFn(1, (i5: rt.usize): Uint8Array => { return rt.bytesFromFn(1, (j: rt.usize): rt.u8 => { return rt.usizeAdd(rt.usizeMul(i5, 1), j) & 0xff; }); }), out); + filled$lengths_Tagged_u32_1(data, rt.arrayFromFn(1, (i6: rt.usize): lengths_Tagged.Tagged => { + return new lengths_Tagged.Tagged(rt.u32Mul(i6 as rt.u32, 257), ~(i6 & 0xff) & 0xff); + }), out); swapped$u8_1(data, rows, out); swapped$u32_1(data, wide, out); } @@ -100,17 +106,20 @@ export function each$17(data: rt.ByteSlice, out: rt.ByteVec): void { })]).map(copy$array_u8), out); retagged$17(rows, out); recloned$u32_17(wide, out); - filledBytes$17(data, rt.bytesFromFn(17, (i3: rt.usize): rt.u8 => { + filled$u8_17(data, rt.bytesFromFn(17, (i3: rt.usize): rt.u8 => { return i3 & 0xff; }), out); - filledWords$17(data, rt.arrayFromFn(17, (i4: rt.usize): rt.u32 => { + filled$u32_17(data, rt.arrayFromFn(17, (i4: rt.usize): rt.u32 => { return rt.u32Mul(16909060, i4 as rt.u32); }), out); - filledRows$17(data, rt.arrayFromFn(17, (i5: rt.usize): Uint8Array => { + filled$array17_u8_17(data, rt.arrayFromFn(17, (i5: rt.usize): Uint8Array => { return rt.bytesFromFn(17, (j: rt.usize): rt.u8 => { return rt.usizeAdd(rt.usizeMul(i5, 17), j) & 0xff; }); }), out); + filled$lengths_Tagged_u32_17(data, rt.arrayFromFn(17, (i6: rt.usize): lengths_Tagged.Tagged => { + return new lengths_Tagged.Tagged(rt.u32Mul(i6 as rt.u32, 257), ~(i6 & 0xff) & 0xff); + }), out); swapped$u8_17(data, rows, out); swapped$u32_17(data, wide, out); } @@ -132,17 +141,20 @@ export function each$3(data: rt.ByteSlice, out: rt.ByteVec): void { })]).map(copy$array_u8), out); retagged$3(rows, out); recloned$u32_3(wide, out); - filledBytes$3(data, rt.bytesFromFn(3, (i3: rt.usize): rt.u8 => { + filled$u8_3(data, rt.bytesFromFn(3, (i3: rt.usize): rt.u8 => { return i3 & 0xff; }), out); - filledWords$3(data, rt.arrayFromFn(3, (i4: rt.usize): rt.u32 => { + filled$u32_3(data, rt.arrayFromFn(3, (i4: rt.usize): rt.u32 => { return rt.u32Mul(16909060, i4 as rt.u32); }), out); - filledRows$3(data, rt.arrayFromFn(3, (i5: rt.usize): Uint8Array => { + filled$array3_u8_3(data, rt.arrayFromFn(3, (i5: rt.usize): Uint8Array => { return rt.bytesFromFn(3, (j: rt.usize): rt.u8 => { return rt.usizeAdd(rt.usizeMul(i5, 3), j) & 0xff; }); }), out); + filled$lengths_Tagged_u32_3(data, rt.arrayFromFn(3, (i6: rt.usize): lengths_Tagged.Tagged => { + return new lengths_Tagged.Tagged(rt.u32Mul(i6 as rt.u32, 257), ~(i6 & 0xff) & 0xff); + }), out); swapped$u8_3(data, rows, out); swapped$u32_3(data, wide, out); } @@ -395,155 +407,496 @@ export function recloned$u32_3(rows: rt.u32[][], out: rt.ByteVec): void { } } -export function filledBytes$0(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { - const item = ([new Uint8Array(0), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; - const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array0_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$array0_u8_0(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 0 }, (): Uint8Array => { + return (new Uint8Array(0) as unknown) as Uint8Array; + }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; + const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array0_array0_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_array0_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + const iter2: rt.Iter = rt.iterLend(rt.iterSlice(fill), rt.byteSliceFrom); + while (true) { + const _26: rt.ByteSlice | rt.Done = iter2.next(); + if (_26 === rt.DONE) { + break; + } + picks.push(copy$array_u8(rt.byteSliceToArray(_26))); + } + const iter3: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_array0_u8(fill), [0, 90] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_29]; - rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(0, 1))); + const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(0, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array, [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_57[0]))), (v: rt.u8): undefined => { - put$lengths_Put_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterLend(rt.iterSlice(_86[0]), rt.byteSliceFrom), (v2: rt.ByteSlice): undefined => { + put$lengths_Put_array0_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledBytes$1(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { - const item = ([new Uint8Array(1), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; - const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array1_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$array17_u8_17(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 17 }, (): Uint8Array => { + return (new Uint8Array(17) as unknown) as Uint8Array; + }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; + const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array17_array17_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_array17_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + const iter2: rt.Iter = rt.iterLend(rt.iterSlice(fill), rt.byteSliceFrom); + while (true) { + const _26: rt.ByteSlice | rt.Done = iter2.next(); + if (_26 === rt.DONE) { + break; + } + picks.push(copy$array_u8(rt.byteSliceToArray(_26))); + } + const iter3: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_array17_u8(fill), [17, 90] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_29]; - rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(1, 1))); + const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(17, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array, [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_57[0]))), (v: rt.u8): undefined => { - put$lengths_Put_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterLend(rt.iterSlice(_86[0]), rt.byteSliceFrom), (v2: rt.ByteSlice): undefined => { + put$lengths_Put_array17_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledBytes$17(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { - const item = ([new Uint8Array(17), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; - const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array17_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$array1_u8_1(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 1 }, (): Uint8Array => { + return (new Uint8Array(1) as unknown) as Uint8Array; + }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; + const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array1_array1_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_array1_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + const iter2: rt.Iter = rt.iterLend(rt.iterSlice(fill), rt.byteSliceFrom); + while (true) { + const _26: rt.ByteSlice | rt.Done = iter2.next(); + if (_26 === rt.DONE) { + break; + } + picks.push(copy$array_u8(rt.byteSliceToArray(_26))); + } + const iter3: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_array1_u8(fill), [1, 90] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_29]; - rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(17, 1))); + const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(1, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array, [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_57[0]))), (v: rt.u8): undefined => { - put$lengths_Put_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterLend(rt.iterSlice(_86[0]), rt.byteSliceFrom), (v2: rt.ByteSlice): undefined => { + put$lengths_Put_array1_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledBytes$3(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { - const item = ([new Uint8Array(3), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; - const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array3_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$array3_u8_3(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 3 }, (): Uint8Array => { + return (new Uint8Array(3) as unknown) as Uint8Array; + }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; + const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array3_array3_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_array3_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + const iter2: rt.Iter = rt.iterLend(rt.iterSlice(fill), rt.byteSliceFrom); + while (true) { + const _26: rt.ByteSlice | rt.Done = iter2.next(); + if (_26 === rt.DONE) { + break; + } + picks.push(copy$array_u8(rt.byteSliceToArray(_26))); + } + const iter3: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array[], [rt.u8, rt.u8]], Uint8Array | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_array3_u8(fill), [3, 90] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_29]; - rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(3, 1))); + const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(3, 1))); + const tags: [rt.u8, rt.u8] = slot[1]; + tags[0] = tags[0] ^ byte; + tags[1] = rt.u8WrappingAdd(tags[1], byte); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); + } + for (const _79 of slots) { + const _86: [Uint8Array[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterLend(rt.iterSlice(_86[0]), rt.byteSliceFrom), (v2: rt.ByteSlice): undefined => { + put$lengths_Put_array3_u8(v2, out); + }); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); + } +} + +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$lengths_Tagged_u32_0(data: rt.ByteSlice, fill: lengths_Tagged.Tagged[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 0 }, (): lengths_Tagged.Tagged => { + return (new lengths_Tagged.Tagged((undefined as unknown) as rt.u32, (undefined as unknown) as rt.u8) as unknown) as lengths_Tagged.Tagged; + }), [undefined, undefined]] as unknown) as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]; + const slots: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array0_lengths_Tagged_u32_tuple2_u8_u8(item); + }); + const iter: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + while (true) { + const _12: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + if (_12 === rt.DONE) { + break; + } + const at: rt.u8 = _12[1]; + const uninit = _12[0]; + rt.ptrWrite(uninit, [copy$array_lengths_Tagged_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit; + } + const picks: Array | undefined> = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_lengths_Tagged_u32(fill), [0, 90] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit2; + } + for (const byte of rt.byteSliceView(data)) { + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); + } + const slot: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(0, 1))); + const tags: [rt.u8, rt.u8] = slot[1]; + tags[0] = tags[0] ^ byte; + tags[1] = rt.u8WrappingAdd(tags[1], byte); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); + } + for (const _79 of slots) { + const _86: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: lengths_Tagged.Tagged): undefined => { + lengths_Tagged.put$lengths_Put_u32(v2, out); + }); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); + } +} + +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$lengths_Tagged_u32_1(data: rt.ByteSlice, fill: lengths_Tagged.Tagged[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 1 }, (): lengths_Tagged.Tagged => { + return (new lengths_Tagged.Tagged((undefined as unknown) as rt.u32, (undefined as unknown) as rt.u8) as unknown) as lengths_Tagged.Tagged; + }), [undefined, undefined]] as unknown) as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]; + const slots: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array1_lengths_Tagged_u32_tuple2_u8_u8(item); + }); + const iter: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + while (true) { + const _12: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + if (_12 === rt.DONE) { + break; + } + const at: rt.u8 = _12[1]; + const uninit = _12[0]; + rt.ptrWrite(uninit, [copy$array_lengths_Tagged_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit; + } + const picks: Array | undefined> = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_lengths_Tagged_u32(fill), [1, 90] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit2; + } + for (const byte of rt.byteSliceView(data)) { + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); + } + const slot: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(1, 1))); + const tags: [rt.u8, rt.u8] = slot[1]; + tags[0] = tags[0] ^ byte; + tags[1] = rt.u8WrappingAdd(tags[1], byte); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); + } + for (const _79 of slots) { + const _86: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: lengths_Tagged.Tagged): undefined => { + lengths_Tagged.put$lengths_Put_u32(v2, out); + }); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); + } +} + +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$lengths_Tagged_u32_17(data: rt.ByteSlice, fill: lengths_Tagged.Tagged[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 17 }, (): lengths_Tagged.Tagged => { + return (new lengths_Tagged.Tagged((undefined as unknown) as rt.u32, (undefined as unknown) as rt.u8) as unknown) as lengths_Tagged.Tagged; + }), [undefined, undefined]] as unknown) as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]; + const slots: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array17_lengths_Tagged_u32_tuple2_u8_u8(item); + }); + const iter: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + while (true) { + const _12: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + if (_12 === rt.DONE) { + break; + } + const at: rt.u8 = _12[1]; + const uninit = _12[0]; + rt.ptrWrite(uninit, [copy$array_lengths_Tagged_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit; + } + const picks: Array | undefined> = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_lengths_Tagged_u32(fill), [17, 90] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit2; + } + for (const byte of rt.byteSliceView(data)) { + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); + } + const slot: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(17, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array, [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_57[0]))), (v: rt.u8): undefined => { - put$lengths_Put_u8(v, out); + for (const _79 of slots) { + const _86: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: lengths_Tagged.Tagged): undefined => { + lengths_Tagged.put$lengths_Put_u32(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledWords$0(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$lengths_Tagged_u32_3(data: rt.ByteSlice, fill: lengths_Tagged.Tagged[], out: rt.ByteVec): void { + const item = ([Array.from({ length: 3 }, (): lengths_Tagged.Tagged => { + return (new lengths_Tagged.Tagged((undefined as unknown) as rt.u32, (undefined as unknown) as rt.u8) as unknown) as lengths_Tagged.Tagged; + }), [undefined, undefined]] as unknown) as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]; + const slots: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array3_lengths_Tagged_u32_tuple2_u8_u8(item); + }); + const iter: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + while (true) { + const _12: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + if (_12 === rt.DONE) { + break; + } + const at: rt.u8 = _12[1]; + const uninit = _12[0]; + rt.ptrWrite(uninit, [copy$array_lengths_Tagged_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit; + } + const picks: Array | undefined> = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[lengths_Tagged.Tagged[], [rt.u8, rt.u8]], lengths_Tagged.Tagged | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_lengths_Tagged_u32(fill), [3, 90] as [rt.u8, rt.u8]] as [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]); + uninit2; + } + for (const byte of rt.byteSliceView(data)) { + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); + } + const slot: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = slots[_58]; + rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(3, 1))); + const tags: [rt.u8, rt.u8] = slot[1]; + tags[0] = tags[0] ^ byte; + tags[1] = rt.u8WrappingAdd(tags[1], byte); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); + } + for (const _79 of slots) { + const _86: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: lengths_Tagged.Tagged): undefined => { + lengths_Tagged.put$lengths_Put_u32(v2, out); + }); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); + } +} + +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u32_0(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { const item = ([new Array(0), [undefined, undefined]] as unknown) as [rt.u32[], [rt.u8, rt.u8]]; const slots: [rt.u32[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [rt.u32[], [rt.u8, rt.u8]] => { return copy$mem_MaybeUninit_tuple2_array0_u32_tuple2_u8_u8(item); @@ -559,28 +912,47 @@ export function filledWords$0(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVe rt.ptrWrite(uninit, [copy$array_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u32(fill), [0, 90] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_29]; + const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_58]; rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(0, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [rt.u32[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(_57[0]), (v: rt.u32): undefined => { - put$lengths_Put_u32(v, out); + for (const _79 of slots) { + const _86: [rt.u32[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: rt.u32): undefined => { + put$lengths_Put_u32(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledWords$1(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u32_1(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { const item = ([new Array(1), [undefined, undefined]] as unknown) as [rt.u32[], [rt.u8, rt.u8]]; const slots: [rt.u32[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [rt.u32[], [rt.u8, rt.u8]] => { return copy$mem_MaybeUninit_tuple2_array1_u32_tuple2_u8_u8(item); @@ -596,28 +968,47 @@ export function filledWords$1(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVe rt.ptrWrite(uninit, [copy$array_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u32(fill), [1, 90] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_29]; + const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_58]; rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(1, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [rt.u32[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(_57[0]), (v: rt.u32): undefined => { - put$lengths_Put_u32(v, out); + for (const _79 of slots) { + const _86: [rt.u32[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: rt.u32): undefined => { + put$lengths_Put_u32(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledWords$17(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u32_17(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { const item = ([new Array(17), [undefined, undefined]] as unknown) as [rt.u32[], [rt.u8, rt.u8]]; const slots: [rt.u32[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [rt.u32[], [rt.u8, rt.u8]] => { return copy$mem_MaybeUninit_tuple2_array17_u32_tuple2_u8_u8(item); @@ -633,28 +1024,47 @@ export function filledWords$17(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteV rt.ptrWrite(uninit, [copy$array_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u32(fill), [17, 90] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_29]; + const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_58]; rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(17, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [rt.u32[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(_57[0]), (v: rt.u32): undefined => { - put$lengths_Put_u32(v, out); + for (const _79 of slots) { + const _86: [rt.u32[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: rt.u32): undefined => { + put$lengths_Put_u32(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledWords$3(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u32_3(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVec): void { const item = ([new Array(3), [undefined, undefined]] as unknown) as [rt.u32[], [rt.u8, rt.u8]]; const slots: [rt.u32[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [rt.u32[], [rt.u8, rt.u8]] => { return copy$mem_MaybeUninit_tuple2_array3_u32_tuple2_u8_u8(item); @@ -670,180 +1080,262 @@ export function filledWords$3(data: rt.ByteSlice, fill: rt.u32[], out: rt.ByteVe rt.ptrWrite(uninit, [copy$array_u32(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of fill) { + picks.push(_26); + } + const iter3: rt.Iter<[[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[rt.u32[], [rt.u8, rt.u8]], rt.u32 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u32(fill), [3, 90] as [rt.u8, rt.u8]] as [rt.u32[], [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_29]; + const slot: [rt.u32[], [rt.u8, rt.u8]] = slots[_58]; rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(3, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [rt.u32[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterSlice(_57[0]), (v: rt.u32): undefined => { - put$lengths_Put_u32(v, out); + for (const _79 of slots) { + const _86: [rt.u32[], [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(_86[0]), (v2: rt.u32): undefined => { + put$lengths_Put_u32(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledRows$0(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { - const item = ([Array.from({ length: 0 }, (): Uint8Array => { - return (new Uint8Array(0) as unknown) as Uint8Array; - }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; - const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array0_array0_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u8_0(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { + const item = ([new Uint8Array(0), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; + const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array0_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_array0_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of rt.byteSliceView(rt.byteSliceFrom(fill))) { + picks.push(_26); + } + const iter3: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u8(fill), [0, 90] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_29]; - rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(0, 1))); + const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_58]; + rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(0, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterLend(rt.iterSlice(_57[0]), rt.byteSliceFrom), (v: rt.ByteSlice): undefined => { - put$lengths_Put_array0_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array, [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_86[0]))), (v2: rt.u8): undefined => { + put$lengths_Put_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledRows$1(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { - const item = ([Array.from({ length: 1 }, (): Uint8Array => { - return (new Uint8Array(1) as unknown) as Uint8Array; - }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; - const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array1_array1_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u8_1(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { + const item = ([new Uint8Array(1), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; + const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array1_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_array1_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of rt.byteSliceView(rt.byteSliceFrom(fill))) { + picks.push(_26); + } + const iter3: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u8(fill), [1, 90] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_29]; - rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(1, 1))); + const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_58]; + rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(1, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterLend(rt.iterSlice(_57[0]), rt.byteSliceFrom), (v: rt.ByteSlice): undefined => { - put$lengths_Put_array1_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array, [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_86[0]))), (v2: rt.u8): undefined => { + put$lengths_Put_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledRows$17(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { - const item = ([Array.from({ length: 17 }, (): Uint8Array => { - return (new Uint8Array(17) as unknown) as Uint8Array; - }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; - const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array17_array17_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u8_17(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { + const item = ([new Uint8Array(17), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; + const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array17_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_array17_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of rt.byteSliceView(rt.byteSliceFrom(fill))) { + picks.push(_26); + } + const iter3: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u8(fill), [17, 90] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_29]; - rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(17, 1))); + const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_58]; + rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(17, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterLend(rt.iterSlice(_57[0]), rt.byteSliceFrom), (v: rt.ByteSlice): undefined => { - put$lengths_Put_array17_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array, [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_86[0]))), (v2: rt.u8): undefined => { + put$lengths_Put_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } -export function filledRows$3(data: rt.ByteSlice, fill: Uint8Array[], out: rt.ByteVec): void { - const item = ([Array.from({ length: 3 }, (): Uint8Array => { - return (new Uint8Array(3) as unknown) as Uint8Array; - }), [undefined, undefined]] as unknown) as [Uint8Array[], [rt.u8, rt.u8]]; - const slots: [Uint8Array[], [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array[], [rt.u8, rt.u8]] => { - return copy$mem_MaybeUninit_tuple2_array3_array3_u8_tuple2_u8_u8(item); +/** + * Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while + * nothing points into them, the last two again beside a vector's iterator, which std + * drops, then changed in place, a pair of tags through a pointer to it, and read back. + */ +export function filled$u8_3(data: rt.ByteSlice, fill: Uint8Array, out: rt.ByteVec): void { + const item = ([new Uint8Array(3), [undefined, undefined]] as unknown) as [Uint8Array, [rt.u8, rt.u8]]; + const slots: [Uint8Array, [rt.u8, rt.u8]][] = Array.from({ length: 3 }, (): [Uint8Array, [rt.u8, rt.u8]] => { + return copy$mem_MaybeUninit_tuple2_array3_u8_tuple2_u8_u8(item); }); - const iter: rt.Iter<[[Uint8Array[], [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); + const iter: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8]> = rt.iterZip(rt.iterSlice(slots), new rt.RangeFrom(0, rt.u8Step), "len"); while (true) { - const _12: [[Uint8Array[], [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); + const _12: [[Uint8Array, [rt.u8, rt.u8]], rt.u8] | rt.Done = iter.next(); if (_12 === rt.DONE) { break; } const at: rt.u8 = _12[1]; const uninit = _12[0]; - rt.ptrWrite(uninit, [copy$array_array3_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array[], [rt.u8, rt.u8]]); + rt.ptrWrite(uninit, [copy$array_u8(fill), [at, ~at & 0xff] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); uninit; } + const picks: Array = []; + for (const _26 of rt.byteSliceView(rt.byteSliceFrom(fill))) { + picks.push(_26); + } + const iter3: rt.Iter<[[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined]> = rt.iterZip(rt.iterSkip(rt.iterSlice(slots), 1), rt.iterSlice(picks), "len"); + while (true) { + const _41: [[Uint8Array, [rt.u8, rt.u8]], rt.u8 | undefined] | rt.Done = iter3.next(); + if (_41 === rt.DONE) { + break; + } + const uninit2 = _41[0]; + rt.ptrWrite(uninit2, [copy$array_u8(fill), [3, 90] as [rt.u8, rt.u8]] as [Uint8Array, [rt.u8, rt.u8]]); + uninit2; + } for (const byte of rt.byteSliceView(data)) { - const _29: rt.usize = rt.usizeRem(byte as rt.usize, 3); - if (!(_29 < 3)) { - rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _29); + const _58: rt.usize = rt.usizeRem(byte as rt.usize, 3); + if (!(_58 < 3)) { + rt.panic("index out of bounds: the len is " + 3 + " but the index is " + _58); } - const slot: [Uint8Array[], [rt.u8, rt.u8]] = slots[_29]; - rt.sliceRotateLeft(slot[0], rt.usizeRem(byte as rt.usize, rt.max(3, 1))); + const slot: [Uint8Array, [rt.u8, rt.u8]] = slots[_58]; + rt.byteSliceRotateLeft(rt.byteSliceFrom(slot[0]), rt.usizeRem(byte as rt.usize, rt.max(3, 1))); const tags: [rt.u8, rt.u8] = slot[1]; tags[0] = tags[0] ^ byte; tags[1] = rt.u8WrappingAdd(tags[1], byte); rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(tags[0], tags[1])), undefined, true); } - for (const _50 of slots) { - const _57: [Uint8Array[], [rt.u8, rt.u8]] = _50; - rt.iterForEach(rt.iterLend(rt.iterSlice(_57[0]), rt.byteSliceFrom), (v: rt.ByteSlice): undefined => { - put$lengths_Put_array3_u8(v, out); + for (const _79 of slots) { + const _86: [Uint8Array, [rt.u8, rt.u8]] = _79; + rt.iterForEach(rt.iterSlice(rt.byteSliceView(rt.byteSliceFrom(_86[0]))), (v2: rt.u8): undefined => { + put$lengths_Put_u8(v2, out); }); - rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_57[1][0], _57[1][1])), undefined, true); + rt.iterExtendBytes(out, rt.iterSlice(Uint8Array.of(_86[1][0], _86[1][1])), undefined, true); } } diff --git a/ts/fixtures/lang/expected/lib.ts b/ts/fixtures/lang/expected/lib.ts index 70fe8186f..efd8f0946 100644 --- a/ts/fixtures/lang/expected/lib.ts +++ b/ts/fixtures/lang/expected/lib.ts @@ -259,6 +259,10 @@ export function copy$array_keys_Hop(v: Hop.Hop[]): Hop.Hop[] { return v.map(copy$keys_Hop); } +export function copy$array_lengths_Tagged_u32(v: lengths_Tagged.Tagged[]): lengths_Tagged.Tagged[] { + return v.slice(); +} + export function copy$array_ptr_array4_u8(v: rt.ByteSlice[]): rt.ByteSlice[] { return v.slice(); } @@ -417,6 +421,13 @@ export function copy$mem_MaybeUninit_array_array3_u8(v: Uint8Array[]): Uint8Arra return v.map(copy$mem_MaybeUninit_array_u8); } +export function copy$mem_MaybeUninit_array_lengths_Tagged_u32(v: lengths_Tagged.Tagged[]): lengths_Tagged.Tagged[] { + if (v === undefined) { + return v; + } + return v.slice(); +} + export function copy$mem_MaybeUninit_array_u32(v: rt.u32[]): rt.u32[] { if (v === undefined) { return v; @@ -438,6 +449,13 @@ export function copy$mem_MaybeUninit_tuple2_array0_array0_u8_tuple2_u8_u8(v: [Ui return [copy$mem_MaybeUninit_array_array0_u8(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; } +export function copy$mem_MaybeUninit_tuple2_array0_lengths_Tagged_u32_tuple2_u8_u8(v: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] { + if (v === undefined) { + return v; + } + return [copy$mem_MaybeUninit_array_lengths_Tagged_u32(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; +} + export function copy$mem_MaybeUninit_tuple2_array0_u32_tuple2_u8_u8(v: [rt.u32[], [rt.u8, rt.u8]]): [rt.u32[], [rt.u8, rt.u8]] { if (v === undefined) { return v; @@ -459,6 +477,13 @@ export function copy$mem_MaybeUninit_tuple2_array17_array17_u8_tuple2_u8_u8(v: [ return [copy$mem_MaybeUninit_array_array17_u8(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; } +export function copy$mem_MaybeUninit_tuple2_array17_lengths_Tagged_u32_tuple2_u8_u8(v: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] { + if (v === undefined) { + return v; + } + return [copy$mem_MaybeUninit_array_lengths_Tagged_u32(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; +} + export function copy$mem_MaybeUninit_tuple2_array17_u32_tuple2_u8_u8(v: [rt.u32[], [rt.u8, rt.u8]]): [rt.u32[], [rt.u8, rt.u8]] { if (v === undefined) { return v; @@ -480,6 +505,13 @@ export function copy$mem_MaybeUninit_tuple2_array1_array1_u8_tuple2_u8_u8(v: [Ui return [copy$mem_MaybeUninit_array_array1_u8(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; } +export function copy$mem_MaybeUninit_tuple2_array1_lengths_Tagged_u32_tuple2_u8_u8(v: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] { + if (v === undefined) { + return v; + } + return [copy$mem_MaybeUninit_array_lengths_Tagged_u32(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; +} + export function copy$mem_MaybeUninit_tuple2_array1_u32_tuple2_u8_u8(v: [rt.u32[], [rt.u8, rt.u8]]): [rt.u32[], [rt.u8, rt.u8]] { if (v === undefined) { return v; @@ -501,6 +533,13 @@ export function copy$mem_MaybeUninit_tuple2_array3_array3_u8_tuple2_u8_u8(v: [Ui return [copy$mem_MaybeUninit_array_array3_u8(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; } +export function copy$mem_MaybeUninit_tuple2_array3_lengths_Tagged_u32_tuple2_u8_u8(v: [lengths_Tagged.Tagged[], [rt.u8, rt.u8]]): [lengths_Tagged.Tagged[], [rt.u8, rt.u8]] { + if (v === undefined) { + return v; + } + return [copy$mem_MaybeUninit_array_lengths_Tagged_u32(v[0]), copy$mem_MaybeUninit_tuple2_u8_u8(v[1])]; +} + export function copy$mem_MaybeUninit_tuple2_array3_u32_tuple2_u8_u8(v: [rt.u32[], [rt.u8, rt.u8]]): [rt.u32[], [rt.u8, rt.u8]] { if (v === undefined) { return v; diff --git a/ts/fixtures/lang/src/lengths.rs b/ts/fixtures/lang/src/lengths.rs index 25e504577..4064c8139 100644 --- a/ts/fixtures/lang/src/lengths.rs +++ b/ts/fixtures/lang/src/lengths.rs @@ -25,13 +25,18 @@ fn each(data: &[u8], out: &mut Vec) { joined(data, vec![[0xa5; N], std::array::from_fn(|i| i as u8)], out); retagged(&rows, out); recloned(&wide, out); - filled_bytes::(data, std::array::from_fn(|i| i as u8), out); - filled_words::(data, std::array::from_fn(|i| 0x0102_0304 * i as u32), out); - filled_rows::( + filled::(data, std::array::from_fn(|i| i as u8), out); + filled::(data, std::array::from_fn(|i| 0x0102_0304 * i as u32), out); + filled::<[u8; N], N>( data, std::array::from_fn(|i| std::array::from_fn(|j| (i * N + j) as u8)), out, ); + filled::, N>( + data, + std::array::from_fn(|i| Tagged(i as u32 * 0x0101, !(i as u8))), + out, + ); swapped(data, &rows, out); swapped(data, &wide, out); } @@ -77,40 +82,38 @@ fn recloned, const N: usize>(rows: &[[T; N]], out: &mut Vec< } } -/// Slots of `MaybeUninit` arrays of `$elem`, each written whole through an iterator -/// while nothing points into them, then changed in place, a pair of tags through a pointer -/// to it, and read back. Over the length alone: a type parameter's values would be types -/// std's iterators may run the crate's code on. -macro_rules! filled { - ($name:ident, $elem:ty) => { - fn $name(data: &[u8], fill: [$elem; N], out: &mut Vec) { - let mut slots: [MaybeUninit<([$elem; N], (u8, u8))>; 3] = [const { MaybeUninit::uninit() }; 3]; - for (slot, at) in slots.iter_mut().zip(0u8..) { - slot.write((fill, (at, !at))); - } - for &byte in data { - let slot = unsafe { slots[usize::from(byte) % 3].assume_init_mut() }; - slot.0.rotate_left(usize::from(byte) % N.max(1)); - let tags = &raw mut slot.1; - unsafe { - (*tags).0 ^= byte; - (*tags).1 = (*tags).1.wrapping_add(byte); - out.extend([(*tags).0, (*tags).1]); - } - } - for slot in &slots { - let (values, (a, b)) = unsafe { slot.assume_init_ref() }; - values.iter().for_each(|v| v.put(out)); - out.extend([*a, *b]); - } +/// Slots of `MaybeUninit` arrays of `T`, each written whole through an iterator while +/// nothing points into them, the last two again beside a vector's iterator, which std +/// drops, then changed in place, a pair of tags through a pointer to it, and read back. +fn filled(data: &[u8], fill: [T; N], out: &mut Vec) { + let mut slots: [MaybeUninit<([T; N], (u8, u8))>; 3] = [const { MaybeUninit::uninit() }; 3]; + for (slot, at) in slots.iter_mut().zip(0u8..) { + slot.write((fill, (at, !at))); + } + let mut picks = Vec::new(); + for &v in &fill { + picks.push(Some(v)); + } + for (slot, _) in slots.iter_mut().skip(1).zip(picks) { + slot.write((fill, (N as u8, 0x5a))); + } + for &byte in data { + let slot = unsafe { slots[usize::from(byte) % 3].assume_init_mut() }; + slot.0.rotate_left(usize::from(byte) % N.max(1)); + let tags = &raw mut slot.1; + unsafe { + (*tags).0 ^= byte; + (*tags).1 = (*tags).1.wrapping_add(byte); + out.extend([(*tags).0, (*tags).1]); } - }; + } + for slot in &slots { + let (values, (a, b)) = unsafe { slot.assume_init_ref() }; + values.iter().for_each(|v| v.put(out)); + out.extend([*a, *b]); + } } -filled!(filled_bytes, u8); -filled!(filled_words, u32); -filled!(filled_rows, [u8; N]); - /// A value's bytes. trait Put { fn put(&self, out: &mut Vec); @@ -134,6 +137,13 @@ impl Put for [u8; N] { } } +impl Put for Tagged { + fn put(&self, out: &mut Vec) { + self.0.put(out); + out.push(self.1); + } +} + /// Rows of a grid swapped whole, each copy kept apart from the row it was read from as /// either changes. fn swapped, const N: usize>(data: &[u8], rows: &[[T; N]], out: &mut Vec) { diff --git a/ts/fixtures/reject/census.md b/ts/fixtures/reject/census.md index fd12576bd..1648158a7 100644 --- a/ts/fixtures/reject/census.md +++ b/ts/fixtures/reject/census.md @@ -1,14 +1,14 @@ # Census of `reject-fixture` -- Refusals: 218 -- Function instances: 271 +- Refusals: 222 +- Function instances: 283 - Generic functions no instance reached, lowered over their type parameters: 13 ## By construct | Count | Construct | First | | ---: | --- | --- | -| 45 | a raw pointer to `_` in `_`, which the crate may put another object in place of | fixtures/reject/src/lib.rs:610:10 | +| 49 | a raw pointer to `_` in `_`, which the crate may put another object in place of | fixtures/reject/src/lib.rs:610:10 | | 25 | unsupported call to `_` | fixtures/reject/src/lib.rs:167:8 | | 19 | a raw pointer to `_` in a variable assigned again while it may point there | fixtures/reject/src/lib.rs:618:10 | | 15 | a reference through which a raw pointer may be made into `_` in `_`, which the crate may put another object in place of | fixtures/reject/src/lib.rs:1339:33 | @@ -93,6 +93,7 @@ The type or module each refused type or path belongs to. | 6 | `f16` | fixtures/reject/src/lib.rs:7:14 | | 6 | `std::borrow::Cow` | fixtures/reject/src/lib.rs:338:2 | | 6 | `u32` | fixtures/reject/src/lib.rs:557:27 | +| 5 | `(u8, u8)` | fixtures/reject/src/lib.rs:1274:31 | | 5 | `Gap` | fixtures/reject/src/lib.rs:910:10 | | 5 | `Option` | fixtures/reject/src/lib.rs:16:15 | | 5 | `u8` | fixtures/reject/src/lib.rs:260:6 | @@ -131,6 +132,10 @@ The type or module each refused type or path belongs to. | 2 | `std::sync::Arc` | fixtures/reject/src/lib.rs:298:2 | | 2 | `std::sync::MutexGuard` | fixtures/reject/src/lib.rs:90:2 | | 2 | `std::vec::IntoIter` | fixtures/reject/src/lib.rs:436:17 | +| 1 | `(Dropped, (u8, u8))` | fixtures/reject/src/lib.rs:2200:2 | +| 1 | `([Cloned; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2184:2 | +| 1 | `([Greatest; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2218:13 | +| 1 | `([Touched; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2249:2 | | 1 | `(std::vec::Vec, Tens)` | fixtures/reject/src/lib.rs:1274:31 | | 1 | `(u16, ByKeyReplace)` | fixtures/reject/src/lib.rs:1623:55 | | 1 | `(u16, ByKeySet)` | fixtures/reject/src/lib.rs:1615:51 | @@ -138,7 +143,6 @@ The type or module each refused type or path belongs to. | 1 | `(u16, ByRefReplace)` | fixtures/reject/src/lib.rs:1599:32 | | 1 | `(u16, ByRefTake)` | fixtures/reject/src/lib.rs:1607:32 | | 1 | `(u16, InTuple)` | fixtures/reject/src/lib.rs:1348:33 | -| 1 | `(u8, u8)` | fixtures/reject/src/lib.rs:1274:31 | | 1 | `*const [u8]` | fixtures/reject/src/lib.rs:1716:28 | | 1 | `*const u8` | fixtures/reject/src/lib.rs:1715:33 | | 1 | `*mut [u8; 4]` | fixtures/reject/src/lib.rs:1714:41 | @@ -313,6 +317,10 @@ The type or module each refused type or path belongs to. | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u32, u32)`, `Track` | fixtures/reject/src/lib.rs:854:19 | | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u32, u32)`, `Window` | fixtures/reject/src/lib.rs:671:2 | | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u32, u32)`, `std::cell::UnsafeCell` | fixtures/reject/src/lib.rs:689:15 | +| 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u8, u8)`, `(Dropped, (u8, u8))` | fixtures/reject/src/lib.rs:2200:2 | +| 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u8, u8)`, `([Cloned; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2184:2 | +| 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u8, u8)`, `([Greatest; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2218:13 | +| 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `(u8, u8)`, `([Touched; 2], (u8, u8))` | fixtures/reject/src/lib.rs:2249:2 | | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `ByKeyReplace`, `(u16, ByKeyReplace)` | fixtures/reject/src/lib.rs:1623:55 | | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `ByKeySet`, `(u16, ByKeySet)` | fixtures/reject/src/lib.rs:1615:51 | | 1 | a raw pointer to `_` in `_`, which the crate may put another object in place of | `ByKeyTake`, `(u16, ByKeyTake)` | fixtures/reject/src/lib.rs:1630:52 | @@ -423,7 +431,7 @@ The type or module each refused type or path belongs to. ## Spans -
a raw pointer to `_` in `_`, which the crate may put another object in place of (45) +
a raw pointer to `_` in `_`, which the crate may put another object in place of (49) - fixtures/reject/src/lib.rs:610:10: a raw pointer to `(u32, u32)` in `Span2`, which the crate may put another object in place of - fixtures/reject/src/lib.rs:671:2: a raw pointer to `(u32, u32)` in `Window`, which the crate may put another object in place of @@ -470,6 +478,10 @@ The type or module each refused type or path belongs to. - fixtures/reject/src/lib.rs:1615:51: a raw pointer to `ByKeySet` in `(u16, ByKeySet)`, which the crate may put another object in place of - fixtures/reject/src/lib.rs:1623:55: a raw pointer to `ByKeyReplace` in `(u16, ByKeyReplace)`, which the crate may put another object in place of - fixtures/reject/src/lib.rs:1630:52: a raw pointer to `ByKeyTake` in `(u16, ByKeyTake)`, which the crate may put another object in place of +- fixtures/reject/src/lib.rs:2184:2: a raw pointer to `(u8, u8)` in `([Cloned; 2], (u8, u8))`, which the crate may put another object in place of +- fixtures/reject/src/lib.rs:2200:2: a raw pointer to `(u8, u8)` in `(Dropped, (u8, u8))`, which the crate may put another object in place of +- fixtures/reject/src/lib.rs:2218:13: a raw pointer to `(u8, u8)` in `([Greatest; 2], (u8, u8))`, which the crate may put another object in place of +- fixtures/reject/src/lib.rs:2249:2: a raw pointer to `(u8, u8)` in `([Touched; 2], (u8, u8))`, which the crate may put another object in place of
diff --git a/ts/fixtures/reject/expected.txt b/ts/fixtures/reject/expected.txt index f194a04cf..284f7996b 100644 --- a/ts/fixtures/reject/expected.txt +++ b/ts/fixtures/reject/expected.txt @@ -215,3 +215,7 @@ a raw pointer to `std::cell::UnsafeCell` in `InField`, which the crate may a raw pointer to `std::cell::UnsafeCell` in `InGeneric`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:1324:9 a raw pointer to `std::cell::UnsafeCell` in `InWritten`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:1328:9 a reference to `std::option::Option>`, through which a raw pointer may be made, in a variable assigned again while that pointer may point there at fixtures/reject/src/lib.rs:2110:13 +a raw pointer to `(u8, u8)` in `([Cloned; 2], (u8, u8))`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:2162:23 +a raw pointer to `(u8, u8)` in `(Dropped, (u8, u8))`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:2162:23 +a raw pointer to `(u8, u8)` in `([Greatest; 2], (u8, u8))`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:2218:13 +a raw pointer to `(u8, u8)` in `([Touched; 2], (u8, u8))`, which the crate may put another object in place of at fixtures/reject/src/lib.rs:2162:23 diff --git a/ts/fixtures/reject/src/lib.rs b/ts/fixtures/reject/src/lib.rs index 279bfe6e7..860ddfd3e 100644 --- a/ts/fixtures/reject/src/lib.rs +++ b/ts/fixtures/reject/src/lib.rs @@ -2154,3 +2154,97 @@ pub fn mapped_closure(add: u8) -> u8 { let f = std::cell::RefMut::map(cell.borrow_mut(), |pair| &mut pair.0); f(1) } + +/// The tags of the first of two slots, each written whole as `fill` beside a pair of +/// tags, then changed through a pointer to them. +macro_rules! tagged_slots { + ($slots:ident) => {{ + let tags = unsafe { &raw mut $slots[0].assume_init_mut().1 }; + unsafe { + (*tags).0 ^= 1; + (*tags).0 + } + }}; +} + +#[derive(Clone, Copy)] +pub struct Cloned(pub u8); + +/// Slots of a type parameter's values written whole through an iterator zipped with +/// clones of them: std's code calls the crate's `Clone`, so the writes fill nothing fresh. +pub fn cloned_slots(fill: [Cloned; 2]) -> u8 { + kept_slots(fill) +} + +fn kept_slots(fill: [T; 2]) -> u8 { + let mut slots: [std::mem::MaybeUninit<([T; 2], (u8, u8))>; 2] = [const { std::mem::MaybeUninit::uninit() }; 2]; + for (slot, value) in slots.iter_mut().zip(fill.iter().cloned()) { + slot.write(([value.clone(), value], (0, 1))); + } + tagged_slots!(slots) +} + +pub struct Dropped(pub Noisy); + +/// [`cloned_slots`] zipped with a vector's values, which std's iterator drops through +/// the crate's `Drop` of a field. +pub fn dropped_slots(fill: Vec) -> u8 { + moved_slots(fill) +} + +fn moved_slots(fill: Vec) -> u8 { + let mut slots: [std::mem::MaybeUninit<(T, (u8, u8))>; 2] = [const { std::mem::MaybeUninit::uninit() }; 2]; + for (slot, value) in slots.iter_mut().zip(fill) { + slot.write((value, (0, 1))); + } + tagged_slots!(slots) +} + +#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)] +pub struct Greatest(pub u8); + +/// A slot written whole through the greatest of a type parameter's values, which std +/// finds through the crate's `Ord`. +pub fn ranked_slots(fill: [Greatest; 2]) -> u8 { + greatest_slot(fill) +} + +fn greatest_slot(fill: [T; 2]) -> u8 { + let mut slots: [([T; 2], (u8, u8)); 2] = [(fill, (0, 0)); 2]; + let Some(top) = slots.iter_mut().max() else { + return 0; + }; + *top = (fill, (1, 2)); + let tags = &raw mut top.1; + unsafe { + (*tags).0 ^= 1; + (*tags).0 + } +} + +/// What a type parameter's value does to a slot of it. +pub trait Touch: Sized { + fn touch(&self, slot: &mut std::mem::MaybeUninit<([Self; 2], (u8, u8))>); +} + +#[derive(Clone, Copy)] +pub struct Touched(pub u8); + +impl Touch for Touched { + fn touch(&self, _: &mut std::mem::MaybeUninit<([Self; 2], (u8, u8))>) {} +} + +/// [`cloned_slots`] where each slot is first given to the crate's own trait, through +/// the type parameter's bound. +pub fn touched_slots(fill: [Touched; 2]) -> u8 { + given_slots(fill) +} + +fn given_slots(fill: [T; 2]) -> u8 { + let mut slots: [std::mem::MaybeUninit<([T; 2], (u8, u8))>; 2] = [const { std::mem::MaybeUninit::uninit() }; 2]; + for (slot, at) in slots.iter_mut().zip(0u8..) { + fill[0].touch(slot); + slot.write((fill, (at, !at))); + } + tagged_slots!(slots) +} diff --git a/ts/fixtures/reject/ts.toml b/ts/fixtures/reject/ts.toml index 532e7378e..ea7f18773 100644 --- a/ts/fixtures/reject/ts.toml +++ b/ts/fixtures/reject/ts.toml @@ -166,5 +166,9 @@ roots = [ "block_cloned", "lists", "mapped_closure", + "cloned_slots", + "dropped_slots", + "ranked_slots", + "touched_slots", ] printable = ["Meters"] diff --git a/ts/src/lower/mir/holders.rs b/ts/src/lower/mir/holders.rs index 3f5afdf72..8d3c99722 100644 --- a/ts/src/lower/mir/holders.rs +++ b/ts/src/lower/mir/holders.rs @@ -269,7 +269,7 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { } TerminatorKind::Drop { place, .. } if held.all.contains(place.local) - && self.runs_own_code(place.ty(&mir.local_decls, self.t.tcx).ty) => + && self.drops_own_code(place.ty(&mir.local_decls, self.t.tcx).ty) => { held.escapes.push(at); } @@ -485,9 +485,7 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { } // Until found, as for an impl whose bounds come back to it, it may not be. self.memo.borrow_mut().inert.insert(key, false); - let inert = args - .types() - .all(|t| !self.runs_own_code(t) || !t.needs_drop(tcx, self.env)) + let inert = args.types().all(|t| !self.drops_own_code(t)) && tcx .clauses_of(did) .instantiate(tcx, args) @@ -549,7 +547,24 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { /// keep what it is given: through the crate's own types, a trait object, a closure, or /// a function pointer. fn runs_own_code(&self, ty: Ty<'tcx>) -> bool { - self.t.reaches(self.env, ty, |t| match t.kind() { + self.t.reaches(self.env, ty, |t| self.own_code(t)) + } + + /// Whether dropping a value of `ty` may run the crate's code: it has drop glue and holds + /// what [`Self::runs_own_code`] counts, but a type parameter whose bounds in the body's + /// environment leave it no drop glue, as `Copy` does. + fn drops_own_code(&self, ty: Ty<'tcx>) -> bool { + let tcx = self.t.tcx; + ty.needs_drop(tcx, self.env) + && self.t.reaches(self.env, ty, |t| match t.kind() { + ty::Param(_) => t.needs_drop(tcx, self.env), + _ => self.own_code(t), + }) + } + + /// Whether `ty` itself, not what it holds, is what [`Self::runs_own_code`] counts. + fn own_code(&self, ty: Ty<'tcx>) -> bool { + match ty.kind() { ty::Adt(adt, _) => self.t.own(adt.did()), ty::FnDef(def_id, args) => self.translated(*def_id, args.skip_binder()), ty::Dynamic(..) @@ -560,11 +575,24 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { | ty::Param(_) | ty::Alias(..) => true, _ => false, - }) + } } /// Whether a value of `ty` could hold a pointer or a reference, in any field of any type. fn carries(&self, ty: Ty<'tcx>) -> bool { + self.holds_pointer(ty, true) + } + + /// Whether code reading a value of `ty` could get a pointer or a reference out of it: as + /// [`Self::carries`], but for one a type parameter's value holds, which code generic + /// over it gets only as a whole value of that parameter, never a pointer itself. + fn shows_pointer(&self, ty: Ty<'tcx>) -> bool { + self.holds_pointer(ty, false) + } + + /// Whether a value of `ty` could hold a pointer or a reference, in any field of any + /// type, and with `params`, in a type parameter's value. + fn holds_pointer(&self, ty: Ty<'tcx>, params: bool) -> bool { let mut seen = FxHashSet::default(); let mut stack = vec![ty]; while let Some(ty) = stack.pop() { @@ -587,6 +615,7 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { adt.all_fields() .map(|field| field_ty(self.t.tcx, self.env, field.did, args)), ), + ty::Param(_) if !params => {} _ => return true, } } @@ -704,9 +733,12 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { } /// The types a value of `ty` holds in place, through std's types too; `None` if its type - /// doesn't tell, as a type parameter's or a trait object's. + /// doesn't tell, as a trait object's. A type parameter's value holds none the body or + /// std's code can see: code generic over it sees inside only through its bounds, which + /// run the crate's code, and std's code that reinterprets memory is refused. fn fields(&self, ty: Ty<'tcx>) -> Option>> { Some(match ty.kind() { + ty::Param(_) => Vec::new(), ty::Bool | ty::Char | ty::Int(_) @@ -794,7 +826,7 @@ impl<'x, 'a, 'tcx> Trace<'x, 'a, 'tcx> { Some(()) }; while let Some((local, deep)) = stack.pop() { - if !seen.insert((local, deep)) || deep && !self.carries(self.mir.local_decls[local].ty) { + if !seen.insert((local, deep)) || deep && !self.shows_pointer(self.mir.local_decls[local].ty) { continue; } if defs[local].other { diff --git a/ts/src/lower/mir/mod.rs b/ts/src/lower/mir/mod.rs index 3de8956e0..62fcd8c54 100644 --- a/ts/src/lower/mir/mod.rs +++ b/ts/src/lower/mir/mod.rs @@ -3154,20 +3154,28 @@ pub(super) fn whole(value: Expr, ty: Type) -> Result { } impl<'tcx> Translator<'_, 'tcx> { - /// Whether a value of `ty` reaches somewhere that could take a `part` in: a raw - /// pointer, or a mutable reference to or interior mutability around what could hold one. - /// `env` holds the bounds of the body naming `ty`. + /// Whether a value of `ty` reaches somewhere that std's code could take a `part` in: a + /// raw pointer, or a mutable reference to or interior mutability around what could hold + /// one. Std's code generic over a type parameter puts in its place only a whole value of + /// it. `env` holds the bounds of the body naming `ty`. pub(crate) fn stores(&self, env: TypingEnv<'tcx>, ty: Ty<'tcx>, part: Ty<'tcx>) -> bool { use rustc_middle::ty::TypeVisitableExt; + let holds = |t| self.holds_as(env, t, part, false); self.reaches(env, ty, |t| match t.kind() { ty::RawPtr(..) => true, - ty::Ref(_, inner, rustc_ast::Mutability::Mut) => self.holds(env, *inner, part), - _ => !t.has_escaping_bound_vars() && !t.is_freeze(self.tcx, env) && self.holds(env, t, part), + ty::Ref(_, inner, rustc_ast::Mutability::Mut) => holds(*inner), + _ => !t.has_escaping_bound_vars() && !t.is_freeze(self.tcx, env) && holds(t), }) } /// Whether a value of `ty` could hold a `part`: holds its type, or hides what it holds. pub(crate) fn holds(&self, env: TypingEnv<'tcx>, ty: Ty<'tcx>, part: Ty<'tcx>) -> bool { + self.holds_as(env, ty, part, true) + } + + /// [`Self::holds`], where a type parameter's value hides what it holds only with + /// `params`, and is otherwise a `part` only as its whole. + fn holds_as(&self, env: TypingEnv<'tcx>, ty: Ty<'tcx>, part: Ty<'tcx>, params: bool) -> bool { // An array and a slice of its element share storage through an unsizing coercion. let storage = |t: Ty<'tcx>| match t.kind() { ty::Array(elem, _) => Ty::new_slice(self.tcx, *elem), @@ -3178,8 +3186,9 @@ impl<'tcx> Translator<'_, 'tcx> { storage(t) == part || matches!( t.kind(), - ty::Dynamic(..) | ty::Alias(..) | ty::Param(_) | ty::Closure(..) | ty::Coroutine(..) + ty::Dynamic(..) | ty::Alias(..) | ty::Closure(..) | ty::Coroutine(..) ) + || params && matches!(t.kind(), ty::Param(_)) }) }