docs: BUGS.md — audited compiler bug inventory#2
Merged
Conversation
…low) White-box audit on 2026-06-10 against the release binary; all items reproduced. HIGH: prefix !/~ precedence inversion (silent wrong result); release-AOT integer overflow wrap vs interp/debug trap; read-param reassign -> E0308; untyped Some() bypasses arg type-check; turbofish struct ctor -> E0423. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Haofei
added a commit
that referenced
this pull request
Jun 13, 2026
…ument release fast path for package check #1 (List<T>.clone() etc.): `.clone()` on a builtin value type whose clone the checker resolves (List/Bytes/Buffer) typechecked via the Clone protocol but lowered to a dangling `List_clone`-style call -> rustc E0425. The lowerer now emits Rust's `.clone()` for these (they lower to Clone Rust types). Same frontend-accepts/ backend-fails class as the borrowed-match E0308 fix. Removes the need for manual copy helpers in source-shaped ports. Regression test in checker_lowering/stdlib. #2 (slow package check in debug): documented the release-binary fast path in README (Performance) and cross-referenced from BUGS.md RSS-11 — debug leaves the ~O(n^3) generic-substitution path unoptimized; release is usable. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
added a commit
that referenced
this pull request
Jun 13, 2026
…generic params, File.open effects - vm-jit: NativeModule::call now rejects an args slice whose length != the compiled function's n_params (the generated entry block reads exactly n_params words from args_ptr without bounding by n_args, so a short slice was an out-of-bounds read in a 'safe' API) — #1, the highest-severity finding. CompiledId now carries a per-module id so an id from another NativeModule is rejected instead of indexing the wrong table (#2). Tests: call_rejects_wrong_arg_count, call_rejects_id_from_another_module. - lowerer: builtin_generic_type_params mapped Result to [K,V] (Map's params); split so Result uses [T,E] — fixes silently-failing generic substitution for Result.map/map_error/and_then (#7). Unit-test guard added. - stdlib/fs/file.rssi: File.open/open_read/open_write now carry effects(native) so host file-resource creation is review-visible in the signature, consistent with the handle reads/writes (#6). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
added a commit
that referenced
this pull request
Jun 13, 2026
Controlled-assignment targets evaluate subexpressions (a field base, an index
expression) that are genuine reads of bindings. Several use/ident/effect/capture
passes only visited the assigned value, silently dropping those target reads.
Route them all through crate::hir::assign_target_reads / its AST analogue:
local.rs: collect_hir_stmt_idents, collect_hir_stmt_effect_events,
collect_hir_stmt_inline_capture_uses,
collect_closure_local_moved_uses_from_stmt,
collect_retained_closure_captures_from_stmt
body.rs: collect_stmt_uses, collect_spawn_capture_idents_from_stmt,
check_explicit_closure_captures_stmt
analyzer: check_match_exhaustiveness, check_unknown_bindings
This makes use-after-move, unknown-binding, capture, and effect analysis see
reads like obj/idx in 'obj.field[idx] = value' that were previously invisible.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
added a commit
that referenced
this pull request
Jun 13, 2026
Close the four remaining gaps in the dynamic-testing plan. #3 Metamorphic differential tests (tests/metamorphic.rs): for known-valid programs spanning the executable subset, apply semantics-preserving rewrites (reformat, trivia injection, unused local, top-level reorder, dead function) and require every backend still agrees AND produces the same output as the base; structure-preserving transforms must also leave the review classification unchanged. #7 Example-corpus differential execution (tests/examples_exec.rs): the static sweep already checks+lowers examples/scripts; this runs the pure synchronous subset across all backends and asserts agreement. The skip predicate is derived from the source (I/O, timing, async, plus one documented VM capability gap: struct-typed Map/Set keys in uop_interning). #5 JIT arithmetic-edge matrix (tests/jit_arithmetic_edges.rs): the edges the generative suite skips - i64 add/mul overflow, div/mod by zero, MIN/-1 div+mod (all trap cleanly), shift wrap, NaN, signed zero, float infinity (all agree). Each op lives in a pure helper called with read-args so the JIT actually compiles and guards it. #2 cargo-fuzz harness (fuzz/): a detached-workspace crate (never built by cargo build --workspace) with two libFuzzer targets - parse_check (front-end never-panics) and format_idempotent (format(format(x)) == format(x)). Adds common::differential::backends_agreed_stdout for the new sweeps. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 15, 2026
Remove completed entries (now in git history) and keep only open/partial work: - Dropped: symbol identity (#1), class/static members (#2, type-associated consts + static methods), clone consistency (#6), Option ergonomics (#7), plus the already-checked namespace isolation / pattern matching / tuples / lower_name. - Narrowed: type aliases -> generic aliases only; default args -> construction helpers only (defaults done); closures -> named function values. - A header now records what's done so far; 8 items remain. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 16, 2026
A left-linear chain of hundreds of `&&`/`||` lowered to a deeply-nested Rust expression that overflows rustc's recursive parser/type-checker (the RUST_MIN_STACK=2g workaround). `&&`/`||` are associative for both value AND short-circuit/evaluation order, so the lowerer now emits a BALANCED tree (O(log n) nesting). The chain is collected iteratively (its left spine is the deep part) so this pass doesn't recurse n-deep. Generated crates also now allow(unused_parens) for the (benign) regrouping parens. Verified: a 400-deep `&&` chain compiles+runs on the DEFAULT stack (no RUST_MIN_STACK) with VM==compiled results; balanced-shallow-output lowering test (checker_lowering); full vm_eval_parity (87) + vm_eval (17) green; golden header updated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 16, 2026
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 20, 2026
Second review pass (medium/low): - §3.2: clarify that new read helpers reuse the §7.2 fallback *proof* but NOT the ABI — current helpers (field_int/list_len/list_get_int) are Int-only and return a single i64, so non-Int and heap-returning reads (String, nested List/Struct, map values) are a real ABI design task (typed result / handle for heap results, extended handle domain) with its own §7.1 amendment + tests. - Refresh stale regression offenders in plan §0.2/§3.0 and README findings #1/#2 from baseline-20260620.json: list_sort 1.31 / map_int 1.19 / json 1.48 / dynamic_closure 1.66 / string_text 1.80 no longer match; current worst are tier-0 native_read_heap 2.59 / nested_struct_field 1.36 and native task_group_spawn 1.58 / bytes_scan 1.42. Added "re-read JSON before quoting". - Correct the "native near-Rust" framing with nat/rust (not reg/rust): scalar ~1.4x but read_heap ~13.3x. README table now carries an explicit nat/rust column; plan numbers match the committed baseline. - Mark plan status in progress (Phase 0 done; Set/task_group fixed) instead of "draft / not started". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 24, 2026
OSR now fires automatically when a loop is hot, not just under RSS_JIT_OSR. Per-function OSR-candidate state is lazily computed + cached (NotCandidate pays one hoisted check per call; only candidate loops count backedges), and a backedge counter triggers try_osr at a threshold — after which the loop runs native, so the counter cost is bounded to the warm-up iterations. RSS_JIT_OSR stays as the eager/force path. Default differential (now auto-OSR) byte-identical; non-OSR interpreter dispatch (pure_loop_sum/bool_logic_loop) non-regression measured. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jun 24, 2026
…broadening) A captured f64 is bit-reinterpreted from its i64 capture slot (not integer- converted), reusing the native f64<->i64 bitcast convention, so a closure capturing Floats inlines inside an OSR loop. Int/Bool captures unchanged; non-scalar captures still bail. OSR differential byte-identical on/off (float parity exact); 10.3x faster on osr_float_closure_loop. Positive + negative tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jul 1, 2026
…uePush*Float) Item #2 of the remaining-issues list: collection element-type breadth for Float VALUES, riding the float-arg helper ABI. Three clean HostCall mirrors of ListPushFloat: - MapInsertFloat: insert a Float value into an Int-keyed Map<Int, Float>. - DequePushBackFloat / DequePushFrontFloat: push a Float onto a Deque<Float>. Each: vm-jit macro row + Fn type + struct field + heap_effect(MutatesInput) set + test noop; reg_vm host impl (journaled write of VmValue::Float, bails on a wrong- value-type collection) + wiring; translate value-type-flows-in-inference + helper selection by float(value) across both whole-function and OSR lowering arms (int_or_free keeps the Int/unconstrained path). Deliberately deferred (documented as the demand tail): float-KEYED collections (Set<Float>, SortedSet/SortedMap with Float keys) need float-key hashing/ordering with NaN semantics; the Map/Deque READS (MatchMapGetFloat, Deque pop) need a new value-typed JitInstr / Option result. The mechanical write pattern here applies directly when those are added. Verify (Docker dev): differential 33/0, runtime 397/0 (new jit_acceptance_runs_float_map_and_deque_helpers runs natively), vm-jit 83/0, reg_vm lib 31/0 default, default+native builds and clippy clean. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jul 1, 2026
…#4 shipped) Audit of the 9-item JIT follow-ups roadmap found the planning docs were stale: items #2/#3/#4/#5 were already shipped this session. Verified each green and corrected the docs to match reality. - jit_acceptance: add two nested-loop OSR regression tests (native_osr_nested_inner_loop_matches_interpreter + ..._with_dirty_outer_...) — both byte-parity with the interpreter and osr_entries > 0. The OSR pipeline is already multi-loop-aware (detect_natural_loops/select_osr_candidate_loop); detect_single_natural_loop is diagnostics-only, not the OSR gate. - vm-optimizing-jit-plan: J0.4 row → S0–S3 shipped (10 AllocatesResult helpers, mem_budget exact via Model-A refusal, §7.2 force-deopt-tested); S4 still future. - jit-followups-roadmap (new): #2 (deque-pop fusion, OSR in-region path), #3 (flat-list read inlining), #4 (nested-loop OSR), #5 (allocate-only heap writes) marked done; remaining = #1 (on-demand), #3-remainder flat-struct, string split-fold, and the hard precise-deopt main line #7→#6→#8. Runtime suite 403 passed (only red = known env-broken jit_perf_gate baseline); vm-jit lib 83/0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jul 1, 2026
…n at runtime (item #2) The report's per-function "declined by cost model" verdict re-derived the profitability from a bare re-translation, which loses profile-guided PICs (no profile feedback at report time) — so the very case that most often stays interpreted was not attributed. Now `consult_profitability` takes the function name and records it in a new `unprofitable_declined_fns` map (fn name → first decline reason) as the run happens — ground truth. The report reads that map for the per-function verdict instead of re-deriving, so a profile-guided PIC decline is now correctly attributed to its function. `report` mode's per-region log line also gains the `fn=...` tag, and the map is exposed in `to_json`. Test: report_explains_cost_model_decline_for_polymorphic_pic now additionally asserts the per-function `not native: declined by cost model` line (previously only the summary block was reliable). Verified: clippy 0; lib 276/0; runtime 453/0 (incl. all 11 report tests); differential 33/0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Haofei
pushed a commit
that referenced
this pull request
Jul 1, 2026
…quisite) Item #2 (shared transform driver) is explicitly gated on "add targeted deopt-stress tests first" because the driver would touch ip-map composition. Adds that test: a DEEP multi-transform OSR region — an inlined leaf call + a non-escaping Option<Int> + a non-escaping Result<Int,Int> (user variant), all dissolved by scalar replacement in one hot loop, so several region transforms and their ip-maps compose. Run through every fast backend INCLUDING deopt-every-safepoint (which bails at each native safepoint and resumes via the composed ip-map). Byte-identical parity + osr_entries>0 is the guard: a wrong ip-map composition — the exact failure a shared transform driver could introduce — would diverge here. This makes the driver refactor itself verifiable when undertaken (the driver is a larger, deopt-critical, zero-perf-gain change and is deliberately scoped as its own effort now that its safety net exists). Verified: the new test passes (deopt-every parity holds; OSR entered). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
White-box audit of the rss compiler on 2026-06-10; every item reproduced against the release binary (commit
f5fab92).HIGH (5): prefix
!/~precedence inversion (silent wrong result); release-AOT integer overflow wraps while interp/debug trap;read-param reassignment lowers to non-compiling Rust (E0308); untypedSome()local bypasses arg type-check; turbofish struct ctor → E0423.MEDIUM (5):
<</>>share the comparison tier; multi-dot number literals accepted; mixed numeric operands skip check; reg_vm float==is bitwise (diverges from AOT IEEE); generic ctor drops its type arg.LOW (1): ~O(n³)
checkblowup on nested generics.Each entry has source location, root cause, a minimal repro, expected-vs-actual, and a suggested fix. See
BUGS.md.🤖 Generated with Claude Code