Skip to content

im-rc -> im: Arc-backed persistent carriers (step 1 of Arc share), with perf receipt - #6929

Merged
briansrls merged 7 commits into
mainfrom
session/cool-wren-467
Jul 20, 2026
Merged

briansrls merged 7 commits into
mainfrom
session/cool-wren-467

Conversation

@briansrls

@briansrls briansrls commented Jul 20, 2026 •

Copy link
Copy Markdown
Contributor

Step 1 of the Arc-share lane: swap the persistent-collection crate im-rc for
its Arc-backed sibling im. No Rc → Arc change anywhere — that is step 2,
gated on the perf number below.

Why this is a prerequisite, not a follow-on

The typed payloads are built out of im_rc collections (TypeEnv.bindings is
Rc<HashMap<..>> where HashMap is im_rc::HashMap; 04_infer, infer_env,
infer_items, std_core all open with the im_rc prelude). An outer Arc cannot
make such a value Send while its interior is im_rc-backed, so the collection
crate has to move first.

What actually changes — exactly one axis

im and im-rc 15.1 are the same crate source. build.rs matches on
CARGO_PKG_NAME and emits cargo:rustc-cfg=threadsafe only for im; that cfg flips
one alias in the crate's util.rs:

#[cfg(threadsafe)]      pub(crate) type Ref<A> = std::sync::Arc<A>;
#[cfg(not(threadsafe))] pub(crate) type Ref<A> = std::rc::Rc<A>;

Every other difference between the two crates' src/** is doc-comment only
(verified by diff -r). Public API, macro set, and algorithms are identical. The
only feature im-rc has that im lacks is pool, which we do not request.
v2.std.value_carrier declares only the algorithmic shape
(^hash_array_mapped_trie, ^relaxed_radix_balanced_tree) and never names a crate,
so the declared model is untouched — this is a §2 Realization handler swap.

im requires no source changes: the seed compiled on the first try. Neither
Vector<A> nor HashMap<K,V> declares a Send/Sync bound, so Vector<Rc<Node>>
still compiles. Nothing became Send in this PR — the Value substrate is still
std::rc::Rc, by design.

Diff shape

Pure token substitution over .rs (161), .toml (11), .dag (10) — 432 changed
lines, every one differing by nothing but the im token (checked
programmatically). .md files are left alone: they are dated design records and
historical receipts, and rewriting them would falsify the record.

Emitter authority (the .dag side, which drives the generated seed):
05_emit_rust.dag prelude rows + emit_cargo_dep, runtime_rust.dag rt_header,
stage0_crates.dag dependency rows, compiler_tests_rust.dag, and 6
dag/tools/self_host_* transports.

Second commit is regen: im:: is 5 chars shorter than im_rc::, so rustfmt re-joins
previously-wrapped calls. --verify reported divergence_count=1
(compiler_tests.rs); write-mode regen reconciles it, and cargo fmt --all re-wraps
4 hand-maintained files for the same reason. All formatting-only — the sole token
change is trailing commas dropped when a multi-line call is joined onto one line.

The Cargo.toml rationale comment previously asserted "im-rc is the Rc-backed
(thread-confined, matching the Value Rc-discipline) crate". A mechanical substitution
would have turned that into a falsehood, so it is rewritten to state what is now true
and why the swap happened.

Oracles (green by execution, not typecheck)

Box for every number below: container ec014146f776, 128 vCPU visible, cgroup
memory.max 31.25 GiB (not MemAvailable 115 GiB, which is the host view),
local build (CTRL_BUILD_MODE=local — the session default is remote, which would
have invalidated the receipt), sccache off, load avg ~5–13 from co-tenant sessions.

1. Self-host fixed point — converges. regen_stage0 --verify,
regen_divergence_count=0 on 6/6 post-swap runs (and 6/6 pre-swap, the control).

2. Emitted corpus — equivalent. --emit-fresh before and after, 131 files each,
same file set. After applying the im token substitution and normalizing whitespace
and join-dropped trailing commas: 131/131 files equivalent, 0 residual differences.
Nothing semantic moved in parse → resolve → typecheck → emit.

3. Interpreter corpus — byte-identical. claim_batch --roster-from-discovery over
dag + src/v2, 2,074 witness rows — the only oracle that exercises the Ref
refcount in the eval hot path, so it is the one that actually tests Rc→Arc.

baseline post-swap
PASS 2072 2072
FAIL 2 2
resolve aborts 0 0
sha256 of sorted rows 5494b7df2131a2dc… 5494b7df2131a2dc…

diff of the sorted row sets: zero differences. The 2 failures
(non_fold_residue_clean_holds, non_fold_residue_no_unrostered_or_stale) are
pre-existing on the clean tree at 73eea76dd7 — captured in the baseline before any
edit, and unchanged by this PR.

Perf receipt

Instrument: regen_stage0 --verify, phases[compile_stage0] — the pure-compute
phase, excluding the cargo fmt subprocess. n=6 per arm, same box, same protocol.

baseline (im-rc) post (im)
min 44,972 ms 46,809 ms
median 45,720 ms 46,974 ms
mean 45,713 ms 48,071 ms
stdev 520 (1.1%) 2,157 (4.5%)

