diff --git a/quest/m3/README.md b/quest/m3/README.md index a8bdd7e11..1af7c61a8 100644 --- a/quest/m3/README.md +++ b/quest/m3/README.md @@ -39,7 +39,6 @@ memory model for values whose address is reinterpreted, without a consumer. - [A Pin of a crate's own Deref type](/quest/m3/ts-pin-own-deref.md) - `Pin

` over a crate's own `Deref` derefs through its impl and type-checks - [Waiting: drop the lang fixture's mul_add allowance](/quest/m3/ts-fma-allowance.md) - the differential fails on any `mul_add` difference again once wasm32's `fma` rounds exactly - [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 -- [Throw only where Rust panics](/quest/m3/ts-runtime-throws.md) - no runtime `rust2-ts:` error where native Rust goes on: exact, or refused at translation - [rust2-ts with no ts.toml](/quest/m3/ts-configless.md) - a crate's whole `pub` API translates with no config and no bound items - [Browser APIs through wasm-bindgen](/quest/m3/ts-wasm-bindgen/README.md) - web-sys and js-sys imports become direct JS calls, so idiomatic crates such as web-rs's web-codecs translate as stock crates - [`u64` wrapping arithmetic in V8](/quest/m3/ts-u64-wrapping.md) - `rs.u64WrappingAdd` and its kin cost near a plain `+` while the value is a safe integer diff --git a/quest/m3/ts-array-ref-conversions.md b/quest/m3/ts-array-ref-conversions.md index ee764bbe3..75fdee6b0 100644 --- a/quest/m3/ts-array-ref-conversions.md +++ b/quest/m3/ts-array-ref-conversions.md @@ -18,7 +18,3 @@ and lends parts of arrays where they are: its tests use `first_chunk_mut` in pla Decided with the maintainer on 2026-11-07: ✅ plan it, in m3 (from #662's follow-ups). Public API: the translator's output. - -## Related - -- [Throw only where Rust panics](/quest/m3/ts-runtime-throws.md) - its exact `ptr::eq` for `as_chunks` copies changes how an array taken from a flat slice is represented, on the same `rs.ArraySlice` diff --git a/quest/m3/ts-runtime-throws.md b/quest/m3/ts-runtime-throws.md deleted file mode 100644 index 05fb9d0f8..000000000 --- a/quest/m3/ts-runtime-throws.md +++ /dev/null @@ -1,71 +0,0 @@ -# [M] Throw only where Rust panics - -## Goal - -Code [rust2-ts](/ts/README.md) generates fails at run time only where the Rust source -does: no `rust2-ts:` error the runtime throws where native Rust would go on. Each such -construct translates exactly, or is refused at translation with a span. Proven by -differential tests against native Rust for every construct that now translates. - -## Plan - -Decided with the maintainer on 2026-11-04: "we should not panic when Rust would not -panic", and runtime throws that copy Rust's behaviour are fine. A throw that guards Rust -UB stays, as an abort worded like std's `unsafe precondition(s) violated` check. - -Decided with the maintainer on 2026-11-07, in -[moq-dev/rust2#661](https://github.com/moq-dev/rust2/pull/661), for the throws that fire -only because translation can't see where a pointer came from: - -- ✅ Refuse at translation, with a span, where the body doesn't show the pointer fits: - `rs.arcErase` (done in #661) and `alloc`'s bytes. -- ✅ Keep as loud run-time checks: `ptrUnerase`, `offset_from` across arrays, - `AtIndex.reach`, and raw slices of a field's byte, which AGENTS.md allows under m3's - [unsafe policy](/quest/m3/README.md). - Two pointers made from one reference, one through a branch or loop, may each be in - an array of one of its own; keep the loud check rather than trace joins (decided - 2026-11-07 in [#621](https://github.com/moq-dev/rust2/pull/621)). -- Rejected: refusing all of them at translation, which refuses pointer arithmetic on any - pointer parameter; keeping all as run-time checks. - -Decided with the maintainer on 2026-11-07, in the quest audit: ✅ `Bytes::slice_ref` of -bytes from other storage is refused at translation, since it is safe code and AGENTS.md -allows a run-time check only for an `unsafe` pointer. Rejected: keeping its run-time -check, as #661 had, and widening AGENTS.md's exception to safe code with no exact answer -while a `&str` stays a JS string. - -What remains: - -- `alloc`'s bytes: a byte of memory from `alloc` read or written, or the memory cast to a - type other than the one it holds, throws in `rs/alloc.ts` when the byte pointer reached - there from elsewhere. Refuse at the `alloc` or `realloc` call whose byte pointer the - body doesn't show going only to a typed cast, `dealloc`, `realloc`, or the - `NonNull`/`Option` steps [`alloc_root`](/ts/src/lower/mir/alloc.rs) already follows, so - no untyped pointer leaves the body; and a `realloc` of memory the body cast from one type - whose result it casts to another. This needs a use analysis of that pointer, which the - translator doesn't have yet. The throws in `rs/alloc.ts` are then translator guards. -- `ptr::eq` of an array `as_chunks` split from one flat slice, which std's callback gets a - copy of, answers `false` where Rust answers `true`, silently (moved here 2026-11-07 in - [#608](https://github.com/moq-dev/rust2/pull/608)). A copy that remembers the slice and - offset it came from, compared through that, is exact; it builds on the `rs.ArraySlice` - [#662](https://github.com/moq-dev/rust2/pull/662) left, where `rs.arraySliceItems` still - copies. -- `Bytes::slice_ref` of bytes from other storage throws in `bytesSliceRef` - (`ts/runtime/rs/bytes.ts`), since Rust may share what JS copied, such as a - `&'static str`'s bytes that `as_bytes` encodes anew. Refuse the call whose `subset` the - body doesn't show borrowed from that same `Bytes`, through `Deref`, `as_ref`, or a slice - of one; the throw is then a translator guard, and `ts/README.md` says so. -- `bytes`' panics in a hook program: `BYTES` in [`caller.rs`](/ts/src/lower/caller.rs) - finds each by searching the source of the program's `bytes` for text, so a - `--remap-path-prefix` of a directory inside `bytes` fails translation of a hook program. - Take each panic's location from `bytes`' compiled code for the function that panics, as - [`tokio.rs`](/ts/src/lower/tokio.rs) does for tokio's oneshot `poll`, so rustc names the - file as native does under any remap, and delete the source search (decided with the - maintainer on 2026-11-07, from [#661](https://github.com/moq-dev/rust2/pull/661)'s - follow-ups). - -Public API: the translator's output, and which crates translate. - -## Related - -- [Array references from slices and cells](/quest/m3/ts-array-ref-conversions.md) - also changes how an array taken from a flat slice is represented, on the same `rs.ArraySlice` diff --git a/ts/README.md b/ts/README.md index ca986b487..481e0aa15 100644 --- a/ts/README.md +++ b/ts/README.md @@ -123,7 +123,7 @@ crate translation reaches is refused, and so are two versions of one crate it re | `Ordering`, `DefaultHasher`, `RandomState`, `BuildHasherDefault` | `rs.Ordering`, which is `-1`, `0`, or `1`; `rs.Hasher`; `rs.RandomState`, the keys of the `DefaultHasher` it builds, never changed once made; `undefined`, as `PhantomData` is, whose `build_hasher` is `H::default()` | | `Duration` | `rs.Duration`: `{ secs, nanos }`, std's whole seconds as an `rs.u64` and the nanoseconds past them, never changed once made | | `TypeId` | `rs.TypeId`: rustc's 128-bit hash of the type, which std's holds at run time, as 32 hex digits, equal by `===`; ordered as std's derive orders the hash's pointer-sized words, lowest first, hashed as its high 64 bits, and written as `TypeId(0x…)`, as std's are | -| `Layout`, `alloc::alloc` | `rs.Layout`: `{ size, align }`, never changed once made, checked as std's constructors check it; `alloc` gives an `rs.Block` of its bytes, which a cast of its pointer to `*mut T` the body shows came from `alloc` or `realloc` makes a JS array of `T`s, values JS copies, as an `rs.AtIndex` of its first; a cast back to `*mut u8` only as what `dealloc` or `realloc` takes, which free the array or copy it into a new one, and abort on memory `alloc` didn't give, as Rust leaves that undefined; its bytes, read, written, or cast to any other type, are refused, and fail at run time through a pointer from elsewhere | +| `Layout`, `alloc::alloc` | `rs.Layout`: `{ size, align }`, never changed once made, checked as std's constructors check it; `alloc` gives an `rs.Block` of its bytes, which a cast of its pointer to `*mut T` the body shows came from `alloc` or `realloc` makes a JS array of `T`s, values JS copies, as an `rs.AtIndex` of its first; a cast back to `*mut u8` only as what `dealloc` or `realloc` takes, which free the array or copy it into a new one, and abort on memory `alloc` didn't give, as Rust leaves that undefined; its bytes, read, written, or cast to any other type, are refused, as are a call of `alloc` or `realloc` whose pointer the body passes on as bytes elsewhere, such as out of the body, and a `realloc` whose result it casts to a type other than the one the memory it grows was cast from, so no pointer to its bytes leaves the body that made it | | closure | an arrow function, with `[Symbol.dispose]` if it owns a value that drops, and what makes its clone if a clone can't be itself | | `fn` pointer, function item as a value | the function, or std's an arrow that calls it as a written call does, as a closure is typed: a `()` result is `undefined`, where a declared function returns `void` | | `&dyn Trait`, `&mut dyn Trait`, `Box`, `Arc`, `Rc`, `Weak`, `Pin

` of one | an object with the trait's methods, its supertraits' included: `shape.area$Shape()`; behind an `Arc` or an `Rc`, an `rs.ArcDyn` sharing the count of the `Arc` it was made from | @@ -193,7 +193,8 @@ where the arrays are, whether each is a JS array of its own, as a `Vec<[T; N]>` split it. A caller passes one as `rs.arraySliceFrom(arrays, rs.sliceFrom)`, `rs.byteSliceFrom` for bytes and `rs.arraySliceOf(rs.sliceFrom)` for arrays of arrays, and reads one as `rs.arraySliceItems(slice)`: the arrays themselves, or copies of the ones a split of one -slice holds, which have no array of their own. std's methods that lend arrays or parts of +slice holds, which have no array of their own, each remembered as its run, so `ptr::eq` +compares a pointer to one where the run is. std's methods that lend arrays or parts of the slice, such as `iter_mut`, `split_at_mut`, `chunks_mut`, and `swap`, take them where they are; any other reads them as `rs.arraySliceItems` does, or for a `&mut` one, such as `sort` or `rotate_left`, reads copies of the arrays, which it writes back once it returns, @@ -213,9 +214,8 @@ with its payload if that is text, or `Box` as std's hook writes any oth A program that reaches `set_hook` has each panic carry the `Location` native code gives it, std's own at the `/rustc//library/...` path its build names, read from the toolchain's source, and runs its hook with a `PanicHookInfo` before throwing; a panic in -the hook throws `rs.Abort`, as std aborts. A panic of `bytes`' own code is where the -program's `bytes` has it, and one of tokio's where its compiled code has it, named as the -session names that file: by the host's cargo registry, unless the build remaps it, as +the hook throws `rs.Abort`, as std aborts. A panic of `bytes`' or tokio's own code is +where its compiled code has it, named as the session names that file: by the host's cargo registry, unless the build remaps it, as `--remap-path-prefix` does natively. The default hook writes nothing, as wasm32 has no stderr. A program without one passes no locations, and a bundler drops the hook's runtime, `rs/hook.ts`, from it; what stays is the location @@ -765,8 +765,9 @@ of them: `rs/bytes.ts`, panicking as `bytes` does, and so do `split_to`, `split_off`, `truncate`, `clear`, and `slice_ref`, whose panic names no addresses. A `Bytes` of a `String` takes storage of its capacity, as `bytes` does. `slice_ref` of - bytes from other storage throws, since Rust may share what JS copied, as a `&'static - str`'s bytes that `as_bytes` encodes anew. `Bytes::from_owner` + bytes the body doesn't show borrowed, through `Deref`, `as_ref`, or a slice of one, from + that `Bytes` or one sharing its storage through `slice` or `clone`, is refused, since Rust + may share what JS copied, as a `&'static str`'s bytes that `as_bytes` encodes anew. `Bytes::from_owner` reads its owner's bytes once, as `bytes` does, and an owner that drops is kept in the `rs.Shared` they count, which drops it with the last `Bytes` sharing them; one of an owner is never unique, so taking it back copies. diff --git a/ts/fixtures/lang/panics/hook/expected/bytes.ts b/ts/fixtures/lang/panics/hook/expected/bytes.ts index be64a50ee..02ac6c41d 100644 --- a/ts/fixtures/lang/panics/hook/expected/bytes.ts +++ b/ts/fixtures/lang/panics/hook/expected/bytes.ts @@ -8,7 +8,7 @@ export function panicAdvance(errorInfo: TryGetError.TryGetError): never { const _8: rs.Fmt = (f: rs.Formatter) => rs.usizeDisplay(arg, f); const arg2 = errorInfo.requested; const args3 = [_8, (f: rs.Formatter) => rs.usizeDisplay(arg2, f)]; - rs.panicFmt(["advance out of bounds: the len is ", args3[0], " but advancing by ", args3[1]], { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 207, col: 5 }); + rs.panicFmt(["advance out of bounds: the len is ", args3[0], " but advancing by ", args3[1]], { file: "bytes/source/lib.rs", line: 207, col: 5 }); } //# sourceMappingURL=bytes.ts.map diff --git a/ts/fixtures/lang/panics/hook/expected/bytes/buf/take.Take.ts b/ts/fixtures/lang/panics/hook/expected/bytes/buf/take.Take.ts index df0c613a5..ad76820b1 100644 --- a/ts/fixtures/lang/panics/hook/expected/bytes/buf/take.Take.ts +++ b/ts/fixtures/lang/panics/hook/expected/bytes/buf/take.Take.ts @@ -72,8 +72,8 @@ export function tryCopyToSlice$bytes_Buf_bytes_Bytes(self: Take, d while (!(dst.length === 0)) { const src: rs.ByteSlice = chunk$bytes_Buf_bytes_Bytes_mut(self); const cnt: rs.usize = rs.min(src.length, dst.length); - rs.byteSliceCopyFromSlice(rs.byteSliceRange(dst, 0, cnt, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_impl.rs", line: 1178, col: 16 }), rs.byteSliceRange(src, 0, cnt, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_impl.rs", line: 1178, col: 44 }), { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_impl.rs", line: 1178, col: 24 }); - dst = rs.byteSliceRange(dst, cnt, undefined, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_impl.rs", line: 1179, col: 27 }); + rs.byteSliceCopyFromSlice(rs.byteSliceRange(dst, 0, cnt, { file: "bytes/source/buf/buf_impl.rs", line: 1178, col: 16 }), rs.byteSliceRange(src, 0, cnt, { file: "bytes/source/buf/buf_impl.rs", line: 1178, col: 44 }), { file: "bytes/source/buf/buf_impl.rs", line: 1178, col: 24 }); + dst = rs.byteSliceRange(dst, cnt, undefined, { file: "bytes/source/buf/buf_impl.rs", line: 1179, col: 27 }); advance$bytes_Buf_bytes_Bytes(self, cnt); } return rs.OK; @@ -225,7 +225,7 @@ export function remaining$bytes_Buf_bytes_Bytes(self: Take): rs.us */ export function chunk$bytes_Buf_bytes_Bytes(self: Take): rs.ByteSlice { const bytes: rs.ByteSlice = self.inner; - return rs.byteSliceRange(bytes, 0, min$00xoube(bytes.length, self.limit), { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/take.rs", line: 142, col: 15 }); + return rs.byteSliceRange(bytes, 0, min$00xoube(bytes.length, self.limit), { file: "bytes/source/buf/take.rs", line: 142, col: 15 }); } /** @@ -262,10 +262,10 @@ export function chunk$bytes_Buf_bytes_Bytes(self: Take): rs.ByteSl */ export function advance$bytes_Buf_bytes_Bytes(self: Take, cnt: rs.usize): void { if (!(cnt <= self.limit)) { - rs.panic("assertion failed: cnt <= self.limit", { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/take.rs", line: 146, col: 9 }); + rs.panic("assertion failed: cnt <= self.limit", { file: "bytes/source/buf/take.rs", line: 146, col: 9 }); } else { rs.bytesAdvance(rs.place(() => self.inner, (value) => self.inner = value), cnt); - self.limit = rs.usizeSub(self.limit, cnt, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/take.rs", line: 148, col: 9 }); + self.limit = rs.usizeSub(self.limit, cnt, { file: "bytes/source/buf/take.rs", line: 148, col: 9 }); } } @@ -292,10 +292,10 @@ export function advance$bytes_Buf_bytes_Bytes(self: Take, cnt: rs. */ export function copyToBytes$bytes_Buf_bytes_Bytes(self: Take, len: rs.usize): rs.ByteSlice { if (!(len <= remaining$bytes_Buf_bytes_Bytes_mut(self))) { - rs.panicFmt(["`len` greater than remaining"], { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/take.rs", line: 152, col: 9 }); + rs.panicFmt(["`len` greater than remaining"], { file: "bytes/source/buf/take.rs", line: 152, col: 9 }); } else { const r: rs.ByteSlice = rs.bytesSplitTo(rs.place(() => self.inner, (value) => self.inner = value), len); - self.limit = rs.usizeSub(self.limit, len, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/take.rs", line: 155, col: 9 }); + self.limit = rs.usizeSub(self.limit, len, { file: "bytes/source/buf/take.rs", line: 155, col: 9 }); return r; } } diff --git a/ts/fixtures/lang/panics/hook/expected/bytes/buf/uninit_slice.UninitSlice.ts b/ts/fixtures/lang/panics/hook/expected/bytes/buf/uninit_slice.UninitSlice.ts index ef9af030b..ea878829b 100644 --- a/ts/fixtures/lang/panics/hook/expected/bytes/buf/uninit_slice.UninitSlice.ts +++ b/ts/fixtures/lang/panics/hook/expected/bytes/buf/uninit_slice.UninitSlice.ts @@ -64,9 +64,9 @@ export function uninit(slice: rs.ByteSlice): rs.ByteSlice { */ export function writeByte(self: rs.ByteSlice, index: rs.usize, byte: rs.u8): void { if (!(index < len(self))) { - rs.panic("assertion failed: index < self.len()", { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/uninit_slice.rs", line: 108, col: 9 }); + rs.panic("assertion failed: index < self.len()", { file: "bytes/source/buf/uninit_slice.rs", line: 108, col: 9 }); } else { - asMutPtr(indexMut$ops_IndexMut_ops_RangeFrom_usize(self, new rs.RangeFrom(index, rs.usizeStep), { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/uninit_slice.rs", line: 110, col: 22 })).v = byte; + asMutPtr(indexMut$ops_IndexMut_ops_RangeFrom_usize(self, new rs.RangeFrom(index, rs.usizeStep), { file: "bytes/source/buf/uninit_slice.rs", line: 110, col: 22 })).v = byte; } } @@ -96,7 +96,7 @@ export function copyFromSlice(self: rs.ByteSlice, src: rs.ByteSlice): void { const _5: rs.usize = len(self); const _8: rs.usize = src.length; if (!(_5 === _8)) { - rs.assertFailed("==", (f: rs.Formatter) => rs.usizeDebug(_5, f), (f: rs.Formatter) => rs.usizeDebug(_8, f), undefined as rs.Arguments | undefined, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/uninit_slice.rs", line: 137, col: 9 }); + rs.assertFailed("==", (f: rs.Formatter) => rs.usizeDebug(_5, f), (f: rs.Formatter) => rs.usizeDebug(_8, f), undefined as rs.Arguments | undefined, { file: "bytes/source/buf/uninit_slice.rs", line: 137, col: 9 }); } else { rs.ptrCopy(rs.byteSliceAsPtr(src), asMutPtr(self), len(self)); } diff --git a/ts/fixtures/lang/panics/hook/expected/hooked.ts b/ts/fixtures/lang/panics/hook/expected/hooked.ts index ef810dc01..881cf3e9f 100644 --- a/ts/fixtures/lang/panics/hook/expected/hooked.ts +++ b/ts/fixtures/lang/panics/hook/expected/hooked.ts @@ -87,7 +87,7 @@ export function hook(): void { captured(info); }, (): void => { rs.drop(captured); - }), { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 1246, col: 9 } }); + }), { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "bytes/source/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "bytes/source/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "bytes/source/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "bytes/source/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "bytes/source/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "bytes/source/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "bytes/source/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "bytes/source/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "bytes/source/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "bytes/source/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "bytes/source/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "bytes/source/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "bytes/source/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "bytes/source/bytes_mut.rs", line: 1246, col: 9 } }); } export function tracked(n: rs.u8, caller: rs.Location): rs.u8 { @@ -220,7 +220,7 @@ export function aborted(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void } }, (): void => { rs.drop(captured2); - }), { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 1246, col: 9 } }); + }), { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "bytes/source/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "bytes/source/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "bytes/source/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "bytes/source/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "bytes/source/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "bytes/source/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "bytes/source/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "bytes/source/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "bytes/source/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "bytes/source/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "bytes/source/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "bytes/source/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "bytes/source/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "bytes/source/bytes_mut.rs", line: 1246, col: 9 } }); rs.byteVecPush(out, n); const _13: rs.u8 = rs.u8Rem(kind, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 174, col: 11 }); if (_13 === 3 || _13 === 4) { @@ -661,7 +661,7 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { rs.stringPushStr(note, line.v); }, { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/thread/local.rs", line: 721, col: 38 }); rs.panicFmt(["unread"], { file: "fixtures/lang/panics/src/hooked.rs", line: 466, col: 13 }); - }, { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/bytes_mut.rs", line: 1246, col: 9 } }); + }, { capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/raw_vec/mod.rs", line: 29, col: 5 }, trusted_capacity: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/spec_from_iter_nested.rs", line: 57, col: 18 }, swap_remove: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2178, col: 13 }, vec_set_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 2138, col: 9 }, into_flattened: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/mod.rs", line: 3667, col: 36 }, rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3902, col: 9 }, rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/mod.rs", line: 3948, col: 9 }, ord_violation: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/slice/sort/shared/smallsort.rs", line: 854, col: 5 }, ord_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cmp.rs", line: 1166, col: 9 }, f32_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f32.rs", line: 1665, col: 9 }, f64_clamp: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/num/f64.rs", line: 1643, col: 9 }, encode_utf8: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2507, col: 9 }, encode_utf16: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/char/methods.rs", line: 2601, col: 13 }, format: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/fmt.rs", line: 657, col: 14 }, to_string: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/string.rs", line: 2997, col: 14 }, debug_struct_fields: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/fmt/mod.rs", line: 2572, col: 9 }, exact_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/exact_size.rs", line: 122, col: 9 }, join_len: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/str.rs", line: 177, col: 10 }, int_sum: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/traits/accum.rs", line: 206, col: 1 }, int_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 554, col: 1 }, char_forward: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/range.rs", line: 119, col: 45 }, hash_capacity: { file: "/cargo/registry/25cdd57fae9f0462/hashbrown-0.17.1/src/raw.rs", line: 36, col: 40 }, btree_range_equal_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 110, col: 21 }, btree_range_equal_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 112, col: 21 }, btree_range_order_BTreeSet: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 119, col: 21 }, btree_range_order_BTreeMap: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/btree/search.rs", line: 121, col: 21 }, deque_insert: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2612, col: 9 }, deque_swap_i: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1062, col: 9 }, deque_swap_j: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 1063, col: 9 }, deque_rotate_left: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3198, col: 9 }, deque_rotate_right: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 3243, col: 9 }, deque_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/vec_deque/mod.rs", line: 2724, col: 9 }, list_split_off: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/collections/linked_list.rs", line: 1015, col: 9 }, mutex_lock: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sys/sync/mutex/no_threads.rs", line: 28, col: 9 }, once_force: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/std/src/sync/once.rs", line: 227, col: 20 }, reentrant_init: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/once.rs", line: 325, col: 66 }, lazy_poisoned: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell/lazy.rs", line: 386, col: 5 }, ready_poll: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 23, col: 35 }, ready_into_inner: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/future/ready.rs", line: 46, col: 16 }, duration_new: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 281, col: 18 }, duration_from_mins: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 540, col: 13 }, duration_from_hours: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 510, col: 13 }, duration_add: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1345, col: 31 }, duration_sub: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1365, col: 31 }, duration_mul: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/time.rs", line: 1385, col: 31 }, zip_next_back: { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/iter/adapters/zip.rs", line: 213, col: 5 }, bytes_advance: { file: "bytes/source/lib.rs", line: 207, col: 5 }, bytes_does_not_fit: { file: "bytes/source/lib.rs", line: 215, col: 5 }, bytes_slice: { file: "bytes/source/bytes.rs", line: 374, col: 28 }, bytes_slice_ref_start: { file: "bytes/source/bytes.rs", line: 426, col: 9 }, bytes_slice_ref_end: { file: "bytes/source/bytes.rs", line: 432, col: 9 }, bytes_split_off: { file: "bytes/source/bytes.rs", line: 481, col: 9 }, bytes_split_to: { file: "bytes/source/bytes.rs", line: 533, col: 9 }, bytes_buf_advance: { file: "bytes/source/bytes.rs", line: 694, col: 9 }, bytes_mut_split_off: { file: "bytes/source/bytes_mut.rs", line: 329, col: 9 }, bytes_mut_split_to: { file: "bytes/source/bytes_mut.rs", line: 408, col: 9 }, bytes_mut_set_len: { file: "bytes/source/bytes_mut.rs", line: 545, col: 9 }, bytes_mut_overflow: { file: "bytes/source/bytes_mut.rs", line: 700, col: 21 }, bytes_mut_overflow_offset: { file: "bytes/source/bytes_mut.rs", line: 720, col: 29 }, bytes_mut_buf_advance: { file: "bytes/source/bytes_mut.rs", line: 1246, col: 9 } }); const subset: rs.ByteSlice = rs.bytesSlice(whole, 0, 1); if (k === 0) { const _22: rs.ByteSlice = rs.bytesSlice(whole, rs.usizeAdd(1, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 470, col: 34 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 470, col: 30 })); diff --git a/ts/fixtures/lang/pointers/expected/pointers.ts b/ts/fixtures/lang/pointers/expected/pointers.ts index db0886202..efc4d3268 100644 --- a/ts/fixtures/lang/pointers/expected/pointers.ts +++ b/ts/fixtures/lang/pointers/expected/pointers.ts @@ -2986,6 +2986,37 @@ export function lent(n: rs.u8): rs.ByteVec { const nested: rs.u32[][] = [[w, 1], [2, 3]]; const _296: rs.u8 = rs.sliceSame(rs.optionUnwrap(rs.arraySliceLast(rs.arraySliceFrom(nested, rs.sliceFrom))), rs.optionUnwrap(rs.iterNth(rs.arraySliceIter(rs.arraySliceFrom(nested, rs.sliceFrom)), 1))) ? 1 : 0; rs.byteVecPush(o, _296); + const _312: [rs.ArraySlice>, rs.Slice] = rs.sliceAsChunks(rs.sliceFrom(Array.from({ length: 6 }, (): rs.u32 => { + return w; + })), 2); + const last: rs.Slice = rs.optionUnwrap(rs.arraySliceLast(_312[0])); + const _321: (a0: rs.Slice) => boolean = (run: rs.Slice): boolean => { + return !rs.sliceSame(run, last); + }; + const _319: rs.u8 = rs.slicePartitionPoint(rs.arraySliceAsSlice(_312[0]), (held2) => _321(rs.sliceFrom(held2))) & 0xff; + rs.byteVecPush(o, _319); + const bytes: Uint8Array = rs.bytes(6).fill(n); + const _326: rs.ByteSlice = rs.byteSliceFrom(bytes); + const _333: rs.ByteSlice = rs.byteSliceFrom(bytes); + const _324: [rs.ArraySlice, rs.ByteSlice] = rs.sliceAsChunks(rs.byteSliceRange(_326, 1), 2); + const _332: (a0: rs.ByteSlice) => boolean = (run2: rs.ByteSlice): boolean => { + return !rs.byteSliceSame(run2, rs.optionUnwrap(rs.byteSliceGetRange(rs.byteSliceRange(_333, 3), 0, 2))); + }; + const _330: rs.u8 = rs.slicePartitionPoint(rs.arraySliceAsSlice(_324[0]), (held3) => _332(rs.byteSliceFrom(held3))) & 0xff; + rs.byteVecPush(o, _330); + const _335: rs.u32[] = Array.from({ length: 2 }, (): rs.u32 => { + return w; + }); + const pairs2: rs.u32[][] = Array.from({ length: 4 }, (): rs.u32[] => { + return copy$array_u32(_335); + }); + const _345: rs.ArraySlice> = rs.arraySliceFrom(pairs2, rs.sliceFrom); + const _337: [rs.ArraySlice>>, rs.ArraySlice>] = rs.sliceAsChunks(rs.arraySliceFrom(pairs2, rs.sliceFrom), 2); + const _344: (a0: rs.ArraySlice>) => boolean = (run3: rs.ArraySlice>): boolean => { + return !rs.arraySliceSame(run3, rs.optionUnwrap(rs.arraySliceLastChunk(_345, 2))); + }; + const _342: rs.u8 = rs.slicePartitionPoint(rs.arraySliceAsSlice(_337[0]), (held4) => _344(rs.arraySliceOf(rs.sliceFrom)(held4))) & 0xff; + rs.byteVecPush(o, _342); un[Symbol.dispose](); held[Symbol.dispose](); rs.refRelease(_240); diff --git a/ts/fixtures/lang/pointers/src/pointers.rs b/ts/fixtures/lang/pointers/src/pointers.rs index a5b9b71a7..152e4fa76 100644 --- a/ts/fixtures/lang/pointers/src/pointers.rs +++ b/ts/fixtures/lang/pointers/src/pointers.rs @@ -2407,6 +2407,17 @@ fn lent(n: u8) -> Vec { o.push(u8::from(ptr::eq(un.first_chunk::<2>().unwrap(), &*held))); let nested = [[w, 1], [2, 3]]; o.push(u8::from(ptr::eq(nested.last().unwrap(), nested.iter().nth(1).unwrap()))); + // Runs of equal elements a callback of std's tells apart only by where each is. + let same = [w; 6]; + let (runs, _) = same.as_chunks::<2>(); + let last = runs.last().unwrap(); + o.push(runs.partition_point(|run| !ptr::eq(run, last)) as u8); + let bytes = [n; 6]; + let (runs, _) = bytes[1..].as_chunks::<2>(); + o.push(runs.partition_point(|run| !ptr::eq(run, bytes[3..].first_chunk::<2>().unwrap())) as u8); + let pairs = [[w; 2]; 4]; + let (runs, _) = pairs.as_chunks::<2>(); + o.push(runs.partition_point(|run| !ptr::eq(run, pairs.last_chunk::<2>().unwrap())) as u8); o } diff --git a/ts/fixtures/reject/census.txt b/ts/fixtures/reject/census.txt index f9a4ec104..87ed5d41e 100644 --- a/ts/fixtures/reject/census.txt +++ b/ts/fixtures/reject/census.txt @@ -1,4 +1,7 @@ fixtures/reject/src/alloc.rs:addressed+1:17: a pointer's address, which JS has no counterpart of +fixtures/reject/src/alloc.rs:alloc_leaked+4:11: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as +fixtures/reject/src/alloc.rs:alloc_leaked+6:8: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as +fixtures/reject/src/alloc.rs:alloc_leaked+8:3: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as fixtures/reject/src/alloc.rs:alloc_retyped+4:7: memory from `alloc` cast to pointers to `u32` and to `i32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:alloc_retyped+5:11: memory from `alloc` cast to pointers to `i32` and to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:alloc_retyped+7:17: memory from `alloc` cast to pointers to `i32` and to `u32`, which reads the bytes of one type as another @@ -12,6 +15,7 @@ fixtures/reject/src/alloc.rs:beside_reference+2:11: a read or write reaching pas fixtures/reject/src/alloc.rs:beside_reference+2:32: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:beside_reference+2:44: a slice of a length the body doesn't fix, from a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:bytes_as_values+3:3: a byte of memory from `alloc`, which JS keeps as the values a cast of its pointer types it as +fixtures/reject/src/alloc.rs:bytes_as_values+3:19: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as fixtures/reject/src/alloc.rs:bytes_as_values+4:15: a cast from a pointer to `u8` to one to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:bytes_as_values+5:16: a cast from a pointer to `u8` to one to `pointers::Halves`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:bytes_as_values+7:15: a cast from a pointer to `u32` to one to `u8`, which reads the bytes of one type as another @@ -48,6 +52,7 @@ fixtures/reject/src/alloc.rs:past_reference+1:30: a pointer reaching past a valu fixtures/reject/src/alloc.rs:peeked_moved+3:26: a read moving out a `std::iter::Peekable>>`, a library object whose inline state only its runtime class knows, which no copy splits from the original as Rust's read does fixtures/reject/src/alloc.rs:pinned_lent+1:32: `UnsafeCell::get_mut` of `std::pin::Pin>`, an object a whole write through the reference changes in place, so a value read out before would be a copy at another address fixtures/reject/src/alloc.rs:pinned_lent+2:43: `UnsafeCell::as_mut_unchecked` of `std::pin::Pin>`, an object a whole write through the reference changes in place, so a value read out before would be a copy at another address +fixtures/reject/src/alloc.rs:realloc_retyped+2:11: `realloc` of memory cast from a pointer to `u32` whose result is cast to one to `i32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:recast_reference+4:11: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:recast_reference+4:48: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:recast_reference+4:76: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust @@ -70,6 +75,8 @@ fixtures/reject/src/alloc.rs:wrapped_cells+12:3: a whole write of `std::mem::Man fixtures/reject/src/alloc.rs:zeroed+1:12: a cast from a pointer to `u8` to one to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:zeroed+1:13: unsupported call to `std::alloc::alloc_zeroed` fixtures/reject/src/buffers.rs:blank_bytes+1:2: `Buf::copy_to_bytes` of `buffers::Blank`, a value JS copies, which is not supported +fixtures/reject/src/buffers.rs:sliced_elsewhere+4:4: `Bytes::slice_ref` of bytes the body doesn't show it borrowed from that `Bytes`'s storage, through `Deref`, `as_ref`, or a slice of one, which JS may keep apart where Rust shares them +fixtures/reject/src/buffers.rs:sliced_elsewhere+4:47: `Bytes::slice_ref` of bytes the body doesn't show it borrowed from that `Bytes`'s storage, through `Deref`, `as_ref`, or a slice of one, which JS may keep apart where Rust shares them fixtures/reject/src/clones.rs:given_slots+6:2: a raw pointer to `(u8, u8)` in `([clones::Touched; 2], (u8, u8))`, which the crate may put another object in place of fixtures/reject/src/clones.rs:greatest_slot+6:13: a raw pointer to `(u8, u8)` in `([clones::Greatest; 2], (u8, u8))`, which the crate may put another object in place of fixtures/reject/src/clones.rs:kept_slots+5:2: a raw pointer to `(u8, u8)` in `([clones::Cloned; 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 ff32bc79b..e2420b562 100644 --- a/ts/fixtures/reject/expected.txt +++ b/ts/fixtures/reject/expected.txt @@ -3,6 +3,9 @@ no item `clones::slice_of_object` in the crate no item `lopsided` in the crate no item `missing` in the crate fixtures/reject/src/alloc.rs:addressed+1:17: a pointer's address, which JS has no counterpart of +fixtures/reject/src/alloc.rs:alloc_leaked+4:11: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as +fixtures/reject/src/alloc.rs:alloc_leaked+6:8: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as +fixtures/reject/src/alloc.rs:alloc_leaked+8:3: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as fixtures/reject/src/alloc.rs:alloc_retyped+4:7: memory from `alloc` cast to pointers to `u32` and to `i32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:alloc_retyped+5:11: memory from `alloc` cast to pointers to `i32` and to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:alloc_retyped+7:17: memory from `alloc` cast to pointers to `i32` and to `u32`, which reads the bytes of one type as another @@ -16,6 +19,7 @@ fixtures/reject/src/alloc.rs:beside_reference+2:11: a read or write reaching pas fixtures/reject/src/alloc.rs:beside_reference+2:32: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:beside_reference+2:44: a slice of a length the body doesn't fix, from a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:bytes_as_values+3:3: a byte of memory from `alloc`, which JS keeps as the values a cast of its pointer types it as +fixtures/reject/src/alloc.rs:bytes_as_values+3:19: `alloc` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as fixtures/reject/src/alloc.rs:bytes_as_values+4:15: a cast from a pointer to `u8` to one to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:bytes_as_values+5:16: a cast from a pointer to `u8` to one to `pointers::Halves`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:bytes_as_values+7:15: a cast from a pointer to `u32` to one to `u8`, which reads the bytes of one type as another @@ -52,6 +56,7 @@ fixtures/reject/src/alloc.rs:past_reference+1:30: a pointer reaching past a valu fixtures/reject/src/alloc.rs:peeked_moved+3:26: a read moving out a `std::iter::Peekable>>`, a library object whose inline state only its runtime class knows, which no copy splits from the original as Rust's read does fixtures/reject/src/alloc.rs:pinned_lent+1:32: `UnsafeCell::get_mut` of `std::pin::Pin>`, an object a whole write through the reference changes in place, so a value read out before would be a copy at another address fixtures/reject/src/alloc.rs:pinned_lent+2:43: `UnsafeCell::as_mut_unchecked` of `std::pin::Pin>`, an object a whole write through the reference changes in place, so a value read out before would be a copy at another address +fixtures/reject/src/alloc.rs:realloc_retyped+2:11: `realloc` of memory cast from a pointer to `u32` whose result is cast to one to `i32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:recast_reference+4:11: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:recast_reference+4:48: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust fixtures/reject/src/alloc.rs:recast_reference+4:76: a read or write reaching past a value in no array, which JS keeps apart from what holds it in Rust @@ -74,6 +79,8 @@ fixtures/reject/src/alloc.rs:wrapped_cells+12:3: a whole write of `std::mem::Man fixtures/reject/src/alloc.rs:zeroed+1:12: a cast from a pointer to `u8` to one to `u32`, which reads the bytes of one type as another fixtures/reject/src/alloc.rs:zeroed+1:13: unsupported call to `std::alloc::alloc_zeroed` fixtures/reject/src/buffers.rs:blank_bytes+1:2: `Buf::copy_to_bytes` of `buffers::Blank`, a value JS copies, which is not supported +fixtures/reject/src/buffers.rs:sliced_elsewhere+4:4: `Bytes::slice_ref` of bytes the body doesn't show it borrowed from that `Bytes`'s storage, through `Deref`, `as_ref`, or a slice of one, which JS may keep apart where Rust shares them +fixtures/reject/src/buffers.rs:sliced_elsewhere+4:47: `Bytes::slice_ref` of bytes the body doesn't show it borrowed from that `Bytes`'s storage, through `Deref`, `as_ref`, or a slice of one, which JS may keep apart where Rust shares them fixtures/reject/src/clones.rs:greatest_slot+6:13: a raw pointer to `(u8, u8)` in `([clones::Greatest; 2], (u8, u8))`, which the crate may put another object in place of fixtures/reject/src/clones.rs:stashed_slots+5:19: a raw pointer to `(u8, u8)` in `([u8; 2], (u8, u8))`, which the crate may put another object in place of fixtures/reject/src/clones.rs:tagged_slots!+2:23: a raw pointer to `(u8, u8)` in `([clones::Cloned; 2], (u8, u8))`, which the crate may put another object in place of diff --git a/ts/fixtures/reject/src/alloc.rs b/ts/fixtures/reject/src/alloc.rs index 0daaa6a71..521b682a3 100644 --- a/ts/fixtures/reject/src/alloc.rs +++ b/ts/fixtures/reject/src/alloc.rs @@ -339,3 +339,31 @@ pub fn alloc_retyped() -> i32 { pub fn zeroed() -> u32 { unsafe { *(std::alloc::alloc_zeroed(std::alloc::Layout::new::()) as *mut u32) } } + +/// Memory from `alloc` whose byte pointer leaves the body untyped: returned, kept in a +/// field, or given to a function of the crate's own, which JS can't read as bytes. +pub fn alloc_leaked(n: u8) -> *mut u8 { + let layout = std::alloc::Layout::new::(); + unsafe { + let held = Held { + bytes: std::alloc::alloc(layout), + }; + fill(std::alloc::alloc(layout), n); + std::alloc::dealloc(held.bytes, layout); + std::alloc::alloc(layout) + } +} + +pub struct Held { + bytes: *mut u8, +} + +unsafe fn fill(p: *mut u8, n: u8) { + unsafe { *p = n }; +} + +/// `realloc` of memory a pointer to `u32`s points at, whose result is read as `i32`s. +pub fn realloc_retyped(words: *mut u32) -> i32 { + let layout = std::alloc::Layout::new::(); + unsafe { std::alloc::realloc(words as *mut u8, layout, 8).cast::().read() } +} diff --git a/ts/fixtures/reject/src/buffers.rs b/ts/fixtures/reject/src/buffers.rs index 77360c755..fff954350 100644 --- a/ts/fixtures/reject/src/buffers.rs +++ b/ts/fixtures/reject/src/buffers.rs @@ -23,3 +23,12 @@ impl bytes::Buf for Blank { pub fn blank_bytes(len: usize) -> usize { bytes::Buf::copy_to_bytes(&mut Blank::Empty, len).len() } + +/// `slice_ref` of bytes the body doesn't show of that `Bytes`'s storage: a `&'static str`'s, +/// which Rust shares and JS encodes anew, and of another `Bytes` of them. +pub fn sliced_elsewhere(n: usize) -> usize { + let text = "shared"; + let a = bytes::Bytes::from_static(text.as_bytes()); + let b = bytes::Bytes::from_static(text.as_bytes()); + a.slice_ref(&text.as_bytes()[..n]).len() + a.slice_ref(&b[..n]).len() +} diff --git a/ts/fixtures/reject/ts.toml b/ts/fixtures/reject/ts.toml index ec178a04e..3bd1cf244 100644 --- a/ts/fixtures/reject/ts.toml +++ b/ts/fixtures/reject/ts.toml @@ -1,6 +1,7 @@ package = "reject-fixture" roots = [ "alloc::addressed", + "alloc::alloc_leaked", "alloc::alloc_retyped", "alloc::allocated", "alloc::arrays_boxed", @@ -19,6 +20,7 @@ roots = [ "alloc::past_reference", "alloc::peeked_moved", "alloc::pinned_lent", + "alloc::realloc_retyped", "alloc::recast_reference", "alloc::reinterpreted", "alloc::unfixed_reference", @@ -29,6 +31,7 @@ roots = [ "alloc::zeroed", "bound_ranges", "buffers::blank_bytes", + "buffers::sliced_elsewhere", "clones::cloned_slots", "clones::dropped_slots", "clones::ranked_slots", diff --git a/ts/fixtures/stock/expected/buf.Fixed.ts b/ts/fixtures/stock/expected/buf.Fixed.ts index 5ecbd401f..03460e912 100644 --- a/ts/fixtures/stock/expected/buf.Fixed.ts +++ b/ts/fixtures/stock/expected/buf.Fixed.ts @@ -177,7 +177,7 @@ export function putSlice$bytes_BufMut(self: Fixed, src: rs.ByteSlice): void { while (!(src.length === 0)) { const dst: rs.ByteSlice = chunkMut$bytes_BufMut(self); const cnt: rs.usize = rs.min(src.length, UninitSlice.len(dst)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(dst, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 258, col: 16 }), rs.byteSliceRange(src, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(dst, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 258, col: 16 }), rs.byteSliceRange(src, 0, cnt)); src = rs.byteSliceRange(src, cnt); advanceMut$bytes_BufMut(self, cnt); } diff --git a/ts/fixtures/stock/expected/buf.Spare.ts b/ts/fixtures/stock/expected/buf.Spare.ts index 710f56295..609d64975 100644 --- a/ts/fixtures/stock/expected/buf.Spare.ts +++ b/ts/fixtures/stock/expected/buf.Spare.ts @@ -186,7 +186,7 @@ export function putSlice$bytes_BufMut(self: Spare, src: rs.ByteSlice): void { while (!(src.length === 0)) { const dst: rs.ByteSlice = chunkMut$bytes_BufMut(self); const cnt: rs.usize = rs.min(src.length, UninitSlice.len(dst)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(dst, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 258, col: 16 }), rs.byteSliceRange(src, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(dst, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 258, col: 16 }), rs.byteSliceRange(src, 0, cnt)); src = rs.byteSliceRange(src, cnt); advanceMut$bytes_BufMut(self, cnt); } diff --git a/ts/fixtures/stock/expected/buf.ts b/ts/fixtures/stock/expected/buf.ts index 0b4efb470..89f29579c 100644 --- a/ts/fixtures/stock/expected/buf.ts +++ b/ts/fixtures/stock/expected/buf.ts @@ -4719,11 +4719,13 @@ export function edits(dataData: Uint8Array, dataStart: number, dataLen: number, part = rs.bytesNew(); } else if (_17 === 4) { const sub: rs.ByteSlice = rs.byteSliceRange(bytes, rs.min(a, dataLen - 2)); - part = rs.bytesSliceRef(bytes, sub); + const _32: rs.ByteSlice = rs.bytesClone(bytes); + part = rs.bytesSliceRef(_32, sub); + rs.bytesDrop(_32); } else if (_17 === 5) { rs.bytesAdvance(rs.place(() => bytes, (value3) => bytes = value3), a); - const _35: rs.usize = rs.usizeDiv(a, 2); - part = rs.bytesSplitTo(rs.place(() => bytes, (value4) => bytes = value4), _35); + const _37: rs.usize = rs.usizeDiv(a, 2); + part = rs.bytesSplitTo(rs.place(() => bytes, (value4) => bytes = value4), _37); } else if (_17 === 6) { let clone: rs.ByteSlice = rs.bytesClone(bytes); rs.bytesTruncate(rs.place(() => clone, (value2) => clone = value2), a); @@ -4733,15 +4735,15 @@ export function edits(dataData: Uint8Array, dataStart: number, dataLen: number, rs.bytesTruncate(rs.place(() => bytes, (value) => bytes = value), a); part = clone2; } else { - const _46: rs.Place = { v: rs.bytesClone(bytes) }; - rs.bytesDrop(rs.bytesStatic(_46.v)); - rs.bytesDrop(rs.bytesStatic(rs.byteSliceRange(_46.v, 0))); - part = rs.bytesStatic(_46.v); + const _48: rs.Place = { v: rs.bytesClone(bytes) }; + rs.bytesDrop(rs.bytesStatic(_48.v)); + rs.bytesDrop(rs.bytesStatic(rs.byteSliceRange(_48.v, 0))); + part = rs.bytesStatic(_48.v); } - const _65: boolean = rs.bytesIsUnique(part); - const _68: boolean = rs.bytesIsUnique(bytes); - const _70: rs.ByteSlice = part; - const args3 = [(f: rs.Formatter) => rs.bytesDebug(_70, f), (f: rs.Formatter) => rs.bytesDebug(bytes, f), (f: rs.Formatter) => rs.fmtBool(_65, f), (f: rs.Formatter) => rs.fmtBool(_68, f)]; + const _67: boolean = rs.bytesIsUnique(part); + const _70: boolean = rs.bytesIsUnique(bytes); + const _72: rs.ByteSlice = part; + const args3 = [(f: rs.Formatter) => rs.bytesDebug(_72, f), (f: rs.Formatter) => rs.bytesDebug(bytes, f), (f: rs.Formatter) => rs.fmtBool(_67, f), (f: rs.Formatter) => rs.fmtBool(_70, f)]; rs.byteVecExtendFromSlice(out, rs.stringAsBytes(rs.fmtFormat([args3[0], " ", args3[1], " ", args3[2], " ", args3[3]]).v)); rs.bytesDrop(part); rs.bytesDrop(bytes); diff --git a/ts/fixtures/stock/expected/bytes/buf/buf_mut.ts b/ts/fixtures/stock/expected/bytes/buf/buf_mut.ts index fefbb1ce1..4af45e578 100644 --- a/ts/fixtures/stock/expected/bytes/buf/buf_mut.ts +++ b/ts/fixtures/stock/expected/bytes/buf/buf_mut.ts @@ -132,7 +132,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_buf_Pieces(sel const s: rs.ByteSlice = Pieces.chunk$bytes_Buf(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); Pieces.advance$bytes_Buf(src, cnt); } @@ -169,7 +169,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_buf_Provided(s const s: rs.ByteSlice = Provided.chunk$bytes_Buf(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); Provided.advance$bytes_Buf(src, cnt); } @@ -206,7 +206,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_bytes_Bytes(se const s: rs.ByteSlice = src; const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.bytesAdvance(rs.place(() => src, (value) => src = value), cnt); } @@ -244,7 +244,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_bytes_BytesMut const s: rs.ByteSlice = rs.bytesMutView(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.bytesMutAdvance(src, cnt); } @@ -282,7 +282,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_bytes_buf_Chai const s: rs.ByteSlice = Chain.chunk$bytes_Buf_bytes_Bytes_ref_slice_u8(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); Chain.advance$bytes_Buf_bytes_Bytes_ref_slice_u8(src, cnt); } @@ -320,7 +320,7 @@ export function put$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8_ref_slice_u8(s const s: rs.ByteSlice = src; const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.byteSliceAdvance(rs.place(() => src, (value) => src = value), cnt); } @@ -357,7 +357,7 @@ export function put$bytes_BufMut_mut_mut_slice_u8_buf_Pieces(self: rs.Place src, (value) => src = value), cnt); } @@ -469,7 +469,7 @@ export function put$bytes_BufMut_mut_mut_slice_u8_bytes_BytesMut(self: rs.Place< const s: rs.ByteSlice = rs.bytesMutView(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_u8(self, cnt); rs.bytesMutAdvance(src, cnt); } @@ -507,7 +507,7 @@ export function put$bytes_BufMut_mut_mut_slice_u8_bytes_buf_Chain_bytes_Bytes_re const s: rs.ByteSlice = Chain.chunk$bytes_Buf_bytes_Bytes_ref_slice_u8(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_mut_slice_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_mut_slice_u8(self, cnt); Chain.advance$bytes_Buf_bytes_Bytes_ref_slice_u8(src, cnt); } @@ -545,7 +545,7 @@ export function put$bytes_BufMut_mut_mut_slice_u8_ref_slice_u8(self: rs.Place src, (value) => src = value), cnt); } @@ -582,7 +582,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_buf_Pieces(self: r const s: rs.ByteSlice = Pieces.chunk$bytes_Buf(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); Pieces.advance$bytes_Buf(src, cnt); } @@ -619,7 +619,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_buf_Provided(self: const s: rs.ByteSlice = Provided.chunk$bytes_Buf(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); Provided.advance$bytes_Buf(src, cnt); } @@ -656,7 +656,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_bytes_Bytes(self: const s: rs.ByteSlice = src; const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.bytesAdvance(rs.place(() => src, (value) => src = value), cnt); } @@ -694,7 +694,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_bytes_BytesMut(sel const s: rs.ByteSlice = rs.bytesMutView(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.bytesMutAdvance(src, cnt); } @@ -732,7 +732,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_bytes_buf_Chain_by const s: rs.ByteSlice = Chain.chunk$bytes_Buf_bytes_Bytes_ref_slice_u8(src); const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); Chain.advance$bytes_Buf_bytes_Bytes_ref_slice_u8(src, cnt); } @@ -770,7 +770,7 @@ export function put$bytes_BufMut_mut_slice_mem_MaybeUninit_u8_ref_slice_u8(self: const s: rs.ByteSlice = src; const d: rs.ByteSlice = chunkMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self); const cnt: rs.usize = rs.min(s.length, UninitSlice.len(d)); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(d, { end: cnt }, { file: "bytes/source/buf/buf_mut.rs", line: 218, col: 14 }), rs.byteSliceRange(s, 0, cnt)); advanceMut$bytes_BufMut_mut_slice_mem_MaybeUninit_u8(self, cnt); rs.byteSliceAdvance(rs.place(() => src, (value) => src = value), cnt); } @@ -807,7 +807,7 @@ export function put$bytes_BufMut_mut_slice_u8_buf_Pieces(self: rs.Place src, (value) => src = value), cnt); } @@ -919,7 +919,7 @@ export function put$bytes_BufMut_mut_slice_u8_bytes_BytesMut(self: rs.Place src, (value) => src = value), cnt); } diff --git a/ts/fixtures/stock/expected/bytes/buf/uninit_slice.UninitSlice.ts b/ts/fixtures/stock/expected/bytes/buf/uninit_slice.UninitSlice.ts index 161a41f91..851b8e73b 100644 --- a/ts/fixtures/stock/expected/bytes/buf/uninit_slice.UninitSlice.ts +++ b/ts/fixtures/stock/expected/bytes/buf/uninit_slice.UninitSlice.ts @@ -110,7 +110,7 @@ export function writeByte(self: rs.ByteSlice, index: rs.usize, byte: rs.u8): voi if (!(index < len(self))) { rs.panic("assertion failed: index < self.len()"); } else { - asMutPtr(indexMut$ops_IndexMut_ops_RangeFrom_usize(self, new rs.RangeFrom(index, rs.usizeStep), { file: "/cargo/registry/src/index.crates.io-1949cf8c6b5b557f/bytes-1.12.1/src/buf/uninit_slice.rs", line: 110, col: 22 })).v = byte; + asMutPtr(indexMut$ops_IndexMut_ops_RangeFrom_usize(self, new rs.RangeFrom(index, rs.usizeStep), { file: "bytes/source/buf/uninit_slice.rs", line: 110, col: 22 })).v = byte; } } diff --git a/ts/fixtures/stock/src/buf.rs b/ts/fixtures/stock/src/buf.rs index c1b165e24..f7aa49a8e 100644 --- a/ts/fixtures/stock/src/buf.rs +++ b/ts/fixtures/stock/src/buf.rs @@ -972,8 +972,9 @@ pub fn edits(data: &[u8], out: &mut Vec) { Bytes::new() } 4 => { - let sub = &bytes[a.min(rest.len())..]; - bytes.slice_ref(sub) + let all: &[u8] = bytes.as_ref(); + let sub = &all[a.min(rest.len())..]; + bytes.clone().slice_ref(sub) } 5 => { bytes.advance(a); diff --git a/ts/runtime/rs.ts b/ts/runtime/rs.ts index 4281a336f..87dc5430d 100644 --- a/ts/runtime/rs.ts +++ b/ts/runtime/rs.ts @@ -968,6 +968,8 @@ export function boxArrayFromRaw(s: Slice): T[] { */ export function sliceSame(a: Slice, b: Slice): boolean { if (!(a instanceof Slice && b instanceof Slice)) return a === b; + a = arrayRefWhere(a); + b = arrayRefWhere(b); return (roomItems(a.data) ?? a.data) === (roomItems(b.data) ?? b.data) && a.start === b.start; } @@ -1275,6 +1277,8 @@ export function arraySliceCopy(r: ArraySlice, copy?: Elem */ export function arraySliceSame(a: ArraySlice, b: ArraySlice): boolean { if (!(a instanceof ArraySlice && b instanceof ArraySlice)) return a === b; + a = arrayRefWhere(a); + b = arrayRefWhere(b); if (a.items !== undefined || b.items !== undefined) return a.items === b.items && a.start === b.start; return arrayRefSame(arrayRefPart(a.flat!, a.start * a.n, 0), arrayRefPart(b.flat!, b.start * b.n, 0)); } @@ -1289,10 +1293,11 @@ function arrayRefSame(a: ArrayRef, b: ArrayRef): boolean { /** * The arrays of `r` as a JS array of arrays, for what only reads them: the arrays themselves * where each array is one, so a callback's `ptr::eq` sees the array it was lent, or else copies - * of the arrays `as_chunks` split from one flat slice, which have no array of their own. + * of the arrays `as_chunks` split from one flat slice, which have no array of their own, as + * `arraySliceRuns` makes them. */ export function arraySliceItems(r: ArraySlice): LentArray[] { - if (r.items === undefined) return arraySliceCopy(r); + if (r.items === undefined) return arraySliceRuns(r); if (r.start === 0 && r.length === r.items.length) return r.items as LentArray[]; return r.items.slice(r.start, r.start + r.length) as LentArray[]; } @@ -1310,7 +1315,26 @@ export function arraySliceSplitLastChunk(r: ArraySlice, n /** The arrays of `r` as a slice of arrays, as `arraySliceItems` reads them: a slice of the arrays where each array is one. */ export function arraySliceAsSlice(r: ArraySlice): Slice> { if (r.items !== undefined) return new Slice(r.items as LentArray[], r.start, r.length); - return sliceFrom(arraySliceCopy(r)); + return sliceFrom(arraySliceRuns(r)); +} + +/** Each run `arraySliceRuns` copied, by the array the copy is. */ +const RUNS = /* @__PURE__ */ new WeakMap(); + +/** + * Copies of the arrays of `r`, runs `as_chunks` split from one flat slice, for what only + * reads them, each remembered as its run, so a pointer into a copy compares where the run is. + */ +function arraySliceRuns(r: ArraySlice): LentArray[] { + const out = arraySliceCopy(r); + for (let i = 0; i < out.length; i++) RUNS.set(out[i] as object, arraySliceAt(r, i)); + return out; +} + +/** Where `s`, the slice a pointer to a `[T; N]` is, points: into the run it copies if it is of a copy `arraySliceRuns` made. */ +function arrayRefWhere(s: S): S { + const run = RUNS.get((s instanceof ArraySlice ? s.items : s.data) ?? s) as S | undefined; + return run === undefined ? s : arrayRefPart(arrayRefWhere(run), s.start, s.length); } /** @@ -2203,6 +2227,8 @@ export function byteSliceSplitLastMut(s: ByteSlice): [Place, ByteSlice] */ export function byteSliceSame(a: ByteSlice, b: ByteSlice): boolean { if (!(a instanceof ByteSlice && b instanceof ByteSlice)) return a === b; + a = arrayRefWhere(a); + b = arrayRefWhere(b); return a.data.buffer === b.data.buffer && a.data.byteOffset + a.start === b.data.byteOffset + b.start; } diff --git a/ts/runtime/rs/alloc.ts b/ts/runtime/rs/alloc.ts index 297fd904f..63d04bf84 100644 --- a/ts/runtime/rs/alloc.ts +++ b/ts/runtime/rs/alloc.ts @@ -1,9 +1,10 @@ // `std::alloc`, for rust2-ts output: a `Layout`, and memory from `alloc` that a cast of its // pointer to one to `T` makes a JS array of `T`s, as many as fit. `rs.ts` re-exports all of it. // -// JS keeps values, not bytes, so the memory is untyped until that cast, and a read or -// write of its bytes fails. `realloc` keeps the values in a new array, and `dealloc` lets -// the array go; a pointer into it after either reads what Rust leaves undefined. +// JS keeps values, not bytes, so the memory is untyped until that cast, and translation +// refuses a read or write of its bytes, and a pointer to them leaving the body that made +// it. `realloc` keeps the values in a new array, and `dealloc` lets the array go; a pointer +// into it after either reads what Rust leaves undefined. import { Abort, Err, type Fmt, type FmtResult, type Formatter, fmtDebugStructFields, fmtPad, fmtWriteFmt, Ok, type Place, type Result, violated } from "../rs.ts"; import { AtIndex } from "./collections.ts"; @@ -128,7 +129,7 @@ export class Block implements Place { } function bytes(): never { - throw new Error("rust2-ts: a read or write of the bytes of memory from `alloc`, which JS keeps as values"); + throw new Error("rust2-ts: a read or write of the bytes of memory from `alloc`, which translation refuses"); } /** The block each array a cast of one's pointer made is in. */ @@ -145,6 +146,7 @@ export function alloc(layout: Layout): Block { * it holds already, of values of that type. */ export function allocAs(p: Place, elem: number, type: string): Place { + // Translation casts only a pointer the body shows `alloc` or `realloc` returned. if (!(p instanceof Block)) { throw new Error("rust2-ts: a pointer cast from one to bytes to one to values, which isn't memory from `alloc`"); } @@ -155,6 +157,7 @@ export function allocAs(p: Place, elem: number, type: string): Place< p.type = type; BLOCKS.set(p.array, p); } + // Translation refuses casting memory from one `alloc` to two types, and from `realloc` to another than its argument's. if (p.type !== type) throw new Error(`rust2-ts: memory from \`alloc\` holding \`${p.type}\`s, as \`${type}\`s`); return new AtIndex(p.array as T[], 0); } diff --git a/ts/runtime/rs/bytes.ts b/ts/runtime/rs/bytes.ts index e3930dc8e..807382608 100644 --- a/ts/runtime/rs/bytes.ts +++ b/ts/runtime/rs/bytes.ts @@ -250,14 +250,14 @@ export function bytesTruncate(p: Place, len: usize): void { /** * `Bytes::slice_ref`: the bytes of `b` that `subset` is, by where they are in memory. Its - * panic names no addresses, which JS has none of. Bytes of other storage throw instead: - * Rust may share what JS copied, such as a `&'static str`'s bytes, which `as_bytes` - * encodes anew each time. + * panic names no addresses, which JS has none of. Translation refuses a `subset` the body + * doesn't show borrowed from `b`'s storage, as Rust may share what JS copied, such as a `&'static + * str`'s bytes, which `as_bytes` encodes anew each time. */ export function bytesSliceRef(b: Bytes, subset: ByteSlice): Bytes { if (subset.length === 0) return bytesNew(); if (subset.data.buffer !== b.data.buffer) { - throw new Error("rust2-ts: `Bytes::slice_ref` of bytes from other storage, which Rust may share where JS copied"); + throw new Error("rust2-ts: `Bytes::slice_ref` of bytes from other storage, which translation refuses"); } const pos = subset.data.byteOffset + subset.start; const from = b.data.byteOffset + b.start; diff --git a/ts/src/census.rs b/ts/src/census.rs index 467cb25e3..cf2c003cb 100644 --- a/ts/src/census.rs +++ b/ts/src/census.rs @@ -147,10 +147,13 @@ const VERBATIM: &[&str] = &[ "Box::from_raw", "Buf::copy_to_bytes", "BufMut::put", + "Bytes", + "Bytes::slice_ref", "BytesMut", "Cell::swap", "Copy", "Debug", + "Deref", "Display", "Drop", "Extend", @@ -184,6 +187,7 @@ const VERBATIM: &[&str] = &[ "alloc", "array::from_ref", "as_chunks", + "as_ref", "async", "async fn", "become", @@ -194,6 +198,7 @@ const VERBATIM: &[&str] = &[ "clone_from", "collect", "copy_nonoverlapping", + "dealloc", "dyn Future", "experimental_generic_mono", "f64", @@ -213,6 +218,7 @@ const VERBATIM: &[&str] = &[ "next", "offset_from", "pub", + "realloc", "ref mut", "rs.None", "rs.OuterPending", diff --git a/ts/src/lower/array_slice.rs b/ts/src/lower/array_slice.rs index 205d33afd..f7af00439 100644 --- a/ts/src/lower/array_slice.rs +++ b/ts/src/lower/array_slice.rs @@ -3,9 +3,9 @@ //! `Vec<[T; N]>` holds them, or parts of one slice, as `as_chunks` splits it. The runtime's //! `arraySlice` functions map std's methods that lend arrays or parts. Any other method of a //! slice of arrays reads it as an `rs.Slice` of JS arrays: shared, of its arrays themselves, or -//! of copies of those `as_chunks` split from one slice, which have no array of their own; and -//! mutable, of copies that `rs.arraySliceBy` writes back once it returns, as Rust moves their -//! elements. +//! of copies of those `as_chunks` split from one slice, which have no array of their own and +//! compare where their runs are; and mutable, of copies that `rs.arraySliceBy` writes back +//! once it returns, as Rust moves their elements. use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/ts/src/lower/caller.rs b/ts/src/lower/caller.rs index 17c1c6338..5f82daee9 100644 --- a/ts/src/lower/caller.rs +++ b/ts/src/lower/caller.rs @@ -9,14 +9,16 @@ //! A program that reaches `panic::set_hook` passes where each panic is, which its hook //! reads: each statement's own, the caller's location to each std function that takes it, //! and the call of the macro that defines one, as an integer's methods. A panic in std's -//! own code is where the toolchain's source has it, and one in `bytes`' where the -//! program's `bytes` has it, named as the session names that file, which `rs.setHook` is -//! given. One in tokio's is where its compiled code has it, passed at the call. +//! own code is where the toolchain's source has it, which `rs.setHook` is given, with one in +//! `bytes`' where its compiled code has it. One in tokio's is where its compiled code has +//! it, passed at the call. use std::sync::OnceLock; use rustc_attr_ir::LangItem; +use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::{Instance, InstanceKind, TyCtxt}; use rustc_span::{RemapPathScopeComponents, SourceFile, Span}; @@ -480,62 +482,31 @@ const CALLEES: &[(&str, &str, &str, &str)] = &[ ]; /// Where `bytes`' code panics, for each of its panics the runtime makes, by the key it -/// passes in place of a location: a file under the crate's `src/`, the texts before it in -/// turn, and the text the call that panics starts with. None of its public functions takes -/// its caller's location, so each panic is where its source has it. -const BYTES: &[(&str, &str, &[&str], &str)] = &[ - ("bytes_advance", "lib.rs", &["fn panic_advance("], "panic!("), - ("bytes_does_not_fit", "lib.rs", &["fn panic_does_not_fit("], "panic!("), +/// passes in place of a location: the function, by its path, and which of its calls that +/// panic it is, in the order of its source, from 0. None of its public functions takes its +/// caller's location, so each panic is where its compiled code has it. +const BYTES: &[(&str, &str, usize)] = &[ + ("bytes_advance", "bytes::panic_advance", 0), + ("bytes_does_not_fit", "bytes::panic_does_not_fit", 0), // `range` takes its caller's location, so its panics are at its call. - ("bytes_slice", "bytes.rs", &["pub fn slice(&self"], "crate::range("), - ("bytes_slice_ref_start", "bytes.rs", &["pub fn slice_ref("], "assert!("), - ( - "bytes_slice_ref_end", - "bytes.rs", - &["pub fn slice_ref(", "assert!("], - "assert!(", - ), - ("bytes_split_off", "bytes.rs", &["pub fn split_off("], "assert!("), - ("bytes_split_to", "bytes.rs", &["pub fn split_to("], "assert!("), - ( - "bytes_buf_advance", - "bytes.rs", - &["impl Buf for Bytes", "fn advance("], - "assert!(", - ), - ( - "bytes_mut_split_off", - "bytes_mut.rs", - &["pub fn split_off("], - "assert!(", - ), - ("bytes_mut_split_to", "bytes_mut.rs", &["pub fn split_to("], "assert!("), - ( - "bytes_mut_set_len", - "bytes_mut.rs", - &["pub unsafe fn set_len("], - "debug_assert!(", - ), - ( - "bytes_mut_overflow", - "bytes_mut.rs", - &["fn reserve_inner(", "len.checked_add(additional)"], - "panic!(", - ), - ( - "bytes_mut_overflow_offset", - "bytes_mut.rs", - &["fn reserve_inner(", "new_cap.checked_add(offset)"], - "panic!(", - ), - ( - "bytes_mut_buf_advance", - "bytes_mut.rs", - &["impl Buf for BytesMut", "fn advance("], - "assert!(", - ), + ("bytes_slice", "bytes::Bytes::slice", 0), + ("bytes_slice_ref_start", "bytes::Bytes::slice_ref", 0), + ("bytes_slice_ref_end", "bytes::Bytes::slice_ref", 1), + ("bytes_split_off", "bytes::Bytes::split_off", 0), + ("bytes_split_to", "bytes::Bytes::split_to", 0), + ("bytes_buf_advance", "::advance", 0), + ("bytes_mut_split_off", "bytes::BytesMut::split_off", 0), + ("bytes_mut_split_to", "bytes::BytesMut::split_to", 0), + ("bytes_mut_set_len", "bytes::BytesMut::set_len", 0), + ("bytes_mut_overflow", "bytes::BytesMut::reserve_inner", 0), + ("bytes_mut_overflow_offset", "bytes::BytesMut::reserve_inner", 1), + ("bytes_mut_buf_advance", "::advance", 0), ]; +/// The [`BYTES`] sites of a `debug_assert!`, which a build without debug assertions leaves +/// out, as Rust leaves a call past it undefined. +const BYTES_DEBUG: &[&str] = &["bytes_mut_set_len"]; + /// The `rs.Sites` of the toolchain's std, which `rs.setHook` takes: where each panic /// [`SITES`] names is, as the native build names it, and each [`BYTES`] names, in the /// program's `bytes`, if it has one. @@ -566,18 +537,30 @@ fn bytes_sites(t: &mut Translator<'_, '_>, span: Span) -> Vec<(Key, Expr)> { if tcx.crate_name(krate).as_str() != "bytes" { continue; } - tcx.import_source_files(krate); + let mut fns = rustc_data_structures::fx::FxHashMap::default(); + let count = rustc_metadata::creader::CStore::from_tcx(tcx).num_def_ids_untracked(krate); + for index in 0..count { + let def_id = DefId { + krate, + index: rustc_hir::def_id::DefIndex::from_usize(index), + }; + if matches!(tcx.def_kind(def_id), DefKind::Fn | DefKind::AssocFn) { + fns.insert( + rustc_middle::ty::print::with_no_trimmed_paths!(tcx.def_path_str(def_id)), + def_id, + ); + } + } let mut props = Vec::new(); - for &(key, file, after, needle) in BYTES { - match bytes_find(tcx, krate, file, after, needle) { - Some(at) => props.push((Key::Name(key.into()), at)), - None => { - let after = after.join(" then "); + for &(key, path, nth) in BYTES { + let found = fns.get(path).map(|&f| panics(tcx, f, true).into_iter().nth(nth)); + match found { + Some(Some(at)) => props.push((Key::Name(key.into()), location(tcx, at))), + Some(None) if BYTES_DEBUG.contains(&key) => {} + _ => { t.err( span, - format!( - "the bytes crate's source has no `{needle}` in `src/{file}` after `{after}`, where it panics" - ), + format!("the bytes crate's compiled code has no panic {nth} in `{path}`, counting from 0"), ); } } @@ -595,29 +578,41 @@ fn bytes_sites(t: &mut Translator<'_, '_>, span: Span) -> Vec<(Key, Expr)> { tables.pop().unwrap_or_default() } -/// The `rs.Location` of the first `needle` after each of `after` in turn in `file`, under -/// `krate`'s `src/`, named as the session names it. -fn bytes_find( - tcx: TyCtxt<'_>, - krate: rustc_span::def_id::CrateNum, - file: &str, - after: &[&str], - needle: &str, -) -> Option { - let map = tcx.sess.source_map(); - let suffix = format!("/src/{file}"); - let source = (map.files().iter()) - .find(|f| f.cnum == krate && self::file(tcx, f).ends_with(&suffix)) - .cloned()?; - if !map.ensure_source_file_source_present(&source) { - return None; +/// The calls in the MIR `def_id`'s crate compiled for it that panic, outside what that +/// inlined, in the order of its source, by the macro call each came from: of std's `panic!`, +/// which `assert!` makes too, and if `tracked`, of a function of its own crate that takes its +/// caller's location, whose panics are at the call. None without that MIR. +fn panics(tcx: TyCtxt<'_>, def_id: DefId, tracked: bool) -> Vec { + if !tcx.is_mir_available(def_id) { + return Vec::new(); } - let text = match &source.src { - Some(src) => src.to_string(), - None => source.external_src.read().get_source()?.to_string(), - }; - let (line, col) = position(&text, after, needle)?; - Some(object(self::file(tcx, &source), line, col)) + let mir = tcx.optimized_mir(def_id); + let mut spans: Vec = (mir.basic_blocks.iter()) + .filter_map(|block| { + let terminator = block.terminator(); + let TerminatorKind::Call { func, .. } = &terminator.kind else { + return None; + }; + let (callee, _) = func.const_fn_def()?; + let panics = [LangItem::PanicFmt, LangItem::Panic, LangItem::PanicDisplay] + .into_iter() + .any(|item| tcx.is_lang_item(callee, item)) + || (tracked + && callee.krate == def_id.krate + && tcx + .codegen_fn_attrs(callee) + .flags + .contains(CodegenFnAttrFlags::TRACK_CALLER)); + let own = (terminator.source_info.scope) + .inlined_instance(&mir.source_scopes) + .is_none(); + let span = terminator.source_info.span; + (panics && own).then(|| span.ctxt().outer_expn().expansion_cause().unwrap_or(span)) + }) + .collect(); + spans.sort_by_key(|span| span.lo()); + spans.dedup(); + spans } /// Where `def_id`, a dependency's function that takes no caller's location, makes its one @@ -625,26 +620,10 @@ fn bytes_find( /// named as the native build names it under any `--remap-path-prefix`. `None` without that /// MIR, or with other than one such call. pub fn own_panic(tcx: TyCtxt<'_>, def_id: DefId) -> Option { - if !tcx.is_mir_available(def_id) { - return None; + match panics(tcx, def_id, false)[..] { + [span] => Some(location(tcx, span)), + _ => None, } - let mir = tcx.optimized_mir(def_id); - let mut spans = mir.basic_blocks.iter().filter_map(|block| { - let terminator = block.terminator(); - let TerminatorKind::Call { func, .. } = &terminator.kind else { - return None; - }; - let (callee, _) = func.const_fn_def()?; - let panics = [LangItem::PanicFmt, LangItem::Panic, LangItem::PanicDisplay] - .into_iter() - .any(|item| tcx.is_lang_item(callee, item)); - let own = (terminator.source_info.scope) - .inlined_instance(&mir.source_scopes) - .is_none(); - (panics && own).then_some(terminator.source_info.span) - }); - let span = spans.next()?; - spans.next().is_none().then(|| location(tcx, span)) } /// Where std's `def_id` panics, if [`CALLEES`] names it. diff --git a/ts/src/lower/mir/alloc.rs b/ts/src/lower/mir/alloc.rs index 59ceab692..ad51163a4 100644 --- a/ts/src/lower/mir/alloc.rs +++ b/ts/src/lower/mir/alloc.rs @@ -2,9 +2,10 @@ //! `*mut u8` to `*mut T` the body shows came from `alloc` or `realloc` makes the memory a JS //! array of `T`s, and one back to `*mut u8` is the block, only as what `dealloc` or //! `realloc` takes. Any other cast between them reads the bytes of one type as another, -//! which stays refused. +//! which stays refused, and so does a call of `alloc` or `realloc` whose byte pointer the +//! body passes on elsewhere, so no pointer to a block's bytes leaves the body that made it. -use rustc_middle::mir::{self, Local, Operand, ProjectionElem, Rvalue, TerminatorKind}; +use rustc_middle::mir::{self, Local, Operand, ProjectionElem, RETURN_PLACE, Rvalue, StatementKind, TerminatorKind}; use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, Spanned}; @@ -17,6 +18,22 @@ fn byte(ty: Ty<'_>) -> bool { matches!(ty.kind(), ty::Uint(ty::UintTy::U8)) } +/// Whether std's `owner::name` gives the byte pointer its first argument holds on, as a +/// pointer, a `NonNull`, or the payload of an `Option`, a `Result`, or `?`'s `ControlFlow`. +fn step(owner: &str, name: &str) -> bool { + matches!( + (owner, name), + ("NonNull", "new" | "new_unchecked" | "as_ptr") + | ("ptr" | "NonNull", "cast" | "cast_const" | "cast_mut") + | ( + "Option", + "ok_or" | "ok_or_else" | "unwrap" | "expect" | "unwrap_unchecked" + ) + | ("Result", "unwrap" | "expect" | "unwrap_unchecked") + | ("Try", "branch") + ) +} + /// Why the bytes of memory from `alloc` are refused. pub(super) const BYTES: &str = "a byte of memory from `alloc`, which JS keeps as the values a cast of its pointer types it as"; @@ -168,11 +185,164 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { match (owner.as_str(), name.as_str()) { ("alloc", "alloc") => library::is_std(self.tcx, def_id).then_some(local), ("alloc", "realloc") if library::is_std(self.tcx, def_id) => self.alloc_root(&args[0].node).or(Some(local)), - ("NonNull", "new" | "new_unchecked" | "as_ptr") - | ("ptr" | "NonNull", "cast" | "cast_const" | "cast_mut") - | ("Option", "ok_or" | "ok_or_else" | "unwrap" | "expect" | "unwrap_unchecked") - | ("Result", "unwrap" | "expect" | "unwrap_unchecked") - | ("Try", "branch") => self.alloc_root(&args[0].node), + (owner, name) if step(owner, name) => self.alloc_root(&args[0].node), + _ => None, + } + } + + /// Why the call of std's `def_id`, if `alloc` or `realloc`, can't be: the body passes the + /// byte pointer it returns into `dest` on elsewhere than a cast to a pointer to values JS + /// copies, `dealloc`, `realloc`, or the steps [`step`] names, such as into a field, out + /// of the body, or to any other function; or, of `realloc`, casts it to a pointer to a type + /// other than the one the memory it grows was cast from. A byte of the memory read or + /// written here is refused where it is. + pub(super) fn alloc_leak( + &self, + def_id: rustc_hir::def_id::DefId, + args: &[Spanned>], + dest: mir::Place<'tcx>, + ) -> Option { + if !library::is_std(self.tcx, def_id) { + return None; + } + let (owner, name) = library::key(self.tcx, def_id)?; + if owner != "alloc" || !matches!(name.as_str(), "alloc" | "realloc") { + return None; + } + let Some(types) = dest.as_local().and_then(|local| self.alloc_uses(local)) else { + return Some(format!( + "`{name}` whose pointer the body passes on as bytes, other than to a cast to a pointer to values, `dealloc`, or `realloc`, which JS keeps as the values a cast types the memory as" + )); + }; + // Memory from an `alloc` in the body, whose casts `alloc_cast` checks against each other. + if name != "realloc" || self.alloc_root(&args.first()?.node).is_some() { + return None; + } + let from = self.freed_type(&args.first()?.node)?; + let to = types.into_iter().find(|t| *t != from)?; + Some(format!( + "`realloc` of memory cast from a pointer to `{from}` whose result is cast to one to `{to}`, which reads the bytes of one type as another" + )) + } + + /// The types the casts in the body of the byte pointer in `root` type it as, if the body + /// passes it on no further than [`Self::alloc_leak`] allows. + fn alloc_uses(&self, root: Local) -> Option>> { + let (decls, tcx) = (&self.mir.local_decls, self.tcx); + // Whether a value of `ty` may hold the pointer: one to bytes, or what holds one. + let holds = |ty: Ty<'tcx>| { + ty.walk().any(|arg| { + arg.as_type().is_some_and(|t| match t.kind() { + ty::RawPtr(pointee, _) => byte(*pointee), + ty::Adt(adt, args) => { + library::Std::of(tcx, adt.did()) == Some(library::Std::NonNull) && byte(args.type_at(0)) + } + _ => false, + }) + }) + }; + // Whether `op` reads what `local` holds, or a payload of it, but not through it. + let reads = |op: &Operand<'tcx>, local: Local| { + op.place() + .is_some_and(|p| p.local == local && !p.projection.contains(&ProjectionElem::Deref)) + }; + let mut types = Vec::new(); + let mut seen = vec![root]; + let mut todo = vec![root]; + while let Some(local) = todo.pop() { + // Out of the body, as what it returns or into what it was given. + if local == RETURN_PLACE || self.is_arg(local) { + return None; + } + let mut carry = |to: mir::Place<'tcx>| -> Option<()> { + if !holds(to.ty(decls, tcx).ty) { + return Some(()); + } + let to = to.as_local()?; + if !seen.contains(&to) { + seen.push(to); + todo.push(to); + } + Some(()) + }; + for data in self.mir.basic_blocks.iter() { + for stmt in &data.statements { + let StatementKind::Assign(assign) = &stmt.kind else { + continue; + }; + let (dest, rvalue) = &**assign; + match rvalue { + Rvalue::Cast(mir::CastKind::PtrToPtr, op, to) if reads(op, local) => { + match to.builtin_deref(true) { + Some(pointee) if !byte(pointee) => types.push(self.alloc_key(pointee)), + _ => carry(*dest)?, + } + } + Rvalue::Use(op, _) | Rvalue::Cast(_, op, _) if reads(op, local) => carry(*dest)?, + Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) + if place.local == local && !place.projection.contains(&ProjectionElem::Deref) => + { + return None; + } + Rvalue::Aggregate(_, ops) if ops.iter().any(|op| reads(op, local)) => return None, + _ => {} + } + } + let TerminatorKind::Call { + func, + args, + destination, + .. + } = &data.terminator().kind + else { + continue; + }; + let Some(at) = args.iter().position(|a| reads(&a.node, local)) else { + continue; + }; + let ty::FnDef(def_id, gargs) = *func.ty(decls, tcx).kind() else { + return None; + }; + let (owner, name) = library::key(tcx, def_id).filter(|_| library::is_std(tcx, def_id))?; + match (owner.as_str(), name.as_str()) { + ("alloc", "dealloc" | "realloc") if at == 0 => {} + ("ptr" | "NonNull", "is_null") => {} + ("ptr" | "NonNull", "cast") => match gargs.skip_binder().types().nth(1) { + Some(to) if !byte(to) => types.push(self.alloc_key(to)), + _ => carry(*destination)?, + }, + (owner, name) if at == 0 && step(owner, name) => carry(*destination)?, + _ => return None, + } + } + } + Some(types) + } + + /// The type of the values the pointer `op`, which `dealloc` or `realloc` takes, was cast + /// from in the body, as `alloc_key` names it. + fn freed_type(&self, op: &Operand<'tcx>) -> Option> { + let local = self.traced(op)?; + if self.def_at[local].is_some() { + return match self.def_rvalue(local)? { + Rvalue::Use(op, _) => self.freed_type(op), + Rvalue::Cast(mir::CastKind::PtrToPtr, op, _) => { + let from = op.ty(&self.mir.local_decls, self.tcx).builtin_deref(true)?; + (!byte(from)).then(|| self.alloc_key(from)) + } + _ => None, + }; + } + let (def_id, gargs, args) = self.def_call(local)?; + match library::key(self.tcx, def_id)? { + (owner, name) if matches!(owner.as_str(), "ptr" | "NonNull") && name == "cast" => { + let from = gargs.types().next()?; + match byte(from) { + true => self.freed_type(&args.first()?.node), + false => Some(self.alloc_key(from)), + } + } + (owner, name) if owner == "NonNull" && name == "as_ptr" => self.freed_type(&args.first()?.node), _ => None, } } diff --git a/ts/src/lower/mir/call.rs b/ts/src/lower/mir/call.rs index 2923d0db0..ddb9505b4 100644 --- a/ts/src/lower/mir/call.rs +++ b/ts/src/lower/mir/call.rs @@ -107,6 +107,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> { ty::FnDef(def_id, gargs) if let Some(why) = self.stray(def_id, gargs.skip_binder(), args) => { (self.err(span, why), true) } + ty::FnDef(def_id, _) if let Some(why) = self.alloc_leak(def_id, args, dest) => (self.err(span, why), true), ty::FnDef(def_id, gargs) if let Some(cast) = self.alloc_cast_call(def_id, gargs.skip_binder(), args, span, &mut pre) => { @@ -1203,6 +1204,15 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> { self.slots[local] = Slot::Alias(Some(place)); Some(None) } + // Bytes from other storage, which JS may keep apart where Rust shares them, as a + // `&'static str`'s bytes that `as_bytes` encodes anew. + ("Bytes", "slice_ref") if bytes && !self.bytes_of(&args[1].node, &args[0].node) => done( + self.err( + span, + "`Bytes::slice_ref` of bytes the body doesn't show it borrowed from that `Bytes`'s storage, through `Deref`, `as_ref`, or a slice of one, which JS may keep apart where Rust shares them", + ), + true, + ), // A `Bytes`'s slice by a range's bounds, read where the range is made. Its bounds // check panics, so it runs even if the slice goes unused. ("Bytes", "slice") diff --git a/ts/src/lower/mir/origin.rs b/ts/src/lower/mir/origin.rs index ef3826c59..1c65599f1 100644 --- a/ts/src/lower/mir/origin.rs +++ b/ts/src/lower/mir/origin.rs @@ -492,15 +492,23 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { return None; } let owner = self.tcx.item_name(adt.did()).to_string(); - let arc = &args.first()?.node; - let place = match self.traced(arc) { + Some((self.referent(&args.first()?.node)?, owner)) + } + + /// The place the shared reference `r` borrows, if the body shows it and that it holds the + /// same value while the borrow lives: one a borrow here took, or what a reference it is + /// given or assigns once points at. + fn referent(&self, r: &Operand<'tcx>) -> Option> { + let place = match self.traced(r) { + Some(r) if self.def_at[r].is_none() => return Some(self.tcx.mk_place_deref(mir::Place::from(r))), Some(r) => match self.def_rvalue(r)? { + Rvalue::Use(op, _) => return self.referent(op), Rvalue::Ref(_, _, place) => *place, _ => return None, }, // A reference the function is given and never assigns. None => { - let r = arc.place()?.as_local()?; + let r = r.place()?.as_local()?; if !self.is_arg(r) || self.defs[r] != 0 { return None; } @@ -528,7 +536,124 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { } _ => false, }); - stays.then_some((place, owner)) + stays.then_some(place) + } + + /// The place the shared reference `r` borrows, as [`Self::referent`] has it, or the + /// element `v[i]` it is where it is `&v[i]` of a `Vec` or slice by an index the body + /// assigns once, which the borrow keeps where it is: two such borrows lend one element. + fn lent(&self, r: &Operand<'tcx>) -> Option> { + let indexed = self.traced(r).filter(|&l| self.def_at[l].is_none()).and_then(|l| { + let (def_id, gargs, args) = self.def_call(l)?; + let by_usize = gargs + .types() + .nth(1) + .is_some_and(|ty| matches!(ty.kind(), ty::Uint(ty::UintTy::Usize))); + if !by_usize || library::key(self.tcx, def_id)? != ("Index".into(), "index".into()) { + return None; + } + let elem = match &args.get(1)?.node { + Operand::Constant(_) => { + let offset = u64::try_from(self.const_int(&args[1].node)?).ok()?; + ProjectionElem::ConstantIndex { + offset, + min_length: offset + 1, + from_end: false, + } + } + op => { + let i = op.place()?.as_local()?; + let fixed = match self.is_arg(i) { + true => self.defs[i] == 0, + false => self.defs[i] == 1, + }; + if !fixed || self.mutated[i] { + return None; + } + ProjectionElem::Index(i) + } + }; + Some(self.lent(&args.first()?.node)?.project_deeper(&[elem], self.tcx)) + }); + indexed.or_else(|| self.referent(r)) + } + + /// The place of the `Bytes` whose storage the `Bytes` at `place` shares, as the body + /// shows: through `slice` or `clone` of one, into a variable assigned once and never + /// changed in place, which keeps that storage. + fn storage(&self, place: mir::Place<'tcx>) -> mir::Place<'tcx> { + let Some(local) = place.as_local() else { + return place; + }; + if self.defs[local] != 1 || self.is_arg(local) || self.mutated[local] { + return place; + } + let Some(bb) = self.def_block(local) else { + return place; + }; + let TerminatorKind::Call { func, args, .. } = &self.mir.basic_blocks[bb].terminator().kind else { + return place; + }; + let Some((def_id, gargs)) = func.const_fn_def() else { + return place; + }; + let shares = match library::key(self.tcx, def_id) { + Some((owner, name)) => match (owner.as_str(), name.as_str()) { + ("Bytes", "slice") => library::inherent_std(self.tcx, def_id) == Some(Std::Bytes), + ("Clone", "clone") => gargs + .types() + .next() + .is_some_and(|ty| self.b.t.std_of(ty) == Some(Std::Bytes)), + _ => false, + }, + None => false, + }; + match args.first().filter(|_| shares).and_then(|a| self.referent(&a.node)) { + Some(from) => self.storage(from), + None => place, + } + } + + /// Whether the shared slice `subset` is of the storage of the `Bytes` the shared + /// reference `bytes` is to, as the body shows: through the `Deref` or `as_ref`, or a slice + /// of one, of that `Bytes` or one sharing its storage, as [`Self::storage`] has it. Only + /// then does JS keep both in one buffer where Rust does. + pub(super) fn bytes_of(&self, subset: &Operand<'tcx>, bytes: &Operand<'tcx>) -> bool { + let Some(local) = self.traced(subset) else { + return false; + }; + if self.def_at[local].is_some() { + return match self.def_rvalue(local) { + Some(Rvalue::Use(op, _)) => self.bytes_of(op, bytes), + // `&*s`, of the shared slice `s`. + Some(Rvalue::Ref(_, mir::BorrowKind::Shared, place)) + if let [ProjectionElem::Deref] = place.projection.as_slice() => + { + self.bytes_of(&Operand::Copy(mir::Place::from(place.local)), bytes) + } + _ => false, + }; + } + let Some((def_id, gargs, args)) = self.def_call(local) else { + return false; + }; + let Some(of) = args.first().map(|a| &a.node) else { + return false; + }; + let Some(self_ty) = gargs.types().next() else { + return false; + }; + match library::key(self.tcx, def_id) { + Some((owner, name)) => match (owner.as_str(), name.as_str()) { + ("Index", "index") if self_ty.is_slice() => self.bytes_of(of, bytes), + ("Deref", "deref") | ("AsRef", "as_ref") if self.b.t.std_of(self_ty) == Some(Std::Bytes) => { + let storage = |r| self.lent(r).map(|place| self.storage(place)); + storage(of).is_some_and(|place| storage(bytes) == Some(place)) + } + _ => false, + }, + None => false, + } } /// `Arc::as_ptr` of the `Arc` or `Rc` whose value of a type JS copies the shared diff --git a/ts/tests/fixtures.rs b/ts/tests/fixtures.rs index 0f3465a7b..f8b3978aa 100644 --- a/ts/tests/fixtures.rs +++ b/ts/tests/fixtures.rs @@ -61,8 +61,8 @@ fn driver_at(manifest: &Path, config: &Path, args: &[&std::ffi::OsStr], build: & /// The flags that name cargo's home `/cargo` in both builds, so the files of the registry's /// crates, which a hook's locations name, are named alike on any host, and tokio's `sync` -/// module `tokio/channels`, a remap of a directory within a crate, which the location of -/// tokio's panic must follow as native does. +/// module `tokio/channels` and bytes' `src` `bytes/source`, remaps of a directory within a +/// crate, which the locations of their panics must follow as native does. fn remap() -> String { static FLAGS: std::sync::OnceLock = std::sync::OnceLock::new(); FLAGS.get_or_init(remap_flags).clone() @@ -84,16 +84,25 @@ fn remap_flags() -> String { .join(".cargo"), }; let lock = std::fs::read_to_string(manifest_dir().join("Cargo.lock")).unwrap(); - let (_, tokio) = lock - .split_once("name = \"tokio\"\nversion = \"") - .expect("tokio in the lockfile"); - let tokio = format!("tokio-{}", &tokio[..tokio.find('"').unwrap()]); + let version = |name: &str| { + let (_, rest) = lock + .split_once(&format!("name = \"{name}\"\nversion = \"")) + .unwrap_or_else(|| panic!("{name} in the lockfile")); + format!("{name}-{}", &rest[..rest.find('"').unwrap()]) + }; + let dirs = [ + (version("tokio") + "/src/sync", "tokio/channels"), + (version("bytes") + "/src", "bytes/source"), + ]; // The later flag wins where both match. let mut flags = format!("--remap-path-prefix={}=/cargo", home.display()); for index in std::fs::read_dir(home.join("registry/src")).into_iter().flatten() { - let sync = index.unwrap().path().join(&tokio).join("src/sync"); - if sync.is_dir() { - flags += &format!(" --remap-path-prefix={}=tokio/channels", sync.display()); + let index = index.unwrap().path(); + for (dir, to) in &dirs { + let dir = index.join(dir); + if dir.is_dir() { + flags += &format!(" --remap-path-prefix={}={to}", dir.display()); + } } } flags @@ -506,6 +515,30 @@ mod lang { super::lang("panics", Some("hook")); } + /// A program with a hook translates when its crates are built without debug assertions, + /// which leave out the panic of `bytes`' `debug_assert!`. + #[test] + fn panics_without_debug_assertions() { + let name = "lang/panics"; + let out = super::scratch().join(name).join("nodebug"); + let args: [&std::ffi::OsStr; 5] = [ + "--out".as_ref(), + out.as_ref(), + "--".as_ref(), + "--features".as_ref(), + "hook".as_ref(), + ]; + let output = super::driver_command(name, &super::fixture(name).join("ts.toml"), &args, "nodebug-build") + .env("CARGO_PROFILE_DEV_DEBUG_ASSERTIONS", "false") + .output() + .expect("running rust2-ts"); + assert!( + output.status.success(), + "translating {name} without debug assertions failed:\n{}", + String::from_utf8_lossy(&output.stderr) + ); + } + lang!( args, arrays,