1@README.md 2 3- The flags on this target (`rustc_flags`, `linker_flags` in `BUCK`) are the 4 whole point of the crate - do not "clean them up". Removing 5 `-Cdebug-assertions=yes` makes `subsecond::call` a no-op silently (it still 6 compiles and runs, it just never patches); removing `-Csave-temps=true` 7 removes the `.rcgu.o` objects `tools/hotpatch` links into the patch. 8- **`-Cdebug-assertions=yes` on THIS target is not enough by itself** - 9 `subsecond::call`/`try_call` are `cfg!(debug_assertions)`-gated 10 (subsecond/src/lib.rs:250-254, :411-414), and `cfg!()` resolves against 11 whichever crate's OWN compilation the macro invocation lives in, not the 12 downstream consumer's. Under cargo, one profile setting covers the whole 13 dependency graph; under buck2/reindeer, `//third-party/rust:subsecond` is 14 its OWN independent rustc invocation, built at the toolchain's default 15 (no debug-assertions) unless told otherwise. That's what 16 `third-party/rust/fixups/subsecond/fixups.toml`'s `rustc_flags = 17 ["-Cdebug-assertions=yes"]` is for. Measured 2026-09-20: without it, 18 `apply_patch` returns `Ok` and "patch applied" prints, but `nm` on the 19 patched binary shows zero calls to subsecond's own `get_jump_table` from 20 anywhere in `main` - the whole redirect was silently inert. 21- **`subsecond::call` needs a bare `fn` item, not a closure that captures 22 anything** - `tick` takes no arguments and reads a `static AtomicU64` 23 instead of a closure-captured `n`, and `main` calls `subsecond::call(tick)` 24 directly, never `subsecond::call(|| tick(n))`. Two independent reasons, 25 both measured 2026-09-20, discovered together as apparent inlining but 26 actually two separate causes: 27 1. `HotFn::try_call`'s redirect key depends on `size_of::<F>()` 28 (subsecond/src/lib.rs:420 on): a closure whose captured environment 29 happens to be exactly pointer-width (one `u64`, one reference, …) takes 30 the "treat this value as a bare fn pointer" branch 31 (`call_as_ptr`/`transmute_copy::<Self, Self::Real>`), which is only 32 correct for an ACTUAL bare fn pointer - for a real capturing closure of 33 that size it transmutes captured DATA as if it were a function address. 34 2. At this project's forced `-Copt-level=3` (toolchains/BUCK), rustc's 35 default cross-codegen-unit ThinLTO (visible as the 36 `*.rcgu.thin-lto-*.bc` files next to the `.rcgu.o`s) inlines a 37 small, single-call-site function into its caller. `subsecond`'s crate 38 carries no `#[inline(never)]` anywhere (it's written assuming a 39 dev-profile-style build where little gets inlined); without 40 `#[inline(never)]` on `tick` itself, `tick`'s own body - and the whole 41 `subsecond::call`/`HotFn`/`HotFunction::call_it` chain around it - 42 collapsed into one block inside `main` with no addressable symbol left 43 to redirect a call to. 44 If either fix is missing, `apply_patch` still succeeds and prints nothing 45 wrong - the log just keeps printing the old string forever. That silence 46 is what makes both traps worth restating here rather than only in the 47 research doc. 48- `tick`'s string literal is the thing this crate exists to let you change 49 without restarting the process. Editing anything else in `main.rs` is a 50 bigger, unproven patch (research/subsecond-patch-build.md's workspace-replay 51 path, §2/§5) - keep edits here to that one function while proving the 52 pipeline. 53- `TICKS` resets to 0 on every patch, on purpose - it's part of the tip 54 crate's own recompiled objects, not carried over from an unchanged 55 dependency crate, so subsecond's "globals are tracked" claim 56 (subsecond/src/lib.rs's module doc) doesn't apply to it. Don't read this 57 as a bug to fix; it's the same limitation as the thread-local one that 58 doc already names. 59- Never run this outside the devshell; like every other target here it needs 60 the pinned fenix rustc, not whatever `rustc` is on the host `PATH`.