diff --git a/AGENTS.md b/AGENTS.md index 0a6cb928b..6eb735453 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,6 +4,7 @@ Each project lives in its own top-level directory; the [quest tree](quest/README # Required - An unsupported construct or malformed input is a compile error with a source span, never a warning, a silent fallback, or a runtime failure. Generated code panics only where the Rust source does. + The one exception is an `unsafe` pointer from elsewhere whose origin translation can't see, such as a parameter's: a loud run-time check may stand in for the refusal, under m3's [unsafe policy](quest/m3/README.md), since refusing every such pointer would refuse pointer arithmetic on any parameter. - Generated output must match the source's semantics exactly: integer widths and overflow, drop order, laziness, and error paths. Prove it with differential tests against native Rust, not by inspection. - Everything is configless, with opinionated names and defaults. Translators take stock crates as they are: no annotations, and no config beyond true platform boundaries. Each config key or source change a consumer needs is a gap to close. - A vanity rename, if ever supported, is opt-in and lives inline in source next to the item, never in a config file. diff --git a/quest/m3/README.md b/quest/m3/README.md index d7109b4bc..624d4100d 100644 --- a/quest/m3/README.md +++ b/quest/m3/README.md @@ -45,7 +45,7 @@ memory model for values whose address is reinterpreted, without a consumer. - [Unsafe code the translator can model](/quest/m3/ts-unsafe/README.md) - a dependency using only `unsafe` the translator can model translates from source - [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: an exact slower path, or a refusal at translation +- [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 - [`if let` of a temporary whose rest drops](/quest/m3/ts-if-let-drop.md) - `if let Some(E::A(x)) = temp()` with a destructor in the rest of `temp` emits TypeScript that type-checks diff --git a/quest/m3/ts-runtime-throws.md b/quest/m3/ts-runtime-throws.md index af4fad7bf..8f0e83035 100644 --- a/quest/m3/ts-runtime-throws.md +++ b/quest/m3/ts-runtime-throws.md @@ -1,67 +1,55 @@ -# [L] Throw only where Rust panics +# [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, through a slower path if it must, or is refused at -translation with a span. Proven by differential tests against native Rust for every -construct that now translates. +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 slower exact path, no flag: where one exists it is the translation, with the fast - path kept where the translator can prove it applies; refuse at translation only where - none exists. Rejected: refusing with no fallback; an inline opt-in. -- ✅ A throw that guards Rust UB (a read through a null or dangling pointer, `from_raw` of - a value already dropped, freeing memory `alloc` did not give) stays, as an abort worded - like std's `unsafe precondition(s) violated` check, since Rust defines nothing there. - -The rest are gaps. At `main` they include a panic its hook cannot locate -([#556](https://github.com/moq-dev/rust2/pull/556)), a pointer cast to `()` that is not an -`Arc`'s or `Rc`'s (`rs.arcErase`, [#562](https://github.com/moq-dev/rust2/pull/562), -[#565](https://github.com/moq-dev/rust2/pull/565)), `offset_from` of one Rust allocation -JS keeps in two arrays, a pointer moved past the array JS keeps it in (`AtIndex.reach`, such -as one kept in a field), `Bytes::slice_ref` of other storage, `alloc`'s bytes read as -values, ranges stepped without their type, fmt widths written as a placeholder, a read -through a substring's `str::as_ptr` outside its own bytes but inside its text's -(`s[..1].as_ptr().add(1)`, `s[1..].as_ptr().wrapping_sub(1)`), and a raw or mutable slice -of a byte in a field (a struct's, a tuple's, a closure's capture, or one an async body keeps -across an `.await`), or a cast of one to `*const [u8; N]`: a field's byte has no buffer of -its own, unlike a `u8` local whose `&raw` the body takes, so the fix is a `Uint8Array(1)` -for each `u8` field whose address is taken. A `u8` local whose address only a call takes, -as `ptr::from_mut(&mut b)` does, has none either. -The substring reads are UB under Stacked Borrows and allowed under Tree Borrows, so they -throw until Rust settles its memory model (decided 2026-11-07 in -[#634](https://github.com/moq-dev/rust2/pull/634)); if Rust rules them defined, a -substring's pointer carries its text's encoding and offset. -`git grep 'rust2-ts: ' ts/runtime` lists them; classify each before fixing. The pointer -comparisons [#584](https://github.com/moq-dev/rust2/pull/584) refuses at translation, where -JS may make two `rs.Place`s for one place, are out of scope: addresses were their route, and -addresses stay refused (decided 2026-11-07 in [the model epic](/quest/m2/ts-model/README.md)). - -✅ Decided with the maintainer on 2026-11-06 in -[moq-dev/rust2#608](https://github.com/moq-dev/rust2/pull/608): comparing `*const [T]` of -values JS copies moved here from rs.Slice's quest. The options -were to wait on rs.String ([moq-dev/rust2#574](https://github.com/moq-dev/rust2/pull/574)) and run only if `&str` shares -its bytes, or to move it here with the other comparisons left refused (picked). Its only -consumer in moq-net is form_urlencoded 1.2.2's `src/lib.rs:417`, -`debug_assert!(ptr::eq(s.as_bytes(), vec))`, of the `&str` that -`String::from_utf8_lossy(&vec)` borrowed. Under -[moq-dev/rust2#574](https://github.com/moq-dev/rust2/pull/574)'s decision a `&str` stays a -JS string, so `as_bytes` makes fresh bytes and today's refusal is exact; comparing by array -and offset would answer `false` where Rust answers `true`. Look for an exact slower path. - -✅ Decided with the maintainer on 2026-11-07 in -[moq-dev/rust2#608](https://github.com/moq-dev/rust2/pull/608): `ptr::eq` of an array that -`as_chunks` split from one flat slice, as std lends it to a callback, moved here. Such an -array has no JS array of its own, so `rs.arraySliceItems` gives std a copy of it, and -`ptr::eq` with the array lent elsewhere answers `false` where Rust answers `true`. Arrays -that are each a JS array of their own keep their identity. Look for an exact slower path -with the `*const [T]` comparisons above. +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`, raw slices of a field's byte, and `Bytes::slice_ref` of copied bytes, + safe code with no exact answer while a `&str` stays a JS string. AGENTS.md allows the + unsafe ones under m3's [unsafe policy](/quest/m3/README.md). +- Rejected: refusing all of them at translation, which refuses pointer arithmetic on any + pointer parameter; keeping all as run-time checks. + +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`' 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. diff --git a/quest/m3/ts-unsafe/README.md b/quest/m3/ts-unsafe/README.md index 328b9830b..39c266f21 100644 --- a/quest/m3/ts-unsafe/README.md +++ b/quest/m3/ts-unsafe/README.md @@ -62,7 +62,9 @@ construct still open at `b3df54b6c`, all in m3: a byte pointer past its view fail loudly at run time are superseded by [Throw only where Rust panics](/quest/m3/ts-runtime-throws.md) (2026-11-04, #597): where Rust defines the access it translates exactly or is refused with a span, and only a - throw guarding UB stays, as a precondition abort. + throw guarding UB stays, as a precondition abort, or a loud check of a pointer from + elsewhere whose origin translation can't see (2026-11-07, + [#661](https://github.com/moq-dev/rust2/pull/661)). - Done and dropped: a byte pointer past its own `Uint8Array` view. Byte pointers index the whole buffer since [#400](https://github.com/moq-dev/rust2/pull/400) and [#576](https://github.com/moq-dev/rust2/pull/576), and a byte `Vec` keeps its diff --git a/ts/Cargo.lock b/ts/Cargo.lock index 2c61d6bac..37c56ffb4 100644 --- a/ts/Cargo.lock +++ b/ts/Cargo.lock @@ -387,6 +387,7 @@ version = "0.0.0" dependencies = [ "bytes", "edition2018", + "tokio", ] [[package]] diff --git a/ts/README.md b/ts/README.md index 5e2dc89f1..614fb143f 100644 --- a/ts/README.md +++ b/ts/README.md @@ -110,7 +110,7 @@ crate translation reaches is refused, and so are two versions of one crate it re | `Vec` | `rs.Vec`: its items, the array `items`, and the capacity std's holds; `rs.vecFrom(items)` makes one of an array with room for exactly them. `rs.ByteVec` of bytes | | `Cow<[T]>`, `Cow` | `rs.Cow`: the `Vec` it owns, or an `rs.Borrowed` holding the slice it borrows, `rs.Cow>` holding the arrays of a slice of arrays; `rs.ByteCow` for bytes, an `rs.ByteVec` or an `rs.ByteSlice`; `rs.StrCow` for text, the `rs.String` it owns or an `rs.Borrowed` holding the string it borrows, whose text `rs.strCowStr` reads | | `&T`, `&mut T`, `Box`, `Reverse`, `NonZero`, `AssertUnwindSafe` | the value; a `&mut` to a value JS copies, such as a number, an `Option`, or a reference, or to an `Arc`, a `Waker`, or a `LocalKey`, whose copies share what it points at, is an `rs.Place`, which for what a box holds is the place holding the box | -| `*const T`, `*mut T`, `NonNull` | what a `&mut T` is: the object, an `rs.Slice` of a `[T; N]`'s elements or an `rs.ByteSlice` of a `[u8; N]`'s bytes, which compares by the array or buffer and offset they are at, refused for an array of one, which `array::from_ref`, `from_mut` of a variable, and `Option::as_slice` make of their own, or an `rs.Place` to a value JS copies and to a library type such as a `Vec` or an `Arc`, which into an array, slice, or `Vec` is the `rs.AtIndex` of its element, which `add`, `sub`, `offset`, their wrapping forms, `offset_from`, `ptr::copy`, `write_bytes` of bytes, and `slice::from_raw_parts` move, measure, copy between, set, and view; one to a value in no array is element 0 of an array of one, as in Rust, but a byte variable whose `&raw` the body takes, or that of a reference to it made there, as `&mut b as *mut u8` does, or of whose `&mut` it makes a slice of one, is element 0 of a `Uint8Array` of its own, which its raw, mutable, and shared slices view as they do any other bytes; JS keeps an array of one, and a shared subslice of a byte in no array, which JS copies, apart from what holds it in Rust, so a pointer, slice, copy, or write of bytes the body shows reaching past either, and `offset_from` between pointers the body shows JS keeps in different arrays, are refused, and through a pointer from elsewhere any of these, a raw or mutable slice of a byte in no array, such as a field's, or a read or write past the array JS keeps it in but for a `Vec`'s room up to its capacity, fails at run time; a pointer into an array of values JS keeps as objects is refused, as is comparing pointers to other values JS copies, each a place JS makes of its own; `rs.NULL` for null and `rs.DANGLING` for dangling. `str::as_ptr` points into the text's UTF-8, which JS encodes anew at each call, so a read through it reads what Rust's does and a write, or a mutable slice, through it, which Rust forbids, fails at run time, as do a read before its first byte, such as a substring's pointer moved back into its text's bytes, and `offset_from` between two calls' pointers, each refused where the body shows it. A pointer to a slice cast to one to an array of its elements is the `rs.Slice` or `rs.ByteSlice` of that many from its first, read through only where Rust reads. A `*const ()` is an identity, such as a waker's data, and `rs.DANGLING_UNIT` when dangling; one to a place of `()` or from a reference to one is refused. A pointer to a value JS keeps as an object cast to one, by `as` or `cast`, is the same object, which `rs.ptrErase` notes the type of, so a cast back to a pointer to another type fails at run time, and null and dangling stay so, dangling at the alignment of the type it was cast from; one to a value JS copies is the same place where an `Arc`'s or `Rc`'s `into_raw` or `as_ptr` gave it, its value's one place, which `rs.arcErase` checks where the body doesn't show it, and refused where the body shows a borrow's, a new place each borrow, as is casting one to a view of bytes, a new one each borrow, or one of no fixed size. A write of a whole object copies into it one object deep, as an assignment through a `&mut` does, the state an `rs` class such as `rs.LazyCell` keeps private included, so a pointer to a part kept as an object, such as a field of a tuple or struct type, is refused wherever the crate may put another object there while a pointer into that memory may still be read, which a write into a fresh allocation, or a variable before any pointer into it is taken, can't, whether by index or through std's iterators over its slots; a read copies what the crate writes into in place | +| `*const T`, `*mut T`, `NonNull` | what a `&mut T` is: the object, an `rs.Slice` of a `[T; N]`'s elements or an `rs.ByteSlice` of a `[u8; N]`'s bytes, which compares by the array or buffer and offset they are at, refused for an array of one, which `array::from_ref`, `from_mut` of a variable, and `Option::as_slice` make of their own, or an `rs.Place` to a value JS copies and to a library type such as a `Vec` or an `Arc`, which into an array, slice, or `Vec` is the `rs.AtIndex` of its element, which `add`, `sub`, `offset`, their wrapping forms, `offset_from`, `ptr::copy`, `write_bytes` of bytes, and `slice::from_raw_parts` move, measure, copy between, set, and view; one to a value in no array is element 0 of an array of one, as in Rust, but a byte variable whose `&raw` the body takes, or that of a reference to it made there, as `&mut b as *mut u8` does, or of whose `&mut` it makes a slice of one, is element 0 of a `Uint8Array` of its own, which its raw, mutable, and shared slices view as they do any other bytes; JS keeps an array of one, and a shared subslice of a byte in no array, which JS copies, apart from what holds it in Rust, so a pointer, slice, copy, or write of bytes the body shows reaching past either, and `offset_from` between pointers the body shows JS keeps in different arrays, are refused, and through a pointer from elsewhere any of these, a raw or mutable slice of a byte in no array, such as a field's, or a read or write past the array JS keeps it in but for a `Vec`'s room up to its capacity, fails at run time; a pointer into an array of values JS keeps as objects is refused, as is comparing pointers to other values JS copies, each a place JS makes of its own; `rs.NULL` for null and `rs.DANGLING` for dangling, a read or write through either of which, or through a pointer arithmetic moved off either, aborts, as Rust leaves it undefined. `str::as_ptr` points into the text's UTF-8, which JS encodes anew at each call, so a read through it reads what Rust's does and a write through it, which Rust leaves undefined, aborts, as std's debug checks of unsafe preconditions do, while a mutable slice of it, a read before its first byte, such as a substring's pointer moved back into its text's bytes, and `offset_from` between two calls' pointers fail at run time, each refused where the body shows it. A pointer to a slice cast to one to an array of its elements is the `rs.Slice` or `rs.ByteSlice` of that many from its first, read through only where Rust reads. A `*const ()` is an identity, such as a waker's data, and `rs.DANGLING_UNIT` when dangling; one to a place of `()` or from a reference to one is refused. A pointer to a value JS keeps as an object cast to one, by `as` or `cast`, is the same object, which `rs.ptrErase` notes the type of, so a cast back to a pointer to another type fails at run time, and null and dangling stay so, dangling at the alignment of the type it was cast from; one to a value JS copies is the same place where an `Arc`'s or `Rc`'s `into_raw` or `as_ptr` gave it, its value's one place, and refused where the body doesn't show one of those gave it, or null or dangling, such as a borrow's, a new place each borrow, as is casting one to a view of bytes, a new one each borrow, or one of no fixed size. A write of a whole object copies into it one object deep, as an assignment through a `&mut` does, the state an `rs` class such as `rs.LazyCell` keeps private included, so a pointer to a part kept as an object, such as a field of a tuple or struct type, is refused wherever the crate may put another object there while a pointer into that memory may still be read, which a write into a fresh allocation, or a variable before any pointer into it is taken, can't, whether by index or through std's iterators over its slots; a read copies what the crate writes into in place | | `MaybeUninit` | `T`: `undefined` until written, `0` for a byte, or an object whose parts kept as objects are there, holding `undefined`, as `Box::new_uninit` and each of `Box::new_uninit_slice`'s is; a slice's `write_clone_of_slice` clones into its slots without dropping what they held. `Box::new_zeroed`'s holds the value of zero bytes in each part they are one of, such as a number, `false`, `None`, a null pointer, or an enum's variant of a tag or niche of zero, and `undefined` in each part they are none of, such as a reference, for a write to fill before a read | | `ManuallyDrop` | `T`, which nothing drops but its own `drop`; its `Debug`, comparisons, and constants are refused | | `union` | an object of slots named by offset, `at0` and `at8`, each holding the field part kept there; fields must overlap in the same type, or in a non-null pointer and an `Option` of it | @@ -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; 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, and fail at run time through a pointer from elsewhere | | 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 | @@ -136,7 +136,7 @@ crate translation reaches is refused, and so are two versions of one crate it re | `static` | a module's value, named for the static, that every use shares, read from the memory rustc evaluated; one that reads another static or a class is an `rs.LazyCell` of it, made on first use, since that may not be made yet when its module is. A `static mut`, and a pointer in one into memory the translation can't name, fail translation | | a type that drops | a class with `[Symbol.dispose]`: its `Drop` impl, then its fields | | a type's function | a function of the type's module, taking `self` first: `Decoder.slice(dec, 4)` after `import * as Decoder` | -| `Arc`, `Rc`, `Weak`, `Mutex` | `rs.Arc` for either, of what a `Box` is for a slice or `str`, with its strong and weak counts, an `Arc<[T; N]>` unsized to an `Arc<[T]>` an `rs.ArcDyn` of the slice of its array, sharing its count, an `Arc<[u8]>` of an `Arc`'s bytes sharing its count, and `new_cyclic`'s `Weak` upgrading only once its value is made, `get_mut` lending its value only while no other `Arc` or `Weak` shares it, `make_mut` cloning it into a new `rs.Arc` while another `Arc` shares it, or moving it there while only `Weak`s do, which then dangle, as a copy where pointers to it compare, `as_ptr` and `into_raw` pointing where a reference to its value does, or at its place where JS copies it, as a pointer the body shows made from a reference to that value does, which `from_raw`, `increment_strong_count`, and `decrement_strong_count` take back to its `rs.Arc` and count, refused for one the body shows a borrow made, and failing at run time on another pointer no `as_ptr` or `into_raw` of that type of `Arc` gave, or one whose value dropped, and refused for one to a slice or bytes, which JS makes anew each time, and `ptr::addr_eq` comparing what `ptr::eq` compares, of one pointee type, and `into_inner` giving it only from the last strong `Arc`, after which its `Weak`s no longer upgrade; `rs.Weak`, counted in its `rs.Arc` until it drops, and of no `Arc` once made by `Weak::new`; `rs.Mutex`, its own guard, which a lock gives as `Ok` and the guard's drop unlocks: locking it again while held panics and `try_lock` gives `WouldBlock`, as wasm32's do, and a guard's `map` and `filter_map` make `rs.MutexMap`s, each where the part it lends is, which hold the mutex locked until they drop, and a panic aborts, so nothing poisons it and `thread::panicking` is `false`; a `Mutex`'s, a `RefCell`'s, and an `RwLock`'s `into_inner` gives its value and `get_mut` lends it, or an `rs.Place` of it where JS copies it | +| `Arc`, `Rc`, `Weak`, `Mutex` | `rs.Arc` for either, of what a `Box` is for a slice or `str`, with its strong and weak counts, an `Arc<[T; N]>` unsized to an `Arc<[T]>` an `rs.ArcDyn` of the slice of its array, sharing its count, an `Arc<[u8]>` of an `Arc`'s bytes sharing its count, and `new_cyclic`'s `Weak` upgrading only once its value is made, `get_mut` lending its value only while no other `Arc` or `Weak` shares it, `make_mut` cloning it into a new `rs.Arc` while another `Arc` shares it, or moving it there while only `Weak`s do, which then dangle, as a copy where pointers to it compare, `as_ptr` and `into_raw` pointing where a reference to its value does, or at its place where JS copies it, as a pointer the body shows made from a reference to that value does, which `from_raw`, `increment_strong_count`, and `decrement_strong_count` take back to its `rs.Arc` and count, refused for one the body shows a borrow made, and aborting, as std's debug checks of unsafe preconditions do, on another pointer no `as_ptr` or `into_raw` of that type of `Arc` gave, or one whose value dropped, which Rust leaves undefined, and refused for one to a slice or bytes, which JS makes anew each time, and `ptr::addr_eq` comparing what `ptr::eq` compares, of one pointee type, and `into_inner` giving it only from the last strong `Arc`, after which its `Weak`s no longer upgrade; `rs.Weak`, counted in its `rs.Arc` until it drops, and of no `Arc` once made by `Weak::new`; `rs.Mutex`, its own guard, which a lock gives as `Ok` and the guard's drop unlocks: locking it again while held panics and `try_lock` gives `WouldBlock`, as wasm32's do, and a guard's `map` and `filter_map` make `rs.MutexMap`s, each where the part it lends is, which hold the mutex locked until they drop, and a panic aborts, so nothing poisons it and `thread::panicking` is `false`; a `Mutex`'s, a `RefCell`'s, and an `RwLock`'s `into_inner` gives its value and `get_mut` lends it, or an `rs.Place` of it where JS copies it | | `PoisonError`, `TryLockError` | the `T` it holds; `rs.TryLockError`, tagged as `Bound` is | | `Cell`, `UnsafeCell`, `RefCell`, `RwLock` | `rs.Cell`, the place holding its value in `v`, for either of the first two: `UnsafeCell::get`'s and `Cell::as_ptr`'s pointer, and `get_mut`'s reference, is the cell where it is an `rs.Place`, and otherwise the object in `v`, refused where the crate may put another cell or object in its place; `rs.RefCell` for either of the others, its own guard, counting its borrows: borrowing it while that conflicts panics as `RefCell`'s does, and locking it so aborts as wasm32's `RwLock` does; `try_borrow` and `try_borrow_mut` fail with `rs.BorrowError` and `rs.BorrowMutError` instead, a clone borrows the cell, `Ref::clone` counts another borrow of it, and a guard's `map`, `filter_map`, `try_map`, and `map_split`, an `RwLock` guard's included, make `rs.RefMap`s, each where a part it lends is, which a write through a mapped `RefMut` reaches in place, sharing the cell's borrow until the last drops; `RwLockWriteGuard::downgrade` keeps the lock as one read, and `Ref::leak` and `RefMut::leak` keep the borrow until `RefCell::undo_leak` ends it; `Cell::update` calls its function on a copy, and `RefCell::replace_with` on the value, borrowed as `borrow_mut` does, or its place where JS copies it; refused for a part of a sized type JS can't write in place, such as a binding's | | `thread_local!`, `LocalKey` | an `rs.LocalKey`, a module's value that each copy of the key is, which makes its value on first use from the `const` or the expression and never drops it, as wasm32's do; `with` calls its function on that value, `try_with` never fails, the `Cell` and `RefCell` helpers lower from std, and a `RefCell` key's `set` and `with_borrow_mut` borrow it as `borrow_mut` does | @@ -205,15 +205,18 @@ wraps silently. A panic throws `rs.Panic`, with the message native Rust panics w aborts as wasm32's does: it runs no cleanup, so what the translation held is undefined after one, as a wasm trap leaves it, and a caller that catches `rs.Panic` must not use it again. An abort without a panic, as std's for an `RwLock` locked again while held, -throws `rs.Abort`, a `Panic` with std's abort message. So `catch_unwind` only ever returns +throws `rs.Abort`, a `Panic` with std's abort message, as does what Rust leaves undefined +that the runtime catches, such as a read through a dangling pointer, worded as std's debug +checks of unsafe preconditions are, without running the hook. So `catch_unwind` only ever returns `Ok`, `resume_unwind` throws `rs.Abort` without running the hook, and `panic_any` panics with its payload if that is text, or `Box` as std's hook writes any other. 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, 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 +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 +`--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 parameter of the runtime's panicking functions, which it leaves unset, and the key each of diff --git a/ts/fixtures/lang/panics/Cargo.toml b/ts/fixtures/lang/panics/Cargo.toml index 40fe27438..b75c4c315 100644 --- a/ts/fixtures/lang/panics/Cargo.toml +++ b/ts/fixtures/lang/panics/Cargo.toml @@ -12,12 +12,13 @@ crate-type = ["lib", "cdylib"] [features] # Adds the cases that set a panic hook, which has the translation give every panic its -# location: the other shape of its output. `bytes`' panics are among them. -hook = ["dep:bytes"] +# location: the other shape of its output. `bytes`' and tokio's panics are among them. +hook = ["dep:bytes", "dep:tokio"] [dependencies] bytes = { version = "1.12.1", optional = true } edition2018 = { path = "edition2018" } +tokio = { version = "1.54.1", default-features = false, features = ["sync"], optional = true } [lints] workspace = true diff --git a/ts/fixtures/lang/panics/caller.ts b/ts/fixtures/lang/panics/caller.ts index 09caea6c5..090d62d18 100644 --- a/ts/fixtures/lang/panics/caller.ts +++ b/ts/fixtures/lang/panics/caller.ts @@ -1,8 +1,14 @@ -// What `panics`' hooks wrote, which `differential.ts` compares after each case. +// What `panics`' hooks wrote, which `differential.ts` compares after each case, and the +// inputs its cases name, which run with the generated ones. +import { ops } from "./lang.ts"; import { note as noted } from "./lib.ts"; export { ops, run } from "./lang.ts"; /** What the hooks wrote since the last call, as a JS string. */ export const note = (): string => noted().v; + +/** Each of std's sites `hooked::sited` panics at, by kind, which random inputs may miss, where a hook is set. */ +const sited = ops.get("hooked::sited"); +export const cases: Uint8Array[] = sited === undefined ? [] : Array.from({ length: 87 }, (_, kind) => Uint8Array.of(...sited, kind, 1)); diff --git a/ts/fixtures/lang/panics/hook/expected/hooked.Short.ts b/ts/fixtures/lang/panics/hook/expected/hooked.Short.ts new file mode 100644 index 000000000..7a0a34eed --- /dev/null +++ b/ts/fixtures/lang/panics/hook/expected/hooked.Short.ts @@ -0,0 +1,31 @@ +// Generated by rust2-ts. Do not edit. + +import * as rs from "./rs.ts"; + +/** + * An iterator of one item fewer than the length it says, which a zip from the back finds + * short. + */ +export interface Short { + _0: rs.u8; +} + +export function next$iter_Iterator(self: Short): rs.u8 | rs.Done { + return rs.iterFromOption(nextBack$iter_DoubleEndedIterator(self)); +} + +export function sizeHint$iter_Iterator(self: Short): [rs.usize, rs.usize | undefined] { + const len: rs.usize = rs.usizeAdd(self._0 as rs.usize, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 439, col: 19 }); + return [len, len] as [rs.usize, rs.usize | undefined]; +} + +export function nextBack$iter_DoubleEndedIterator(self: Short): rs.u8 | undefined { + const _2: rs.u8 | undefined = rs.u8CheckedSub(self._0, 1); + if (_2 !== undefined) { + self._0 = _2; + return self._0; + } + return undefined; +} + +//# sourceMappingURL=hooked.Short.ts.map diff --git a/ts/fixtures/lang/panics/hook/expected/hooked.ts b/ts/fixtures/lang/panics/hook/expected/hooked.ts index ca8228fc8..ef810dc01 100644 --- a/ts/fixtures/lang/panics/hook/expected/hooked.ts +++ b/ts/fixtures/lang/panics/hook/expected/hooked.ts @@ -11,8 +11,10 @@ import { map$1hfd4x1 as result_map$1hfd4x1, unwrapOrDefault$0t7trfe as result_un import { panicked as edition2018_panicked } from "./edition2018.ts"; import * as Failing from "./hooked.Failing.ts"; import * as Lying from "./hooked.Lying.ts"; +import * as Short from "./hooked.Short.ts"; import * as Shown from "./hooked.Shown.ts"; import { withBorrow$097wfl1 } from "./std/thread/local.ts"; +import type * as oneshot_error_RecvError from "./tokio/sync/oneshot/error.RecvError.ts"; /** * Write what `info` says: its `Display`, its payload's type and text, a `String` payload's @@ -85,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 }, 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: "/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 } }); } export function tracked(n: rs.u8, caller: rs.Location): rs.u8 { @@ -218,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 }, 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: "/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 } }); 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) { @@ -257,7 +259,7 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { const _19: rs.u16[] = [n as rs.u16]; const set: rs.BTreeSet = rs.btreeExtendKeys(rs.btreeNew(rs.cmp) as rs.BTreeSet, rs.iterSlice(_19), true, undefined, undefined, 2, true); b0: { - const k: rs.u8 = rs.u8Rem(kind, 86, { file: "fixtures/lang/panics/src/hooked.rs", line: 198, col: 11 }); + const k: rs.u8 = rs.u8Rem(kind, 87, { file: "fixtures/lang/panics/src/hooked.rs", line: 198, col: 11 }); if (k === 0) { rs.byteVecPush(out, rs.byteVecWithCapacity(rs.usizeSub(4294967295, at, { file: "fixtures/lang/panics/src/hooked.rs", line: 199, col: 48 })).length & 0xff); } else if (k === 1) { @@ -276,23 +278,23 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { rs.byteVecPush(out, rs.charEncodeUtf16(_62, rs.sliceFrom(_69)).length & 0xff); } else if (k === 7) { const _73: [rs.RangeBound, rs.RangeBound] = [{ tag: "Excluded", _0: n as rs.u16 } as rs.RangeBound, { tag: "Excluded", _0: n as rs.u16 } as rs.RangeBound]; - rs.iterExtendBytes(out, rs.iterMap(rs.btreeRange(map, _73), (_244: [rs.u16, rs.u8]): rs.u8 => { - return _244[1]; + rs.iterExtendBytes(out, rs.iterMap(rs.btreeRange(map, _73), (_250: [rs.u16, rs.u8]): rs.u8 => { + return _250[1]; }), "next"); } else if (k === 8) { const _81: rs.Range = new rs.Range(rs.u16Add(n as rs.u16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 215, col: 35 }), n as rs.u16); - rs.iterExtendBytes(out, rs.iterMap(rs.btreeRange(map, _81), (_239: [rs.u16, rs.u8]): rs.u8 => { - return _239[1]; + rs.iterExtendBytes(out, rs.iterMap(rs.btreeRange(map, _81), (_244: [rs.u16, rs.u8]): rs.u8 => { + return _244[1]; }), "next"); } else if (k === 9) { const _89: [rs.RangeBound, rs.RangeBound] = [{ tag: "Excluded", _0: n as rs.u16 } as rs.RangeBound, { tag: "Excluded", _0: n as rs.u16 } as rs.RangeBound]; - rs.iterExtendBytes(out, rs.iterMap(rs.btreeRangeKeys(set, _89), (_237: rs.u16): rs.u8 => { - return _237 & 0xff; + rs.iterExtendBytes(out, rs.iterMap(rs.btreeRangeKeys(set, _89), (_239: rs.u16): rs.u8 => { + return _239 & 0xff; }), "next"); } else if (k === 10) { const _97: rs.Range = new rs.Range(rs.u16Add(n as rs.u16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 220, col: 36 }), n as rs.u16); - rs.iterExtendBytes(out, rs.iterMap(rs.btreeRangeKeys(set, _97), (_232: rs.u16): rs.u8 => { - return _232 & 0xff; + rs.iterExtendBytes(out, rs.iterMap(rs.btreeRangeKeys(set, _97), (_237: rs.u16): rs.u8 => { + return _237 & 0xff; }), "next"); } else if (k === 11) { rs.dequeInsert(rs.dequeClone(deque), rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 221, col: 36 }), n); @@ -398,8 +400,8 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { undefined; })); })(EXCLUSIVE.get()); - withBorrow$097wfl1(EXCLUSIVE, (_217: rs.u8): undefined => { - rs.byteVecPush(out, _217); + withBorrow$097wfl1(EXCLUSIVE, (_225: rs.u8): undefined => { + rs.byteVecPush(out, _225); }); } else if (k === 35) { const _277: rs.ByteVec = rs.byteVecFrom(rs.byteVecView(v)); @@ -443,13 +445,13 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { } else if (k === 47) { const _365: rs.ByteVec = rs.byteVecFrom(rs.byteVecView(v)); const _367: rs.RangeFrom = new rs.RangeFrom(rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 306, col: 47 }), rs.usizeStep); - rs.iterExtendBytes(out, rs.byteVecExtractIf(_365, _367, (_210: rs.Place): boolean => { + rs.iterExtendBytes(out, rs.byteVecExtractIf(_365, _367, (_217: rs.Place): boolean => { return true; }, { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/extract_if.rs", line: 43, col: 36 }), "next"); } else if (k === 48) { const _374: rs.Vec = rs.vecFrom([n as rs.u16]); const _377: { end: rs.usize } = { end: rs.usizeAdd(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 307, col: 56 }) }; - rs.byteVecPush(out, rs.ownedCount(rs.vecExtractIfMut(_374, _377, (_29: rs.Place): boolean => { + rs.byteVecPush(out, rs.ownedCount(rs.vecExtractIfMut(_374, _377, (_210: rs.Place): boolean => { return true; }, { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/alloc/src/vec/extract_if.rs", line: 43, col: 36 }), undefined, undefined) & 0xff); } else if (k === 49) { @@ -513,8 +515,8 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { } else if (k === 78) { rs.vecInsert(rs.vecFrom([n as rs.u16]), rs.usizeAdd(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 348, col: 41 }), 0, { file: "fixtures/lang/panics/src/hooked.rs", line: 348, col: 34 }); } else if (k === 79) { - rs.iterExtendBytes(out, rs.iterMap(rs.iterSlice(rs.vecSplitOff(rs.vecFrom([n as rs.u16]), rs.usizeAdd(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 349, col: 55 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 349, col: 45 }).items), (_2: rs.u16): rs.u8 => { - return _2 & 0xff; + rs.iterExtendBytes(out, rs.iterMap(rs.iterSlice(rs.vecSplitOff(rs.vecFrom([n as rs.u16]), rs.usizeAdd(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 349, col: 55 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 349, col: 45 }).items), (_29: rs.u16): rs.u8 => { + return _29 & 0xff; }), undefined, true); } else if (k === 80) { const _550: rs.ByteSlice = rs.byteVecSlice(rs.byteVecFrom(rs.byteVecView(v))); @@ -530,6 +532,8 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { } else if (k === 84) { const _585: Failing.Failing = {}; rs.byteVecExtendFromSlice(out, rs.stringAsBytes(rs.fmtToString((f: rs.Formatter) => Failing.fmt$fmt_Display(_585, f)).v)); + } else if (k === 85) { + rs.byteVecPush(out, rs.iterFrom({ _0: n }, Lying.next$iter_Iterator, undefined, { hint: Lying.sizeHint$iter_Iterator }).len() & 0xff); } else { if (53 <= k) { if (k <= 56) { @@ -543,7 +547,11 @@ export function sited(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { break b0; } } - rs.byteVecPush(out, rs.iterFrom({ _0: n }, Lying.next$iter_Iterator, undefined, { hint: Lying.sizeHint$iter_Iterator }).len() & 0xff); + const _593: Short.Short = { _0: rs.u8Rem(n, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 356, col: 31 }) }; + const _596: rs.Range = new rs.Range(0, rs.u8Add(rs.u8Rem(n, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 356, col: 45 }), 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 356, col: 45 })); + rs.iterExtendBytes(out, rs.iterMap(rs.iterRev(rs.iterZip(rs.iterFrom(_593, Short.next$iter_Iterator, undefined, { hint: Short.sizeHint$iter_Iterator, back: (it: Short.Short) => rs.iterFromOption(Short.nextBack$iter_DoubleEndedIterator(it)) }), _596)), (_2: [rs.u8, rs.u8]): rs.u8 => { + return _2[0] ^ _2[1]; + }), "next"); } } } @@ -557,16 +565,16 @@ export function joined(kind: rs.u8, n: rs.u8, out: rs.ByteVec): void { let joined!: rs.ByteVec; const big: rs.ByteVec = rs.byteVecOf(n, 1 << 16); const refs: (a0: rs.usize) => rs.Vec = (count: rs.usize): rs.Vec => { - return rs.vecFromElem(rs.byteSliceRange(rs.byteVecSlice(big), 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 373, col: 40 }), count, undefined); + return rs.vecFromElem(rs.byteSliceRange(rs.byteVecSlice(big), 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 374, col: 40 }), count, undefined); }; if (kind === 0) { - joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 375, col: 19 })).items)); + joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 376, col: 19 })).items)); } else if (kind === 1) { - joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 376, col: 19 })).items), rs.byteSliceFrom(Uint8Array.of(n))); + joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 16, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 377, col: 19 })).items), rs.byteSliceFrom(Uint8Array.of(n))); } else if (kind === 2) { - joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 15, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 377, col: 19 })).items)); + joined = rs.byteSlicesJoin(rs.sliceFrom(refs(rs.usizeAdd(1 << 15, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 378, col: 19 })).items)); } else { - joined = rs.iterToByteVec(rs.iterMap(rs.iterSlice(rs.slicesJoin(rs.sliceFrom(rs.vecFromElem(rs.sliceFrom(rs.vecFromElem(n as rs.u16, 1 << 16, undefined).items), rs.usizeAdd(1 << 14, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 380, col: 42 }), undefined).items), 2, rs.sliceFrom([1])).items), (_2: rs.u16): rs.u8 => { + joined = rs.iterToByteVec(rs.iterMap(rs.iterSlice(rs.slicesJoin(rs.sliceFrom(rs.vecFromElem(rs.sliceFrom(rs.vecFromElem(n as rs.u16, 1 << 16, undefined).items), rs.usizeAdd(1 << 14, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 381, col: 42 }), undefined).items), 2, rs.sliceFrom([1])).items), (_2: rs.u16): rs.u8 => { return _2 & 0xff; }), undefined, true); } @@ -589,10 +597,10 @@ export function compared(kind: rs.u8, n: rs.u8): rs.u8 { const _5: [rs.RefCell, rs.RefCell] = [new rs.RefCell(n), new rs.RefCell(rs.u8WrappingAdd(n, 1))]; const a: rs.RefCell = _5[0]; const b: rs.RefCell = _5[1]; - if (!(rs.u8Rem(n, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 392, col: 20 }) === 0)) { - _held = rs.refCellBorrowMut(b, { file: "fixtures/lang/panics/src/hooked.rs", line: 392, col: 59 }); + if (!(rs.u8Rem(n, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 393, col: 20 }) === 0)) { + _held = rs.refCellBorrowMut(b, { file: "fixtures/lang/panics/src/hooked.rs", line: 393, col: 59 }); } else { - _held = rs.refCellBorrowMut(a, { file: "fixtures/lang/panics/src/hooked.rs", line: 392, col: 35 }); + _held = rs.refCellBorrowMut(a, { file: "fixtures/lang/panics/src/hooked.rs", line: 393, col: 35 }); } if (kind === 0) { _0 = rs.refCellBy(rs.same, { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell.rs", line: 1482, col: 15 }, { file: "/rustc/7df81381d027710708209f36b98d11b1c88f8d2e/library/core/src/cell.rs", line: 1482, col: 34 })(a, b) ? 1 : 0; @@ -639,11 +647,11 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { const at: rs.usize = n as rs.usize; const whole: rs.ByteSlice = rs.bytesFromVec(rs.byteVecOf(n, 4)); b0: { - const k: rs.u8 = rs.u8Rem(kind, 33, { file: "fixtures/lang/panics/src/hooked.rs", line: 434, col: 24 }); + const k: rs.u8 = rs.u8Rem(kind, 33, { file: "fixtures/lang/panics/src/hooked.rs", line: 461, col: 24 }); if (0 <= k) { if (k <= 1) { rs.setHook((info: rs.PanicHookInfo): undefined => { - const at2: rs.Location = rs.optionUnwrap(info.location, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 436, col: 38 }); + const at2: rs.Location = rs.optionUnwrap(info.location, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 463, col: 38 }); const _10: string = at2.file; const _126: rs.u32 = at2.line; const _14: rs.u32 = at2.col; @@ -652,16 +660,16 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { rs.localKeyWithBorrowMut(NOTE, (note: rs.String): undefined => { 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: 439, 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 }, 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 } }); + 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 } }); 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: 443, col: 34 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 443, col: 30 })); + 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 })); held = rs.bytesSliceRef(_22, subset); rs.bytesDrop(_22); } else { const _32: rs.ByteSlice = rs.bytesSlice(whole, 0, 1); - const _35: rs.ByteSlice = rs.byteSliceRange(whole, 0, rs.usizeAdd(2, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 444, col: 58 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 444, col: 54 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 444, col: 51 }); + const _35: rs.ByteSlice = rs.byteSliceRange(whole, 0, rs.usizeAdd(2, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 471, col: 58 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 471, col: 54 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 471, col: 51 }); held = rs.bytesSliceRef(_32, _35); rs.bytesDrop(_32); } @@ -673,38 +681,38 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { } } hook(); - const shared: rs.BytesMut = rs.bytesMutFrom(rs.byteSliceRange(rs.byteSliceFrom(rs.bytes(8).fill(n)), 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 450, col: 44 })); - const _52: rs.u8 = rs.u8Rem(kind, 33, { file: "fixtures/lang/panics/src/hooked.rs", line: 451, col: 11 }); + const shared: rs.BytesMut = rs.bytesMutFrom(rs.byteSliceRange(rs.byteSliceFrom(rs.bytes(8).fill(n)), 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 477, col: 44 })); + const _52: rs.u8 = rs.u8Rem(kind, 33, { file: "fixtures/lang/panics/src/hooked.rs", line: 478, col: 11 }); if (_52 === 2) { - const _56: rs.ByteSlice = rs.bytesSlice(whole, rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 452, col: 49 }), 2); + const _56: rs.ByteSlice = rs.bytesSlice(whole, rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 479, col: 49 }), 2); rs.byteVecExtendFromSlice(out, _56); rs.bytesDrop(_56); } else if (_52 === 3) { - const _63: rs.ByteSlice = rs.bytesSlice(whole, 0, rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 453, col: 51 })); + const _63: rs.ByteSlice = rs.bytesSlice(whole, 0, rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 480, col: 51 })); rs.byteVecExtendFromSlice(out, _63); rs.bytesDrop(_63); } else if (_52 === 4) { - const _72: rs.RangeInclusive = new rs.RangeInclusive(rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 454, col: 62 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 454, col: 49 }), 4294967295, rs.usizeStep); + const _72: rs.RangeInclusive = new rs.RangeInclusive(rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 481, col: 62 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 481, col: 49 }), 4294967295, rs.usizeStep); const _70: rs.ByteSlice = rs.bytesSliceInclusive(whole, _72); rs.byteVecExtendFromSlice(out, _70); rs.bytesDrop(_70); } else if (_52 === 5) { let _81: rs.ByteSlice = rs.bytesClone(whole); - const _83: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 455, col: 60 }); + const _83: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 482, col: 60 }); const _79: rs.ByteSlice = rs.bytesSplitTo(rs.place(() => _81, (value9) => _81 = value9), _83); rs.byteVecExtendFromSlice(out, _79); rs.bytesDrop(_79); rs.bytesDrop(_81); } else if (_52 === 6) { let _89: rs.ByteSlice = rs.bytesClone(whole); - const _91: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 456, col: 61 }); + const _91: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 483, col: 61 }); const _87: rs.ByteSlice = rs.bytesSplitOff(rs.place(() => _89, (value8) => _89 = value8), _91); rs.byteVecExtendFromSlice(out, _87); rs.bytesDrop(_87); rs.bytesDrop(_89); } else if (_52 === 7) { let _94: rs.ByteSlice = rs.bytesClone(whole); - const _96: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 457, col: 36 }); + const _96: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 484, col: 36 }); rs.bytesAdvance(rs.place(() => _94, (value7) => _94 = value7), _96); rs.bytesDrop(_94); } else if (_52 === 8) { @@ -713,12 +721,12 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { rs.bytesDrop(_101); } else if (_52 === 9) { let _107: rs.ByteSlice = rs.bytesClone(whole); - const _109: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 459, col: 50 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 459, col: 46 }); + const _109: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 486, col: 50 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 486, col: 46 }); rs.byteVecPush(out, rs.u64Low(rs.u64FromBeBytes(rs.bytesReadInt(rs.place(() => _107, (value5) => _107 = value5), 8, _109, false, false))) & 0xff); rs.bytesDrop(_107); } else if (_52 === 10) { - let _114: rs.ByteSlice = rs.byteSliceRange(data, 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 460, col: 21 }); - const _116: rs.usize = rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 460, col: 35 }); + let _114: rs.ByteSlice = rs.byteSliceRange(data, 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 487, col: 21 }); + const _116: rs.usize = rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 487, col: 35 }); rs.byteSliceAdvance(rs.place(() => _114, (value4) => _114 = value4), _116); } else if (_52 === 11) { let _120: rs.ByteSlice = rs.bytesClone(whole); @@ -727,75 +735,75 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { rs.bytesDrop(_120); } else if (_52 === 12) { let _129: rs.ByteSlice = rs.bytesClone(whole); - const _131: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 462, col: 66 }); + const _131: rs.usize = rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 489, col: 66 }); const _127: rs.ByteSlice = rs.bytesSplitTo(rs.place(() => _129, (value2) => _129 = value2), _131); rs.byteVecExtendFromSlice(out, _127); rs.bytesDrop(_127); rs.bytesDrop(_129); } else if (_52 === 13) { - let _137: rs.ByteSlice = rs.byteSliceRange(data, 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 463, col: 44 }); - const _139: rs.usize = rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 463, col: 64 }); + let _137: rs.ByteSlice = rs.byteSliceRange(data, 0, undefined, { file: "fixtures/lang/panics/src/hooked.rs", line: 490, col: 44 }); + const _139: rs.usize = rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 490, col: 64 }); const _135: rs.ByteSlice = rs.byteSliceCopyToBytes(rs.place(() => _137, (value) => _137 = value), _139); rs.byteVecExtendFromSlice(out, _135); rs.bytesDrop(_135); } else if (_52 === 14) { const _146: rs.BytesMut = rs.bytesMutFrom(data); - const _144: rs.BytesMut = rs.bytesMutSplitTo(_146, rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 464, col: 68 })); + const _144: rs.BytesMut = rs.bytesMutSplitTo(_146, rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 491, col: 68 })); rs.byteVecExtendFromSlice(out, rs.bytesMutView(_144)); _144[Symbol.dispose](); _146[Symbol.dispose](); } else if (_52 === 15) { const _154: rs.BytesMut = rs.bytesMutWithCapacity(4); - const _152: rs.BytesMut = rs.bytesMutSplitOff(_154, rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 465, col: 75 })); + const _152: rs.BytesMut = rs.bytesMutSplitOff(_154, rs.usizeAdd(at, 5, { file: "fixtures/lang/panics/src/hooked.rs", line: 492, col: 75 })); rs.byteVecExtendFromSlice(out, rs.bytesMutView(_152)); _152[Symbol.dispose](); _154[Symbol.dispose](); } else if (_52 === 16) { - const b: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 467, col: 49 })); - rs.bytesMutSetLen(b, rs.usizeAdd(b.cap, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 469, col: 32 })); + const b: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 494, col: 49 })); + rs.bytesMutSetLen(b, rs.usizeAdd(b.cap, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 496, col: 32 })); rs.byteVecPush(out, b.length & 0xff); b[Symbol.dispose](); } else if (_52 === 17) { - const b2: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 473, col: 49 })); - rs.bytesMutAdvanceMut(b2, rs.usizeAdd(b2.cap, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 475, col: 36 })); + const b2: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 500, col: 49 })); + rs.bytesMutAdvanceMut(b2, rs.usizeAdd(b2.cap, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 502, col: 36 })); rs.byteVecPush(out, b2.length & 0xff); b2[Symbol.dispose](); } else if (_52 === 18) { - const v: rs.ByteVec = rs.byteVecWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 479, col: 50 })); - rs.byteVecAdvanceMut(v, rs.usizeAdd(v.data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 481, col: 36 })); + const v: rs.ByteVec = rs.byteVecWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 506, col: 50 })); + rs.byteVecAdvanceMut(v, rs.usizeAdd(v.data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 508, col: 36 })); rs.byteVecPush(out, v.length & 0xff); } else if (_52 === 19) { const _197: rs.BytesMut = rs.bytesMutFrom(data); - rs.bytesMutAdvance(_197, rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 484, col: 44 })); + rs.bytesMutAdvance(_197, rs.usizeAdd(data.length, 1, { file: "fixtures/lang/panics/src/hooked.rs", line: 511, col: 44 })); _197[Symbol.dispose](); } else if (_52 === 20) { - const _204: rs.BytesMut = rs.bytesMutFrom(rs.byteSliceRange(data, 0, rs.min(data.length, 3), { file: "fixtures/lang/panics/src/hooked.rs", line: 485, col: 44 })); + const _204: rs.BytesMut = rs.bytesMutFrom(rs.byteSliceRange(data, 0, rs.min(data.length, 3), { file: "fixtures/lang/panics/src/hooked.rs", line: 512, col: 44 })); rs.byteVecPush(out, (rs.bytesMutReadWord(_204, 4, false) as rs.u32) & 0xff); _204[Symbol.dispose](); } else if (_52 === 21) { - const _212: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeSub(4294967295, at, { file: "fixtures/lang/panics/src/hooked.rs", line: 486, col: 48 })); + const _212: rs.BytesMut = rs.bytesMutWithCapacity(rs.usizeSub(4294967295, at, { file: "fixtures/lang/panics/src/hooked.rs", line: 513, col: 48 })); rs.byteVecPush(out, _212.cap & 0xff); _212[Symbol.dispose](); } else if (_52 === 22) { const _tail: rs.BytesMut = rs.bytesMutSplitOff(shared, 4); - rs.bytesMutReserve(shared, rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 490, col: 41 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 490, col: 28 })); + rs.bytesMutReserve(shared, rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 517, col: 41 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 517, col: 28 })); _tail[Symbol.dispose](); } else if (_52 === 23) { rs.bytesMutSplitTo(shared, 4)[Symbol.dispose](); - rs.bytesMutReserve(shared, rs.usizeSub(4294967295 - 4, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 495, col: 45 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 495, col: 28 })); + rs.bytesMutReserve(shared, rs.usizeSub(4294967295 - 4, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 522, col: 45 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 522, col: 28 })); } else if (_52 === 24) { const _235: rs.u64 = n as rs.u64; - const _236: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 497, col: 49 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 497, col: 45 }); + const _236: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 524, col: 49 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 524, col: 45 }); rs.bytesMutPutInt(shared, rs.u64ToBeBytes(_235), _236, false); } else if (_52 === 25) { const _240: rs.i64 = n as rs.i64; - const _241: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 498, col: 45 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 498, col: 41 }); + const _241: rs.usize = rs.usizeAdd(9, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 525, col: 45 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 525, col: 41 }); rs.byteVecPutInt(out, rs.i64ToBeBytes(_240), _241, false); } else if (_52 === 26) { - rs.byteVecPutFill(out, n, rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 499, col: 53 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 499, col: 40 })); + rs.byteVecPutFill(out, n, rs.usizeSub(4294967295, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 526, col: 53 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 526, col: 40 })); } else if (_52 === 27) { const _253: Take.Take = buf_impl_take$bytes_Buf_bytes_Bytes(rs.bytesClone(whole), 2); - const _251: rs.ByteSlice = Take.copyToBytes$bytes_Buf_bytes_Bytes(_253, rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 500, col: 74 })); + const _251: rs.ByteSlice = Take.copyToBytes$bytes_Buf_bytes_Bytes(_253, rs.usizeAdd(at, 3, { file: "fixtures/lang/panics/src/hooked.rs", line: 527, col: 74 })); rs.byteVecExtendFromSlice(out, _251); rs.bytesDrop(_251); drop$bytes_buf_Take_bytes_Bytes(_253); @@ -805,15 +813,15 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { drop$bytes_buf_Take_bytes_Bytes(_261); } else if (_52 === 29) { const chunk: rs.ByteSlice = rs.bytesMutChunkMut(shared); - UninitSlice.writeByte(chunk, rs.usizeAdd(UninitSlice.len(chunk), rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 505, col: 44 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 505, col: 30 }), n); + UninitSlice.writeByte(chunk, rs.usizeAdd(UninitSlice.len(chunk), rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 532, col: 44 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 532, col: 30 }), n); } else if (_52 === 30) { - UninitSlice.writeByte(UninitSlice.indexMut$ops_IndexMut_ops_RangeFrom_usize(rs.byteVecChunkMut(rs.byteVecWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 507, col: 40 }))), new rs.RangeFrom(rs.usizeAdd(65, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 507, col: 65 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 507, col: 60 }), rs.usizeStep), { file: "fixtures/lang/panics/src/hooked.rs", line: 507, col: 59 }), 0, n); + UninitSlice.writeByte(UninitSlice.indexMut$ops_IndexMut_ops_RangeFrom_usize(rs.byteVecChunkMut(rs.byteVecWithCapacity(rs.usizeRem(at, 4, { file: "fixtures/lang/panics/src/hooked.rs", line: 534, col: 40 }))), new rs.RangeFrom(rs.usizeAdd(65, rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 534, col: 65 }), { file: "fixtures/lang/panics/src/hooked.rs", line: 534, col: 60 }), rs.usizeStep), { file: "fixtures/lang/panics/src/hooked.rs", line: 534, col: 59 }), 0, n); } else if (_52 === 31) { const _287: rs.BytesMut = rs.bytesMutWithCapacity(0); - UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(rs.bytesMutChunkMut(_287), { end: rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 508, col: 45 }) }, { file: "fixtures/lang/panics/src/hooked.rs", line: 508, col: 42 }), rs.byteSliceFrom(rs.bytes(3).fill(n))); + UninitSlice.copyFromSlice(UninitSlice.indexMut$ops_IndexMut_ops_RangeTo_usize(rs.bytesMutChunkMut(_287), { end: rs.usizeRem(at, 2, { file: "fixtures/lang/panics/src/hooked.rs", line: 535, col: 45 }) }, { file: "fixtures/lang/panics/src/hooked.rs", line: 535, col: 42 }), rs.byteSliceFrom(rs.bytes(3).fill(n))); _287[Symbol.dispose](); } else { - const _297: rs.BytesMut = rs.bytesMutZeroed(rs.usizeSub(4294967295, at, { file: "fixtures/lang/panics/src/hooked.rs", line: 509, col: 40 })); + const _297: rs.BytesMut = rs.bytesMutZeroed(rs.usizeSub(4294967295, at, { file: "fixtures/lang/panics/src/hooked.rs", line: 536, col: 40 })); rs.byteVecPush(out, _297.length & 0xff); _297[Symbol.dispose](); } @@ -829,7 +837,7 @@ export function stock(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { */ export function edition2018Panicked(kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { b0: { - if (!(rs.u8Rem(kind, 7, { file: "fixtures/lang/panics/src/hooked.rs", line: 517, col: 8 }) !== 6)) { + if (!(rs.u8Rem(kind, 7, { file: "fixtures/lang/panics/src/hooked.rs", line: 544, col: 8 }) !== 6)) { if (!(option_unwrapOr$1fr498u(rs.byteSliceFirst(data), 0) > 200)) { break b0; } @@ -839,4 +847,29 @@ export function edition2018Panicked(kind: rs.u8, data: rs.ByteSlice, out: rs.Byt edition2018_panicked(kind, data, out); } +/** + * A panic of tokio's own code in what translation maps, with a hook set: a oneshot + * receiver polled again once it gave its value. + */ +export function tokioStock(_kind: rs.u8, data: rs.ByteSlice, out: rs.ByteVec): void { + const n: rs.u8 = option_unwrapOr$1fr498u(rs.byteSliceFirst(data), 0); + hook(); + const _10: [rs.OneshotSender, rs.OneshotReceiver] = rs.oneshotChannel(); + const tx: rs.OneshotSender = _10[0]; + const rx: rs.OneshotReceiver = _10[1]; + rs.resultUnwrap(rs.oneshotSend(tx, n), rs.u8Debug, { file: "fixtures/lang/panics/src/hooked.rs", line: 556, col: 16 }); + const cx: rs.Context = rs.NOOP_WAKER; + let iterStart: rs.i32 = 0; + const iterEnd: rs.i32 = 2; + while (iterStart++ < iterEnd) { + const _21: rs.Poll> = rs.oneshotPoll(rx, cx, { _0: undefined }, { file: "tokio/channels/oneshot.rs", line: 1291, col: 13 }); + if (_21 !== rs.Pending) { + if (_21.ok) { + rs.byteVecPush(out, _21.value); + } + } + } + rx[Symbol.dispose](); +} + //# sourceMappingURL=hooked.ts.map diff --git a/ts/fixtures/lang/panics/hook/expected/lib.ts b/ts/fixtures/lang/panics/hook/expected/lib.ts index e8d9f0201..be1a7e2f0 100644 --- a/ts/fixtures/lang/panics/hook/expected/lib.ts +++ b/ts/fixtures/lang/panics/hook/expected/lib.ts @@ -4,7 +4,7 @@ import * as rs from "./rs.ts"; import type * as Take from "./bytes/buf/take.Take.ts"; import type * as Any from "./core/any.Any.ts"; import { panicked as edition2018_panicked } from "./edition2018.ts"; -import { panicked as hooked_panicked, aborted, sited, stock, edition2018Panicked } from "./hooked.ts"; +import { panicked as hooked_panicked, aborted, sited, stock, edition2018Panicked, tokioStock } from "./hooked.ts"; import { via$located_Tracked_u8, at$located_Tracked_u8, called as located_called, read, panicked as located_panicked } from "./located.ts"; import * as Inherits from "./located.Inherits.ts"; import * as Own from "./located.Own.ts"; @@ -158,7 +158,7 @@ export class ofPlace$u8 { * their count, so a case added at the end moves no other. */ export function cases(): rs.Vec<[string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]> { - return rs.iterToVec(rs.iterChain(rs.vecIntoIter(rs.vecFrom([["panics::wrapped", wrapped as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::called", panics_called as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::awaited", awaited as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::raised", raised as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::called", located_called as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::read", read as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::panicked", located_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["edition2018::panicked", edition2018_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]])), rs.iterSlice([["hooked::panicked", hooked_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::aborted", aborted as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::sited", sited as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::stock", stock as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::edition2018_panicked", edition2018Panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]])), undefined, 12, true); + return rs.iterToVec(rs.iterChain(rs.vecIntoIter(rs.vecFrom([["panics::wrapped", wrapped as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::called", panics_called as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::awaited", awaited as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["panics::raised", raised as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::called", located_called as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::read", read as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["located::panicked", located_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["edition2018::panicked", edition2018_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]])), rs.iterSlice([["hooked::panicked", hooked_panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::aborted", aborted as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::sited", sited as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::stock", stock as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::edition2018_panicked", edition2018Panicked as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined], ["hooked::tokio_stock", tokioStock as (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined] as [string, (a0: rs.u8, a1: rs.ByteSlice, a2: rs.ByteVec) => undefined]])), undefined, 12, true); } export const NOTE: rs.LocalKey> = /* @__PURE__ */ new rs.LocalKey(NOTE$init, false); @@ -171,7 +171,7 @@ export function NOTE$init(): rs.RefCell { export function note(): rs.String { return rs.localKeyWithBorrowMut(NOTE, (a0: rs.String): rs.String => { return rs.replaceIn(a0, rs.stringNew()); - }, { file: "fixtures/lang/panics/src/lib.rs", line: 55, col: 5 }); + }, { file: "fixtures/lang/panics/src/lib.rs", line: 56, col: 5 }); } //# sourceMappingURL=lib.ts.map diff --git a/ts/fixtures/lang/panics/hook/expected/tokio/sync/oneshot/error.RecvError.ts b/ts/fixtures/lang/panics/hook/expected/tokio/sync/oneshot/error.RecvError.ts new file mode 100644 index 000000000..08add3b0c --- /dev/null +++ b/ts/fixtures/lang/panics/hook/expected/tokio/sync/oneshot/error.RecvError.ts @@ -0,0 +1,12 @@ +// Generated by rust2-ts. Do not edit. + +/** + * Error returned by the `Future` implementation for `Receiver`. + * + * This error is returned by the receiver when the sender is dropped without sending. + */ +export interface RecvError { + _0: undefined; +} + +//# sourceMappingURL=error.RecvError.ts.map diff --git a/ts/fixtures/lang/panics/src/hooked.rs b/ts/fixtures/lang/panics/src/hooked.rs index bed712bb9..ddc1b29f3 100644 --- a/ts/fixtures/lang/panics/src/hooked.rs +++ b/ts/fixtures/lang/panics/src/hooked.rs @@ -195,7 +195,7 @@ pub fn sited(kind: u8, data: &[u8], out: &mut Vec) { let deque = VecDeque::from(v.clone()); let map = BTreeMap::from([(u16::from(n), n)]); let set = BTreeSet::from([u16::from(n)]); - match kind % 86 { + match kind % 87 { 0 => out.push(Vec::::with_capacity(usize::MAX - at).len() as u8), 1 => v.clone().rotate_right(at + 3), 2 => out.push(n.clamp(n.max(1), n.max(1) - 1)), @@ -352,7 +352,8 @@ pub fn sited(kind: u8, data: &[u8], out: &mut Vec) { 82 => out.push((-i32::from(n)).clamp(0, -1) as u8), 83 => out.extend_from_slice(format!("{Failing}").as_bytes()), 84 => out.extend_from_slice(Failing.to_string().as_bytes()), - _ => out.push(Lying(n).len() as u8), + 85 => out.push(Lying(n).len() as u8), + _ => out.extend(Short(n % 4).zip(0..n % 4 + 1).rev().map(|(a, b)| a ^ b)), } } @@ -423,6 +424,32 @@ impl Iterator for Lying { impl ExactSizeIterator for Lying {} +/// An iterator of one item fewer than the length it says, which a zip from the back finds +/// short. +struct Short(u8); + +impl Iterator for Short { + type Item = u8; + + fn next(&mut self) -> Option { + self.next_back() + } + + fn size_hint(&self) -> (usize, Option) { + let len = usize::from(self.0) + 1; + (len, Some(len)) + } +} + +impl DoubleEndedIterator for Short { + fn next_back(&mut self) -> Option { + self.0 = self.0.checked_sub(1)?; + Some(self.0) + } +} + +impl ExactSizeIterator for Short {} + /// One panic of `bytes`' own code, by `kind`, with a hook set: each where the native build /// names it, in the source of the `bytes` it builds. pub fn stock(kind: u8, data: &[u8], out: &mut Vec) { @@ -519,3 +546,18 @@ pub fn edition2018_panicked(kind: u8, data: &[u8], out: &mut Vec) { } edition2018::panicked(kind, data, out); } + +/// A panic of tokio's own code in what translation maps, with a hook set: a oneshot +/// receiver polled again once it gave its value. +pub fn tokio_stock(_kind: u8, data: &[u8], out: &mut Vec) { + let n = data.first().copied().unwrap_or(0); + hook(); + let (tx, mut rx) = tokio::sync::oneshot::channel(); + tx.send(n).unwrap(); + let mut cx = Context::from_waker(Waker::noop()); + for _ in 0..2 { + if let Poll::Ready(Ok(n)) = Pin::new(&mut rx).poll(&mut cx) { + out.push(n); + } + } +} diff --git a/ts/fixtures/lang/panics/src/lib.rs b/ts/fixtures/lang/panics/src/lib.rs index 7d346af88..7deb5b7e9 100644 --- a/ts/fixtures/lang/panics/src/lib.rs +++ b/ts/fixtures/lang/panics/src/lib.rs @@ -40,6 +40,7 @@ fn cases() -> Vec<(&'static str, Case)> { ("hooked::sited", hooked::sited), ("hooked::stock", hooked::stock), ("hooked::edition2018_panicked", hooked::edition2018_panicked), + ("hooked::tokio_stock", hooked::tokio_stock), ]) .collect(); cases diff --git a/ts/fixtures/lang/pointers/expected/pointers.ts b/ts/fixtures/lang/pointers/expected/pointers.ts index 748742a41..096ff2931 100644 --- a/ts/fixtures/lang/pointers/expected/pointers.ts +++ b/ts/fixtures/lang/pointers/expected/pointers.ts @@ -2742,16 +2742,12 @@ export function flagWaker(flag: rs.Arc>): rs.Waker { return rs.wakerFromRaw({ data: rs.arcErase(rs.arcRaw(arc, rs.arcPlace(arc), "Arc"), "std::sync::atomic::Atomic", 1), vtable: FLAG }); } -/** `p`, a pointer this body doesn't show the source of, erased. */ -export function eraseFlag(p: rs.Place>): rs.Place { - return rs.arcErase(p, "std::sync::atomic::Atomic", 1); -} - /** * The raw pointers of `Arc`s and `Rc`s of values JS copies: a number's remade from a * shared reference to its value, counted up and down, cloned, and taken back through it, * and an `Arc`'s cast to `*const ()` and back, as a waker's data, which its - * vtable counts, wakes, and drops. Each compares as the pointer `as_ptr` gives. + * vtable counts, wakes, and drops. Each compares as the pointer `as_ptr` gives, and a + * null one, made here or a constant, as null, through casts to and from `MaybeUninit`. */ export function rawPlaces(data: rs.ByteSlice, out: rs.ByteVec): void { const num: rs.Arc = new rs.Arc(data.length as rs.u32); @@ -2819,23 +2815,31 @@ export function rawPlaces(data: rs.ByteSlice, out: rs.ByteVec): void { const arc2 = rc; const _116: boolean = _117 === rs.arcErase(rs.arcRaw(arc2, rs.arcPlace(arc2), "Rc"), "u16", 2); const arc3 = flag; - rs.iterExtendBytes(out, rs.iterSlice(rs.bytesMap([_111, _116, eraseFlag(rs.arcRaw(arc3, rs.arcPlace(arc3), "Arc")) === wakers.items[rs.idx(wakers.items, 0)].data as rs.Place, rs.arcErase(rs.arcRaw(flag, rs.arcPlace(flag), "Arc"), "std::sync::atomic::Atomic", 1) === wakers.items[rs.idx(wakers.items, 0)].data as rs.Place], (a0: boolean): rs.u8 => { + const _121: boolean = rs.arcErase(rs.arcRaw(arc3, rs.arcPlace(arc3), "Arc"), "std::sync::atomic::Atomic", 1) === wakers.items[rs.idx(wakers.items, 0)].data as rs.Place; + const _128: boolean = rs.arcErase(rs.arcRaw(flag, rs.arcPlace(flag), "Arc"), "std::sync::atomic::Atomic", 1) === wakers.items[rs.idx(wakers.items, 0)].data as rs.Place; + const _136: boolean = rs.arcErase(rs.NULL, "u32", 4) === rs.NULL; + const _140: boolean = rs.arcErase(rs.NULL, "u32", 4) === rs.NULL; + const _143: boolean = rs.arcErase(rs.NULL, "u32", 4) === rs.NULL; + const arc4 = num; + const _149: rs.Place = rs.arcErase(rs.arcRaw(arc4, rs.arcPlace(arc4), "Arc"), "u32", 4); + const arc5 = num; + rs.iterExtendBytes(out, rs.iterSlice(rs.bytesMap([_111, _116, _121, _128, _136, _140, _143, _149 === rs.arcErase(rs.arcRaw(arc5, rs.arcPlace(arc5), "Arc"), "u32", 4)], (a0: boolean): rs.u8 => { return a0 ? 1 : 0; })), undefined, true); } rs.dropVec(wakers); rs.byteVecPush(out, flag.strong & 0xff); while (num.strong > 1) { - const arc4 = num; - rs.arcFromRaw(rs.arcRaw(arc4, rs.arcPlace(arc4), "Arc"), "Arc")[Symbol.dispose](); + const arc6 = num; + rs.arcFromRaw(rs.arcRaw(arc6, rs.arcPlace(arc6), "Arc"), "Arc")[Symbol.dispose](); } while (rc.strong > 1) { rs.arcFromRaw(rs.arcRaw(rc, rs.arcPlace(rc), "Rc"), "Rc")[Symbol.dispose](); } rs.iterExtendBytes(out, rs.iterSlice(Uint8Array.of(num.strong & 0xff, rc.strong & 0xff, rc.value & 0xff)), undefined, true); - const _169: [Shelf.Shelf, Shelf.Shelf] = [new Shelf.Shelf(new rs.Arc(1)), new Shelf.Shelf(new rs.Arc(2))]; - const first: Shelf.Shelf = _169[0]; - const second: Shelf.Shelf = _169[1]; + const _189: [Shelf.Shelf, Shelf.Shelf] = [new Shelf.Shelf(new rs.Arc(1)), new Shelf.Shelf(new rs.Arc(2))]; + const first: Shelf.Shelf = _189[0]; + const second: Shelf.Shelf = _189[1]; let shelf: Shelf.Shelf = first; const value: rs.u32 = shelf._0.value; if (isSomeAnd$1s2u5lz(rs.byteSliceFirst(data), (b: rs.u8): boolean => { diff --git a/ts/fixtures/lang/pointers/src/pointers.rs b/ts/fixtures/lang/pointers/src/pointers.rs index 56d259cd0..637f7ec4a 100644 --- a/ts/fixtures/lang/pointers/src/pointers.rs +++ b/ts/fixtures/lang/pointers/src/pointers.rs @@ -2183,15 +2183,14 @@ fn flag_waker(flag: &Arc) -> Waker { unsafe { Waker::from_raw(RawWaker::new(data, &FLAG)) } } -/// `p`, a pointer this body doesn't show the source of, erased. -fn erase_flag(p: *const AtomicBool) -> *const () { - p.cast() -} +/// A null pointer to a number, as a constant. +const NULL_NUM: *const u32 = ptr::null(); /// The raw pointers of `Arc`s and `Rc`s of values JS copies: a number's remade from a /// shared reference to its value, counted up and down, cloned, and taken back through it, /// and an `Arc`'s cast to `*const ()` and back, as a waker's data, which its -/// vtable counts, wakes, and drops. Each compares as the pointer `as_ptr` gives. +/// vtable counts, wakes, and drops. Each compares as the pointer `as_ptr` gives, and a +/// null one, made here or a constant, as null, through casts to and from `MaybeUninit`. pub fn raw_places(data: &[u8], out: &mut Vec) { let num = Arc::new(data.len() as u32); let rc = Rc::new(9u16); @@ -2236,8 +2235,12 @@ pub fn raw_places(data: &[u8], out: &mut Vec) { [ num_at as *const () == Arc::as_ptr(&num).cast(), rc_at.cast::<()>() == Rc::as_ptr(&rc) as *const (), - erase_flag(Arc::as_ptr(&flag)) == wakers[0].data(), + Arc::as_ptr(&flag).cast::<()>() == wakers[0].data(), ptr::from_ref(&*flag).cast::<()>() == wakers[0].data(), + ptr::null::() as *const () == ptr::null(), + NULL_NUM.cast::<()>() == ptr::null(), + ptr::null::>().cast::().cast::<()>() == ptr::null(), + Arc::as_ptr(&num).cast::>().cast::<()>() == Arc::as_ptr(&num).cast(), ] .map(u8::from), ); diff --git a/ts/fixtures/reject/census.txt b/ts/fixtures/reject/census.txt index 84558557f..dd50d5ed5 100644 --- a/ts/fixtures/reject/census.txt +++ b/ts/fixtures/reject/census.txt @@ -225,6 +225,7 @@ fixtures/reject/src/pointers.rs:erased_empty+2:20: a pointer to `((), ())` cast fixtures/reject/src/pointers.rs:erased_place+2:2: a pointer to `u32` cast to one to `()`, whose JS value is a place of its own each borrow fixtures/reject/src/pointers.rs:erased_place+2:22: a pointer to `u32` cast to one to `()`, whose JS value is a place of its own each borrow fixtures/reject/src/pointers.rs:erased_start+2:2: a pointer to `pointers::Outer` cast to one to `()`, whose address its `pointers::Inner` at its start shares, which JS keeps as an object of its own +fixtures/reject/src/pointers.rs:erased_unshown+1:4: a pointer to `u32` cast to one to `()`, which only an `Arc`'s or `Rc`'s raw pointer keeps the place of, and the body doesn't show this one is fixtures/reject/src/pointers.rs:made_part_replaced+5:10: a raw pointer to `(u32, u32)` in `pointers::Gap`, which the crate may put another object in place of fixtures/reject/src/pointers.rs:made_part_replaced+6:10: a raw pointer to `(u32, u32)` in `pointers::Gap`, which the crate may put another object in place of fixtures/reject/src/pointers.rs:made_part_replaced+7:58: a raw pointer to `(u32, u32)` in `pointers::Gap`, 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 c2eae6dd6..8230089d2 100644 --- a/ts/fixtures/reject/expected.txt +++ b/ts/fixtures/reject/expected.txt @@ -227,6 +227,7 @@ fixtures/reject/src/pointers.rs:erased_empty+2:20: a pointer to `((), ())` cast fixtures/reject/src/pointers.rs:erased_place+2:2: a pointer to `u32` cast to one to `()`, whose JS value is a place of its own each borrow fixtures/reject/src/pointers.rs:erased_place+2:22: a pointer to `u32` cast to one to `()`, whose JS value is a place of its own each borrow fixtures/reject/src/pointers.rs:erased_start+2:2: a pointer to `pointers::Outer` cast to one to `()`, whose address its `pointers::Inner` at its start shares, which JS keeps as an object of its own +fixtures/reject/src/pointers.rs:erased_unshown+1:4: a pointer to `u32` cast to one to `()`, which only an `Arc`'s or `Rc`'s raw pointer keeps the place of, and the body doesn't show this one is fixtures/reject/src/pointers.rs:made_part_replaced+5:10: a raw pointer to `(u32, u32)` in `pointers::Gap`, which the crate may put another object in place of fixtures/reject/src/pointers.rs:made_part_replaced+6:10: a raw pointer to `(u32, u32)` in `pointers::Gap`, which the crate may put another object in place of fixtures/reject/src/pointers.rs:made_part_replaced+7:58: a raw pointer to `(u32, u32)` in `pointers::Gap`, which the crate may put another object in place of diff --git a/ts/fixtures/reject/src/pointers.rs b/ts/fixtures/reject/src/pointers.rs index e309df1c7..c94c783fa 100644 --- a/ts/fixtures/reject/src/pointers.rs +++ b/ts/fixtures/reject/src/pointers.rs @@ -568,6 +568,12 @@ pub fn erased_borrows(n: &u32, c: &std::cell::UnsafeCell, a: &std::sync::Ar std::ptr::from_ref(n) as *const () == arc && c.get().cast_const().cast() == arc } +/// A pointer to a value JS copies from elsewhere, cast to one to `()`, which only an `Arc`'s +/// raw pointer would keep the one place of. +pub fn erased_unshown(p: *const u32) -> *const () { + p.cast() +} + /// A pointer to a box, cast to one to `()`, which JS keeps as what it holds. pub fn erased_box(b: Box<(u8, u8)>) -> bool { let p = &raw const b; diff --git a/ts/fixtures/reject/ts.toml b/ts/fixtures/reject/ts.toml index 5f97a1870..f15db3536 100644 --- a/ts/fixtures/reject/ts.toml +++ b/ts/fixtures/reject/ts.toml @@ -156,6 +156,7 @@ roots = [ "pointers::erased_empty", "pointers::erased_place", "pointers::erased_start", + "pointers::erased_unshown", "pointers::made_part_replaced", "pointers::nonnull_reassigned", "pointers::object_elements", diff --git a/ts/runtime/rs.ts b/ts/runtime/rs.ts index 9328504fd..27322f67e 100644 --- a/ts/runtime/rs.ts +++ b/ts/runtime/rs.ts @@ -68,12 +68,24 @@ export function panic(message: string, at?: Location | string, owned?: boolean | * nothing past it: a panic that can't unwind, at `at` or at the key of std's site. */ export function precondition(value: T | undefined, check: string, at?: Location | string): T { - if (value === undefined) { - panic(`unsafe precondition(s) violated: ${check}\n\nThis indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.`, at); - } + if (value === undefined) panic(violation(check), at); return value; } +/** The message of std's debug check that an unsafe function's precondition `check` held. */ +function violation(check: string): string { + return `unsafe precondition(s) violated: ${check}\n\nThis indicates a bug in the program. This Undefined Behavior check is optional, and cannot be relied on for safety.`; +} + +/** + * Abort where the program broke `check`, which Rust leaves undefined, worded as std's + * debug checks of an unsafe function's preconditions are. Nothing native does there is + * defined, so no hook runs. + */ +export function violated(check: string): never { + throw new Abort(violation(check)); +} + /** * Panic at `at` with `message`: literal pieces, and the `usize`s between them, which a * hook reads as the `String` std's `panic!` writes each piece and number into. @@ -299,7 +311,7 @@ class TextAt extends AtIndex { } override set v(_: number) { - throw textWrite(); + textWrite(); } override at(index: number): TextAt { @@ -307,9 +319,9 @@ class TextAt extends AtIndex { } } -/** The failure of a write, or a mutable slice, through a `TextAt`. */ -function textWrite(): Error { - return new Error("rust2-ts: a write through a pointer into a `str`'s bytes, which Rust forbids"); +/** A write through a `TextAt`, which a shared reference made. */ +function textWrite(): never { + return violated("a write requires a pointer not made from a shared reference, as `str::as_ptr`'s is"); } /** `str::as_ptr`: the read-only pointer to the first byte of its UTF-8. */ @@ -363,10 +375,14 @@ function addressAt(addr: number): Address { return at; } -function nowhere(): never { - throw new Error("rust2-ts: a read or write through a pointer to no memory"); +/** A read or write through a pointer to no memory. */ +export function nowhere(): never { + return violated("a read or write requires a pointer to memory, not null, dangling, or moved off either"); } +/** What null and dangling pointers point into: no elements, which any access through them is past. */ +export const NO_MEMORY: readonly never[] = /* @__PURE__ */ Object.freeze([]); + /** The array of one element that a pointer to a value in no array points into, by its place. */ const LONE = /* @__PURE__ */ new WeakMap, unknown[]>(); @@ -423,7 +439,7 @@ function elemOf(p: Place): AtIndex { const items = roomItems(p.array); return items ? new AtIndex(items, p.index) : p; } - if (p === NULL || p === DANGLING) return new AtIndex([] as T[], 0); + if (p === NULL || p === DANGLING) return new AtIndex(NO_MEMORY as unknown as T[], 0); let lone = LONE.get(p) as T[] | undefined; if (!lone) { lone = new Proxy(new Array(1), new Lone(p)); @@ -487,7 +503,7 @@ export function ptrOffsetFrom(p: Place, origin: Place): number { export function ptrCopy(src: Place, dst: Place, n: number, copy?: (value: T) => T): void { if (n === 0) return; const [from, to] = [elemOf(src), elemOf(dst)]; - if (to instanceof TextAt) throw textWrite(); + if (to instanceof TextAt) textWrite(); from.reach(n); to.reach(n); if (ArrayBuffer.isView(from.array) && ArrayBuffer.isView(to.array)) { @@ -663,7 +679,9 @@ export function ptrByteSlice(p: Place, len: number, shared: boolean): By } const at = elemOf(p); at.reach(len); - if (!shared && len !== 0 && at instanceof TextAt) throw textWrite(); + // Stacked Borrows makes it undefined, though Tree Borrows allows it until a write, as + // with a substring's pointer moved back into its text, which throws until Rust settles. + if (!shared && len !== 0 && at instanceof TextAt) throw new Error("rust2-ts: a mutable slice of a `str`'s bytes through `str::as_ptr`"); if (at.array instanceof Uint8Array) return new ByteSlice(at.array, at.index, len); // A byte in no array, which no `Uint8Array` can share. if (!shared) throw new Error("rust2-ts: a raw or mutable slice of a byte in no array of bytes"); diff --git a/ts/runtime/rs/alloc.ts b/ts/runtime/rs/alloc.ts index a628ffcd3..297fd904f 100644 --- a/ts/runtime/rs/alloc.ts +++ b/ts/runtime/rs/alloc.ts @@ -5,7 +5,7 @@ // 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. -import { Abort, Err, type Fmt, type FmtResult, type Formatter, fmtDebugStructFields, fmtPad, fmtWriteFmt, Ok, type Place, type Result } from "../rs.ts"; +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"; import { type u32, u32Debug, type usize, usizeDebug } from "./int.ts"; @@ -184,7 +184,7 @@ export function allocBytes(p: Place, elem: number, type: string): Block /** The block the pointer `p` to bytes, which `dealloc` or `realloc` takes, is. */ function blockOf(p: Place): Block { - if (!(p instanceof Block)) throw new Error("rust2-ts: memory freed or grown that isn't from `alloc`"); + if (!(p instanceof Block)) violated("dealloc and realloc require memory that alloc gave"); return p; } diff --git a/ts/runtime/rs/collections.ts b/ts/runtime/rs/collections.ts index f2568c160..63bc470d8 100644 --- a/ts/runtime/rs/collections.ts +++ b/ts/runtime/rs/collections.ts @@ -15,7 +15,7 @@ // A function that may drop a key, value, or item std's would, rather than return or keep // it, takes what drops each that does, as `k`, `v`, or `f`, and drops it where std's does. -import { type ArrayRef, ArraySlice, arraySliceOfSlice, Borrowed, ByteSlice, ByteVec, byteVecPush, byteVecReserve, capReserve, capReserveExact, capTryReserve, capTryReserveExact, type CloneFrom, type Debug, debugStructField, debugStructFinishNonExhaustive, Err, type Fmt, fmtDebugStruct, fmtDebugStructFields, fmtDebugTupleFields, fmtIter, fmtList, type FmtResult, fmtSet, fmtTuple, type Formatter, type None, OK, Ok, panic, type Place, type RangeBound, rangeCheck, type Result, type Room, roomPast, searchBy, type Elements, Slice, sliceData, sliceFrom, sliceLength, sliceSort, sliceStart, Vec, vecAppend, vecCapacity, vecCloneFrom, vecFrom, vecHold, vecKeep, vecMax, vecReserve, vecWithCapacity, panicSizes } from "../rs.ts"; +import { type ArrayRef, ArraySlice, NO_MEMORY, nowhere, arraySliceOfSlice, Borrowed, ByteSlice, ByteVec, byteVecPush, byteVecReserve, capReserve, capReserveExact, capTryReserve, capTryReserveExact, type CloneFrom, type Debug, debugStructField, debugStructFinishNonExhaustive, Err, type Fmt, fmtDebugStruct, fmtDebugStructFields, fmtDebugTupleFields, fmtIter, fmtList, type FmtResult, fmtSet, fmtTuple, type Formatter, type None, OK, Ok, panic, type Place, type RangeBound, rangeCheck, type Result, type Room, roomPast, searchBy, type Elements, Slice, sliceData, sliceFrom, sliceLength, sliceSort, sliceStart, Vec, vecAppend, vecCapacity, vecCloneFrom, vecFrom, vecHold, vecKeep, vecMax, vecReserve, vecWithCapacity, panicSizes } from "../rs.ts"; import { allocError, CAPACITY_OVERFLOW, type TryReserveError } from "./alloc.ts"; import type { HashKey, Hashing } from "./hash.ts"; import { type Limbs, lt, type u64, type usize } from "./int.ts"; @@ -438,6 +438,7 @@ export class AtIndex implements Place { /** The room past the array that holds `n` elements from here, which `reach` requires. */ private room(n: number): Room { const room = this.index >= 0 ? roomPast(this.array, this.index + n) : undefined; + if (room === undefined && this.array === NO_MEMORY) nowhere(); if (room === undefined) throw new Error("rust2-ts: a read or write through a pointer past the array JS keeps it in"); return room; } diff --git a/ts/runtime/rs/iter.ts b/ts/runtime/rs/iter.ts index c2895d7d5..96a6ae3be 100644 --- a/ts/runtime/rs/iter.ts +++ b/ts/runtime/rs/iter.ts @@ -22,7 +22,7 @@ // `owned` functions follow it, dispatching on the kind, so a bundle that never drops an // item carries none of it. -import { ByteSlice, ByteVec, type ArrayRef, type ArraySlice, arraySliceItems, arraySliceAt, arraySlicePart, byteVecExtendFromSlice, byteVecPush, byteVecReserve, byteVecReserveExact, byteVecShrinkTo, byteVecWithCapacity, capReserve, type Debug, Err, type Fmt, type FmtResult, type Formatter, fmtBool, fmtDebugStructFields, fmtDebugTupleFields, fmtOption, type None, Ok, type Place, panic, place, type RangeBound, type Result, sliceItems, slicePart, type Slice, type SliceLike, Vec, vecCapacity, vecExtendFromSlice, vecFrom, vecHold, vecMax, vecWithCapacity, assertFailed, fmtOwned } from "../rs.ts"; +import { ByteSlice, ByteVec, violated, type ArrayRef, type ArraySlice, arraySliceItems, arraySliceAt, arraySlicePart, byteVecExtendFromSlice, byteVecPush, byteVecReserve, byteVecReserveExact, byteVecShrinkTo, byteVecWithCapacity, capReserve, type Debug, Err, type Fmt, type FmtResult, type Formatter, fmtBool, fmtDebugStructFields, fmtDebugTupleFields, fmtOption, type None, Ok, type Place, panic, place, type RangeBound, type Result, sliceItems, slicePart, type Slice, type SliceLike, Vec, vecCapacity, vecExtendFromSlice, vecFrom, vecHold, vecMax, vecWithCapacity, assertFailed, fmtOwned } from "../rs.ts"; import { AtIndex, BTreeIter, HashIter, type Ordering } from "./collections.ts"; import { type Hasher, hash8 } from "./hash.ts"; import { charStep, intToBig, type Limbs, type Step, usizeDebug, lt as wideLt } from "./int.ts"; @@ -3417,7 +3417,7 @@ class ZipIter extends Iter<[A, B]> implements Disposable { const a = this.a.nextBack(); const b = this.b.nextBack(); if (a === DONE && b === DONE) return DONE; - if (a === DONE || b === DONE) panic("internal error: entered unreachable code"); + if (a === DONE || b === DONE) panic("internal error: entered unreachable code", "zip_next_back"); return [a, b]; } @@ -3466,7 +3466,8 @@ class ZipFold extends Iter<[A, B]> { this.left--; const a = this.a.next(); const b = this.b.next(); - if (a === DONE || b === DONE) panic("internal error: entered unreachable code"); + // Only std's iterators are `TrustedLen`, which never run out early. + if (a === DONE || b === DONE) violated("hint::unreachable_unchecked must never be reached"); return [a, b]; } diff --git a/ts/runtime/rs/task.ts b/ts/runtime/rs/task.ts index 772d922b0..741f5e96c 100644 --- a/ts/runtime/rs/task.ts +++ b/ts/runtime/rs/task.ts @@ -4,7 +4,7 @@ // A value whose drop JS can observe has `[Symbol.dispose]`, which runs its `Drop` impl // and drops its fields. `None` is `undefined`, which drops as nothing. -import { Abort, arrayAssign, type ByteSlice, type ArrayRef, type LentArray, type ElemCopy, ArraySlice, arraySliceItems, arraySliceCopy, arraySliceSet, type CloneFrom, cloneOver, type Debug, type DebugStruct, debugStructField, debugStructFinish, debugStructFinishNonExhaustive, debugTupleField, debugTupleFinish, Err, type FmtResult, type Formatter, fmtBool, fmtDebugStruct, fmtDebugTuple, fmtDebugTupleFields, fmtPad, fmtStr, type None, NULL, objectCopy, OK, Ok, Panic, panic, type Place, place, ptrErase, ptrHome, ptrNowhere, ptrWrite, type Result, Slice, sliceSet, sliceToArray, stringAsBytes, type Vec, assertFailed, fmtOwned } from "../rs.ts"; +import { Abort, arrayAssign, type ByteSlice, type ArrayRef, type LentArray, type ElemCopy, ArraySlice, arraySliceItems, arraySliceCopy, arraySliceSet, type CloneFrom, cloneOver, type Debug, type DebugStruct, debugStructField, debugStructFinish, debugStructFinishNonExhaustive, debugTupleField, debugTupleFinish, Err, type FmtResult, type Formatter, fmtBool, fmtDebugStruct, fmtDebugTuple, fmtDebugTupleFields, fmtPad, fmtStr, type None, NULL, objectCopy, OK, Ok, Panic, panic, type Place, place, ptrErase, ptrHome, ptrNowhere, ptrWrite, type Result, Slice, sliceSet, violated, sliceToArray, stringAsBytes, type Vec, assertFailed, fmtOwned } from "../rs.ts"; import type { Hasher } from "./hash.ts"; import type { Location } from "./location.ts"; @@ -336,21 +336,22 @@ export function arcRaw

(arc: Arc, p: P, of: "Arc" | "R /** * `Arc::from_raw`, of an `Arc` or an `Rc` as `of` says: the one `p` points into, which * `into_raw` or `as_ptr` gave, or arithmetic moved back to, and a count of which it takes, - * as std's does. Any other pointer, or one to a value already dropped, fails, as JS keeps - * no count beside it. + * as std's does. Any other pointer, or one to a value already dropped, which Rust leaves + * undefined, aborts. */ export function arcFromRaw(p: object, of: "Arc" | "Rc"): Arc { const arc = (of === "Arc" ? RAW_ARCS : RAW_RCS).get(ptrHome(p)); - if (arc === undefined) throw new Error(`rust2-ts: \`${of}::from_raw\` of a pointer no \`${of}::into_raw\` or \`as_ptr\` gave`); - if (arc.strong === 0) throw new Error(`rust2-ts: \`${of}::from_raw\` of a pointer to a value already dropped`); + if (arc === undefined) violated(`${of}::from_raw requires a pointer that ${of}::into_raw or ${of}::as_ptr gave`); + if (arc.strong === 0) violated(`${of}::from_raw requires a pointer to a value not yet dropped`); return arc as Arc; } /** * `p as *const ()`, as `ptrErase` casts it, of a pointer to a value JS copies: the place * of an `Arc`'s or `Rc`'s value that `into_raw` or `as_ptr` gave, or arithmetic moved back - * to, which is its one place as its address is, or one at no memory. Any other place is a - * borrow's own, which no other pointer to the value would compare as, so it fails. + * to, which is its one place as its address is, or one at no memory. Translation casts + * only one the body shows is either, so any other place, a borrow's own, which no other + * pointer to the value would compare as, fails as its bug. */ export function arcErase(p: object, type: string, align: number): Place { const home = ptrHome(p); diff --git a/ts/runtime/rs/tokio.ts b/ts/runtime/rs/tokio.ts index c39f019fb..bc6a2e778 100644 --- a/ts/runtime/rs/tokio.ts +++ b/ts/runtime/rs/tokio.ts @@ -1606,10 +1606,10 @@ export function oneshotTryRecv(rx: OneshotReceiver, empty: E, closed: E return result; } -/** A receiver's `Future::poll`: `Ok` of the value, or `error` once the sender dropped without one. */ -export function oneshotPoll(rx: OneshotReceiver, cx: Context, error: E): Poll> { +/** A receiver's `Future::poll`: `Ok` of the value, or `error` once the sender dropped without one, and a panic at `at` once it gave either. */ +export function oneshotPoll(rx: OneshotReceiver, cx: Context, error: E, at?: Location): Poll> { const inner = rx.inner; - if (inner === undefined) panic("called after complete"); + if (inner === undefined) panic("called after complete", at); const value = inner.pollRecv(cx); if (value === Pending) return Pending; oneshotFinish(rx); diff --git a/ts/src/census.rs b/ts/src/census.rs index 4c2ea8b3e..467cb25e3 100644 --- a/ts/src/census.rs +++ b/ts/src/census.rs @@ -171,6 +171,7 @@ const VERBATIM: &[&str] = &[ "Pending", "Pointer", "Poll", + "Rc", "Ready", "Reborrow", "Result", diff --git a/ts/src/lower/caller.rs b/ts/src/lower/caller.rs index dad6dba08..17c1c6338 100644 --- a/ts/src/lower/caller.rs +++ b/ts/src/lower/caller.rs @@ -11,11 +11,13 @@ //! 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. +//! given. 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_id::DefId; +use rustc_middle::mir::TerminatorKind; use rustc_middle::ty::{Instance, InstanceKind, TyCtxt}; use rustc_span::{RemapPathScopeComponents, SourceFile, Span}; @@ -327,6 +329,14 @@ const SITES: &[(&str, &str, &str, &str)] = &[ "", "expect(\"multiplying duration by scalar", ), + // A macro's panic is at the macro's call, here the one that gives the general zip its + // `next_back`, which an `ExactSizeIterator` whose length lies reaches. + ( + "zip_next_back", + "core/src/iter/adapters/zip.rs", + "// General Zip impl", + "zip_impl_general_defaults!", + ), ]; /// Where each std function that neither takes its caller's location nor is defined by a @@ -610,6 +620,33 @@ fn bytes_find( Some(object(self::file(tcx, &source), line, col)) } +/// Where `def_id`, a dependency's function that takes no caller's location, makes its one +/// `panic!`: the call in the MIR its crate compiled, outside what that inlined, whose file is +/// 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; + } + 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. pub fn callee_site(tcx: TyCtxt<'_>, def_id: DefId) -> Option { let path = library::std_path(tcx, def_id).join("::"); diff --git a/ts/src/lower/mir/origin.rs b/ts/src/lower/mir/origin.rs index 839924a07..4d914d95c 100644 --- a/ts/src/lower/mir/origin.rs +++ b/ts/src/lower/mir/origin.rs @@ -6,7 +6,8 @@ //! //! So is whether a pointer to a value JS copies is an `Arc`'s, the one place of its value, //! or a borrow's, a place of its own: only an `Arc`'s is an identity, which `from_raw` -//! takes back to it and a cast to `*const ()` keeps. +//! takes back to it and a cast to `*const ()` keeps. That cast is refused unless the body +//! shows an `Arc`'s, or null or dangling, since a place from elsewhere has no one identity. use rustc_middle::mir::{self, BasicBlock, Local, Location, Operand, ProjectionElem, Rvalue, TerminatorKind}; use rustc_middle::ty::{self, GenericArgsRef}; @@ -99,7 +100,7 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { }) }; match (owner.as_str(), name.as_str()) { - ("ptr" | "NonNull", "cast") => self.erased_borrow(arg(0)?, pointee, gargs.types().nth(1)?), + ("ptr" | "NonNull", "cast") => self.erased_place(arg(0)?, pointee, gargs.types().nth(1)?), ("Arc" | "Rc", "from_raw" | "increment_strong_count" | "decrement_strong_count") if self.arc_pointer(arg(0)?) == Some(false) => { @@ -433,6 +434,9 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { ("ptr" | "NonNull", "cast_const" | "cast_mut") | ("NonNull", "as_ptr" | "new_unchecked") => { self.arc_pointer(&args.first()?.node) } + ("ptr" | "NonNull", "cast") if self.same_pointee(&args.first()?.node, local) => { + self.arc_pointer(&args.first()?.node) + } ("UnsafeCell", "get" | "raw_get") | ("Cell", "as_ptr") | ("MaybeUninit", "as_ptr" | "as_mut_ptr") => { Some(false) } @@ -441,13 +445,68 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { } /// Why the cast of the raw pointer `op` to `from` to one to `to` can't be, if it erases - /// one to a value JS copies that the body shows is a borrow's place to a `*const ()`, and - /// the cast itself refuses no pointer to `from`. - pub(super) fn erased_borrow(&self, op: &Operand<'tcx>, from: ty::Ty<'tcx>, to: ty::Ty<'tcx>) -> Option { + /// one to a value JS copies to a `*const ()`, and the cast itself refuses no pointer to + /// `from`: unless the body shows an `Arc`'s or `Rc`'s `into_raw` or `as_ptr` gave it, its + /// value's one place, or that it is null or dangling, it has no one identity. + pub(super) fn erased_place(&self, op: &Operand<'tcx>, from: ty::Ty<'tcx>, to: ty::Ty<'tcx>) -> Option { let t = &self.b.t; let erases = t.identity_pointee(to) && !t.identity_pointee(from) && t.pointee(from) == Pointee::Place; - (erases && pointer::unerasable(self.b, from).is_none() && self.arc_pointer(op) == Some(false)) - .then(|| pointer::erased_place(t.uninit_inner(from))) + if !erases || pointer::unerasable(self.b, from).is_some() || self.nowhere(op) { + return None; + } + let pointee = t.uninit_inner(from); + match self.arc_pointer(op) { + Some(true) => None, + Some(false) => Some(pointer::erased_place(pointee)), + None => Some(format!( + "a pointer to `{pointee}` cast to one to `()`, which only an `Arc`'s or `Rc`'s raw pointer keeps the place of, and the body doesn't show this one is" + )), + } + } + + /// Whether the body shows the raw pointer `op` is null or dangling, at no memory. + fn nowhere(&self, op: &Operand<'tcx>) -> bool { + // A constant pointer of no allocation, an integer: null, or another, which a + // constant's lowering refuses. + if let Operand::Constant(c) = op { + return (c.const_) + .try_eval_scalar_int(self.tcx, self.b.t.typing_env_pub()) + .is_some(); + } + let Some(local) = self.traced(op) else { + return false; + }; + if self.def_at[local].is_some() { + return match self.def_rvalue(local) { + Some( + Rvalue::Use(op, _) + | Rvalue::Cast( + mir::CastKind::PtrToPtr + | mir::CastKind::PointerCoercion(ty::adjustment::PointerCoercion::MutToConstPointer, _), + op, + _, + ), + ) => self.nowhere(op), + _ => false, + }; + } + let Some((def_id, _, args)) = self.def_call(local) else { + return false; + }; + match library::key(self.tcx, def_id) { + Some((owner, name)) => match (owner.as_str(), name.as_str()) { + ( + "ptr", + "null" | "null_mut" | "dangling" | "dangling_mut" | "without_provenance" | "without_provenance_mut", + ) + | ("NonNull", "dangling") => true, + ("ptr" | "NonNull", "cast" | "cast_const" | "cast_mut") | ("NonNull", "as_ptr") => { + args.first().is_some_and(|a| self.nowhere(&a.node)) + } + _ => false, + }, + None => false, + } } /// The local `op` reads whole, if the body assigns it once. @@ -456,9 +515,16 @@ impl<'tcx> Fx<'_, '_, '_, 'tcx> { (self.defs[local] == 1 && !self.is_arg(local)).then_some(local) } - /// Whether `op` is a pointer to what `local` points at. + /// Whether `op` is a pointer, raw or `NonNull`, to what `local` points at, through any + /// `MaybeUninit`s, which a cast between keeps the pointer of. fn same_pointee(&self, op: &Operand<'tcx>, local: Local) -> bool { - let pointee = |ty: ty::Ty<'tcx>| ty.builtin_deref(true); + let pointee = |ty: ty::Ty<'tcx>| { + let pointee = match ty.kind() { + ty::Adt(adt, args) if Std::of(self.tcx, adt.did()) == Some(Std::NonNull) => Some(args.type_at(0)), + _ => ty.builtin_deref(true), + }; + pointee.map(|t| self.b.t.uninit_inner(t)) + }; let from = op.ty(&self.mir.local_decls, self.tcx); pointee(from).is_some() && pointee(from) == pointee(self.mir.local_decls[local].ty) } diff --git a/ts/src/lower/mir/rvalue.rs b/ts/src/lower/mir/rvalue.rs index 17cff3689..72e805675 100644 --- a/ts/src/lower/mir/rvalue.rs +++ b/ts/src/lower/mir/rvalue.rs @@ -483,7 +483,7 @@ impl<'m, 'b, 'a, 'tcx> Fx<'m, 'b, 'a, 'tcx> { if let (Some(a), Some(b)) = (from.builtin_deref(true), to.builtin_deref(true)) && from.is_raw_ptr() => { - if let Some(why) = self.erased_borrow(op, a, b) { + if let Some(why) = self.erased_place(op, a, b) { return self.err(span, why); } if let Some(cast) = self.alloc_cast(op, a, b, span, out) { diff --git a/ts/src/lower/pointer.rs b/ts/src/lower/pointer.rs index a31f5a3e9..ae0eb6a32 100644 --- a/ts/src/lower/pointer.rs +++ b/ts/src/lower/pointer.rs @@ -1168,8 +1168,7 @@ pub fn call<'tcx>( /// Why a pointer to `ty` can't be erased to a `*const ()`, an identity that compares as /// itself, if it can't: one JS reaches through a slice's places, or a view of bytes, is a /// new one each borrow, and one to a value of no fixed size loses its size. Of a place, -/// only an `Arc`'s is the value's one, which `rs.arcErase` checks where the body doesn't -/// show it. +/// only an `Arc`'s is the value's one, which the body must show. pub fn unerasable<'tcx>(b: &Body<'_, '_, 'tcx>, ty: Ty<'tcx>) -> Option { if b.t.polymorphic() && ty.has_param() { return None; diff --git a/ts/src/lower/tokio.rs b/ts/src/lower/tokio.rs index a8469e560..57c8a082a 100644 --- a/ts/src/lower/tokio.rs +++ b/ts/src/lower/tokio.rs @@ -428,7 +428,22 @@ pub fn trait_call<'tcx>( let (rx, cx) = (arg(), arg()); let output = b.t.future_output(self_ty.peel_refs(), span); let error = made(b, err_of(output), None, vec![Expr::undefined()], span, out); - Expr::rs("oneshotPoll", vec![rx, cx, error]) + let mut args = vec![rx, cx, error]; + // Where tokio's `poll` panics once it completed, which a hook reads. + if b.t.hooked { + let own = ty::Instance::try_resolve(tcx, b.t.typing_env_pub(), call.def_id, call.args) + .ok() + .flatten() + .and_then(|poll| super::caller::own_panic(tcx, poll.def_id())); + args.push(match own { + Some(at) => at, + None => b.err( + span, + "tokio's poll of a oneshot receiver, in a program with a panic hook, whose compiled code shows no one panic", + ), + }); + } + Expr::rs("oneshotPoll", args) } // The rest as std maps them: `Debug` by `fmt`, and `IntoFuture` as itself. _ => return Err(args.collect()), diff --git a/ts/tests/fixtures.rs b/ts/tests/fixtures.rs index fde8f2fb5..0f3465a7b 100644 --- a/ts/tests/fixtures.rs +++ b/ts/tests/fixtures.rs @@ -59,16 +59,44 @@ fn driver_at(manifest: &Path, config: &Path, args: &[&std::ffi::OsStr], build: & command } -/// The flag that names 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. +/// 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. fn remap() -> String { + static FLAGS: std::sync::OnceLock = std::sync::OnceLock::new(); + FLAGS.get_or_init(remap_flags).clone() +} + +/// The flags [`remap`] gives, once the lockfile's crates are unpacked, so they don't +/// depend on what a build before unpacked. +fn remap_flags() -> String { + let status = cargo() + .args(["fetch", "--locked", "--manifest-path"]) + .arg(workspace()) + .status() + .expect("running cargo"); + assert!(status.success(), "fetching the fixtures' crates failed"); let home = match std::env::var_os("CARGO_HOME") { Some(home) => PathBuf::from(home), None => std::env::home_dir() .expect("a home directory, which holds cargo's") .join(".cargo"), }; - format!("--remap-path-prefix={}=/cargo", home.display()) + 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()]); + // 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()); + } + } + flags } /// Run the driver on a fixture, returning its output directory and what it printed. diff --git a/ts/tests/pointers.ts b/ts/tests/pointers.ts index ce5c4101c..a1fa48f52 100644 --- a/ts/tests/pointers.ts +++ b/ts/tests/pointers.ts @@ -1,7 +1,8 @@ // A pointer the translation can't follow, such as one a struct's field holds, fails with // a rust2-ts error where JS keeps apart what Rust's reaches, which native Rust can't show: // there each is defined, as `repr(C)` fields are one allocation, and a `Vec`'s capacity -// is past its length. +// is past its length. One Rust leaves undefined, such as a read through a dangling +// pointer, aborts as std's debug checks do. // // usage: node pointers.ts @@ -10,6 +11,8 @@ import { strict as assert } from "node:assert"; import * as rs from "../runtime/rs.ts"; const unsure = (f: () => void) => assert.throws(f, (e: Error) => !(e instanceof rs.Panic) && e.message.startsWith("rust2-ts: ")); +// What Rust leaves undefined aborts, as std's debug checks of unsafe preconditions do. +const undefinedBehavior = (f: () => void) => assert.throws(f, (e: Error) => e instanceof rs.Abort && e.message.startsWith("unsafe precondition(s) violated: ")); // Two `&raw const x` of one variable, each its own `rs.Place`. let x = 5; @@ -77,20 +80,21 @@ unsure(() => rs.allocBytes(words, 4, "f32")); unsure(() => rs.allocBytes(rs.ptrAdd(words, 1), 4, "u32")); // Grown, it keeps its values, as many as fit; freed or grown, a pointer to its values is // no block. -unsure(() => rs.dealloc(words)); -unsure(() => rs.realloc(words, 16)); +undefinedBehavior(() => rs.dealloc(words)); +undefinedBehavior(() => rs.realloc(words, 16)); const grown = rs.realloc(rs.allocBytes(words, 4, "u32"), 18); assert.deepEqual(Array.from(grown.array ?? []), [0xffffffff, undefined, undefined, undefined]); // A dangling pointer read through, written through, or copied from, which Rust leaves // undefined, rather than reading `undefined`. const dangling: rs.Place = rs.DANGLING; -unsure(() => rs.ptrAdd(dangling, 1).v); -unsure(() => { +undefinedBehavior(() => rs.ptrAdd(dangling, 1).v); +undefinedBehavior(() => { rs.ptrAdd(dangling, 1).v = 1; }); -unsure(() => rs.ptrCopy(dangling, rs.arrayAsPtr(vec), 1)); -unsure(() => rs.ptrSlice(dangling, 1)); +undefinedBehavior(() => rs.ptrCopy(dangling, rs.arrayAsPtr(vec), 1)); +undefinedBehavior(() => rs.ptrSlice(dangling, 1)); +undefinedBehavior(() => rs.ptrAdd(rs.NULL as rs.Place, 1).v); assert.equal(vec[0], 7); // A raw slice pointer read through once its `Vec` has shrunk past it, which Rust keeps @@ -129,17 +133,17 @@ assert.notEqual(two, rs.DANGLING_UNIT); const aligned = rs.ptrUnerase(two, "raw::Byte", 1) as object; assert.notEqual(aligned, rs.DANGLING); assert.equal(rs.ptrErase(aligned, "raw::Byte", 1), two); -unsure(() => (aligned as rs.Place).v); +undefinedBehavior(() => (aligned as rs.Place).v); // `Arc::from_raw` of a pointer no `Arc::into_raw` or `as_ptr` gave, such as a box's, of an // `Rc`'s, or of one whose value dropped, which Rust leaves undefined. const task = new rs.Arc({ id: 1 }); const raw = rs.arcRaw(task, task.value, "Arc"); assert.equal(rs.arcFromRaw(raw, "Arc"), task); -unsure(() => rs.arcFromRaw({ id: 1 }, "Arc")); -unsure(() => rs.arcFromRaw(raw, "Rc")); +undefinedBehavior(() => rs.arcFromRaw({ id: 1 }, "Arc")); +undefinedBehavior(() => rs.arcFromRaw(raw, "Rc")); task[Symbol.dispose](); -assert.throws(() => rs.arcFromRaw(raw, "Arc"), /`Arc::from_raw` of a pointer to a value already dropped/); +assert.throws(() => rs.arcFromRaw(raw, "Arc"), /Arc::from_raw requires a pointer to a value not yet dropped/); // Moved off its place by arithmetic and back, which is the same address. const counted = new rs.Arc(7); const at = rs.arcRaw(counted, rs.arcPlace(counted), "Rc"); @@ -153,19 +157,19 @@ assert.equal(rs.arcErase(rs.NULL, "bool", 1), rs.NULL); assert.throws(() => rs.arcErase({ v: false }, "bool", 1), /only an `Arc`'s or `Rc`'s raw pointer keeps the place of/); // A `str`'s UTF-8 through `as_ptr`, which JS encodes anew from its text: read through, -// moved by arithmetic, and viewed, but a write, a copy into it, or a mutable slice of it, -// which Rust forbids, would change nothing the text reads. +// moved by arithmetic, and viewed, but a write or a copy into it, which Rust leaves +// undefined, aborts, and a mutable slice of it, undefined under Stacked Borrows alone, fails. const text = rs.strAsPtr("aé"); assert.equal(rs.ptrAdd(text, 2).v, 0xa9); assert.deepEqual(Array.from(rs.byteSliceView(rs.ptrByteSlice(text, 3, true))), [0x61, 0xc3, 0xa9]); assert.equal(rs.ptrOffsetFrom(rs.ptrWrappingAdd(text, 2, 1, 1), text), 2); -unsure(() => { +undefinedBehavior(() => { rs.ptrAdd(text, 1).v = 0; }); -unsure(() => { +undefinedBehavior(() => { rs.ptrWrappingAdd(text, 1, 1, 1).v = 0; }); -unsure(() => rs.ptrCopy(rs.byteSliceAsPtr(rs.byteSliceFrom(Uint8Array.of(1))), rs.ptrAdd(text, 1), 1)); +undefinedBehavior(() => rs.ptrCopy(rs.byteSliceAsPtr(rs.byteSliceFrom(Uint8Array.of(1))), rs.ptrAdd(text, 1), 1)); unsure(() => rs.ptrByteSlice(text, 1, false)); unsure(() => new rs.RawSlice(text, 3).derefBytes(false)); // None of it is nothing written, and two calls' pointers are two encodings.