Delta: +4.1% min-to-min (median +2.7%; mean +5.2%, or +3.3% excluding one
52,242 ms contention outlier).

Min-to-min is the estimator I'd weight: the workload is deterministic and CPU-bound,
so noise can only add time. The post arm's higher variance is co-tenant contention
during that window, not a property of the change. Every trial was
status=completed.

Not editorialized further — that number is step 2's input.

Brian Searls and others added 2 commits July 20, 2026 16:35
The shorter `im::` token lets rustfmt fit several previously-wrapped calls
on one line. regen_stage0 --verify reported divergence_count=1
(compiler_tests.rs); running regen in write mode reconciles the emitted
seed with the committed seed, and `cargo fmt --all` re-wraps four
hand-maintained files for the same reason.

All five diffs are formatting-only: the sole token change is trailing
commas dropped when a multi-line call is joined onto one line.

regen_stage0 --verify now reports regen_divergence_count=0 across 6 runs.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot gunbai-bot Bot changed the title im-rc to im swap: prerequisite for Arc share, with perf receipt im-rc -> im: Arc-backed persistent carriers (step 1 of Arc share), with perf receipt Jul 20, 2026
@gunbai-bot
gunbai-bot Bot marked this pull request as ready for review July 20, 2026 16:56
Brian Searls and others added 2 commits July 20, 2026 16:59
The C1 realization note (2026-07-14) asserted two blockers for
SharedTypecheckCaches: (a) use std::collections::HashMap shells, not
im_rc::HashMap, and (b) Arc not Rc for every payload.

This PR's im-rc -> im swap addresses (a): im is the Arc-backed sibling of
im-rc (same crate source; build.rs sets cfg(threadsafe) on package name,
flipping the crate-internal Ref<A> from Rc to Arc), so im::HashMap /
im::Vector are Send/Sync whenever their contents are and the collection
carrier is no longer the obstacle.

(b) STANDS: the payloads are still Rc-backed and therefore still !Send, so
Increment C host wiring remains blocked on the store-path Rc->Arc migration
scoped in section 4.2. This PR changed no Rc.

Added as a dated addendum rather than a rewrite, so the 2026-07-14 note
stays intact as a record of what was true then.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 20, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Brian Searls and others added 2 commits July 20, 2026 17:30
Main moved 4 commits (namespace wave 1 #6848, Rc-to-Arc share spike #6913,
orchestration dissolution #6921, effect-grants slice A #6920), 978 files.

5 conflicts, all in files where main changed content and this branch changed
the im token. Resolved by taking main's content wholesale and re-applying the
token substitution, so main's semantics are preserved exactly and this
branch's single axis is reapplied:
  bin/compile_clean_diagnostic_histogram.rs, bin/infer_semantics_witness.rs,
  cli_run.rs, global_bare_corpus_census_test.rs, type_env_scope_chain_test.rs

Main also introduced 3 files carrying im_rc that this branch had never seen
(global_bare_census_coverage_test.rs, global_bare_variant_locals_receipt_test.rs
from the namespace wave, plus pipeline.rs via automerge). Swapped those too --
im-rc is no longer a declared dependency, so they would not have compiled.

Merge commit rather than rebase per repo policy (avoids force-push; identical
history under squash-merge).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Jul 20, 2026

Copy link
Copy Markdown
Contributor

Re: review 40261 (REQUEST_CHANGES) — valid when made, already addressed on the current head.

That review ran against c8842d99, which is the dashboard's intermediate mid-merge WIP snapshot. The main merge brought in three v1-compiler-tests files that did not exist on my base and therefore still carried im_rc; the snapshot was taken after the merge landed those files but before I applied the token swap to them. So the finding was accurate against the commit it saw.

Verified on head 485e933a35:

src/v1/tests/src/global_bare_variant_locals_receipt_test.rs: im_rc=0  im::=4
src/v1/tests/src/global_bare_census_coverage_test.rs:        im_rc=0  im::=2
src/v1/tests/src/pipeline.rs:                                im_rc=0  im::=7

The specific cited lines now read:

use im::HashMap;                                  // receipt_test.rs:6
.collect::<im::Vector<_>>(),                      // census_coverage_test.rs:58
.fold(im::HashMap::new(), |acc, si| {             // census_coverage_test.rs:66
census_only_sources: Rc::new(im::Vector::new()),  // pipeline.rs:9475

src/v1/tests/Cargo.toml declares im = { version = "15.1", features = ["serde"] } (serde parity kept). Tree-wide there are zero remaining im_rc / im-rc tokens outside one prose block in src/v1/stage0/Cargo.toml, which deliberately names both crates to explain the swap.

Proven by execution rather than by grep — the reviewer's claim was that the crate would not compile:

$ cargo check -p v1-compiler-tests --tests
Finished `dev` profile [unoptimized] target(s) in 44.58s   (rc=0)

One pre-existing unused_imports warning on v1_std_core, unrelated to this change.

No commit accompanies this reply because there is nothing left to fix; the fix is already in the branch.

— sent from cool-wren-467

@briansrls
briansrls merged commit 3578097 into main Jul 20, 2026
1 of 2 checks passed
@briansrls
briansrls deleted the session/cool-wren-467 branch July 20, 2026 18:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant