Conversation
Copilot stopped work on behalf of
eval-exec due to an error
February 7, 2026 16:19
eval-exec
added a commit
that referenced
this pull request
Apr 9, 2026
GNU src/search.c:2485-2505 classifies the matched text for the
FIXEDCASE=nil branch of replace-match by checking the buffer's
syntax table:
if (SYNTAX(prevc) != Sword
&& !(case_symbols_as_words && SYNTAX(prevc) == Ssymbol))
some_nonuppercase_initial = 1;
Audit findings #14 and #20 in drafts/regex-search-audit.md flagged
that neomacs's apply_replace_match_case used Rust's Unicode
is_alphanumeric() for the previous-character check and never read
case-symbols-as-words at all (the variable existed only in the
doc table).
This patch:
1. casefiddle.rs::apply_replace_match_case now delegates to a new
apply_replace_match_case_with that takes a FnMut(char) -> bool
word predicate. The default predicate uses GNU's standard
syntax table baseline (ASCII letters and digits + $ %, the
chars neomacs SyntaxTable::new_standard puts in Sword).
2. regex.rs gains compute_replacement_with_syntax,
replace_match_buffer_with_syntax, and
replace_match_string_with_syntax. They thread an
Option<&SyntaxTable> and a case_symbols_as_words: bool down to
apply_match_case_with_syntax, which builds a closure that
consults table.char_syntax(ch) and accepts SyntaxClass::Symbol
when case_symbols_as_words is on. The non-_with_syntax variants
still exist as wrappers that pass None/false to keep external
call sites unchanged.
3. builtins/search.rs::builtin_replace_match reads
case-symbols-as-words from the dynamic environment and threads
the bool through builtin_replace_match_with_state_and_flags,
which routes string replacements to
replace_match_string_with_syntax (None table for the pure
string-arg path, Some(&buf.syntax_table) for the buffer-source
path) and routes buffer replacements to
replace_match_buffer_with_syntax. The legacy
builtin_replace_match_with_state delegates to the new
_and_flags helper with case_symbols_as_words=false so the
bytecode VM call site continues to work.
Existing tests stay green; the change is shape-preserving for
the default case-symbols-as-words=nil baseline (which is GNU's
default too) and only diverges from the previous behavior for
inputs where Rust's Unicode is_alphanumeric disagrees with the
buffer's standard syntax table.
eval-exec
added a commit
that referenced
this pull request
Apr 9, 2026
) GNU re_compile_fastmap at regex-emacs.c:3170-3186 reads the buffer syntax table for both \sX and \SX, iterating every ASCII byte and asking the table what class it has. neomacs's compile_fastmap hardcoded Rust Unicode predicates for syntax classes 0-3 (Whitespace/Punctuation/Word/Symbol) and silently dropped classes 4-15 (Open/Close/Quote/StringDelim/Math/Escape/CharQuote/ Comment/EndComment/InheritStd/CommentFence/StringFence). For patterns like \s( the fastmap was empty, which made the matcher do unnecessary work but did not break correctness — see audit finding #16 in drafts/regex-search-audit.md. This patch: 1. Factors a fastmap_for_syntax_class helper that takes a class byte and a negate flag, decodes the SyntaxClass via SyntaxClass::from_code, walks 0..=127 against SyntaxTable::new_standard, and conservatively allows every non-ASCII byte (since the matcher does the per-character syntax lookup at match time). Unknown class bytes fall through to the GNU "set every byte" fallback. 2. The SyntaxSpec and NotSyntaxSpec arms of compile_fastmap delegate to the new helper. The duplicated Rust-Unicode classification block is gone. We use the standard syntax table here because compile_fastmap runs without a per-buffer table in scope; this matches GNU's behavior for the standard table and is the same baseline used by apply_replace_match_case (audit #14). All existing regex tests stay green.
eval-exec
added a commit
that referenced
this pull request
May 30, 2026
DIVERGENCE #14: overlay priority zero vs negative Neomacs: ERR (args-out-of-range 35 35) GNU Emacs: ERR (args-out-of-range 35) Same args-out-of-range format divergence pattern. 7 pass, 1 diverge. 632 total, 14 divergences.
eval-exec
added a commit
that referenced
this pull request
Jul 3, 2026
…xes (R1c-sidecar) Widens AOT from the pure subset to reloc- and symbol-bearing leaves (the real loadup functions), and folds in the correctness fixes from the adversarial audit. PER-THREAD SIDECAR: session-specific base addresses (reloc_base + deopt buffers) can't be baked into a .so loaded cross-session, and the buffers are per-(thread, leaf) (thread-local heap + COMPILED). So the entry ABI gains a 4th arg — a Rust- owned Box<LeafSidecar> field on the (already per-thread) CompiledLeaf, passed by invoke_native via &self (reentrancy-safe per-frame). JIT declares-and-ignores the 4th param (keeps iconst, byte-identical); AOT loads bases from it. aot:bool flag gates ONLY base materialization. All 3 entry-ptr transmute sites audited + updated. AUDIT FIXES (the cross-session correctness class the pure-subset tests missed): - #16 CRITICAL — symbols baked session-specific SymId. const_relocs_for_aot now relocs non-nil/t symbols BY NAME (recipe -> intern at load), not iconst. nil/t (pre-seeded SymId 0/1) + chars (fixnums) stay baked. The gensym hole the fix opens is closed: write_value_recipe rejects non-canonical (uninterned) symbols via is_canonical_id -> leaf stays JIT. - #17 — mir_is_aot_runnable rejects CallBuiltin/CallBuiltinSym (Op-Debug hash is non-canonical for raw SymId); guard noted for future SymId-bearing ops. - #15 — ABI_TAG salted with the full declare_rt_refs shim set. - #4-9/#12 — fail-closed descriptor: validate magic/version/ABI_TAG before recipe_len, MAX_RECIPE_LEN cap, checked_add, bounded recursion + length checks (rebuild_value -> Option -> JIT fallback, never abort). - #1/#2/#10/#11 — doc-invariant fixes (false "COMPILED never evicts" spec-slot justification -> "heap identity stable during native execution"; LOADED_UNITS outlives COMPILED; alloc-black cross-link). DEFERRED (flagged): call-bearing AOT (precise-deopt-across-call + host shim export, task #32); load-time const-vec recheck (#11/#14, defense behind trusted-dir). Validated: AOT-off full suite byte-identical (7471 pass; the 1 process/timer FAIL is a confirmed env flake — 4/4 in isolation, runs interpreted so the codegen change can't reach it; 5 benign load-test timeouts). NEOVM_AOT=force reloc+symbol gate green (13 AOT tests incl both #16 proofs + gensym-rejected; 119 jit+aot unit).
eval-exec
added a commit
that referenced
this pull request
Jul 3, 2026
… R1c (#32) Completes R1c's runnable subset: AOT now covers call/apply- and reloc/symbol-bearing leaves (the real loadup functions), with the sidecar-audit fixes folded in. CALL-BEARING: - Host shim export: the 6 MIR shims are #[unsafe(no_mangle)] pub extern "C" + a #[used] anchor (survives --gc-sections); build.rs emits cargo:rustc-link-arg-tests =-rdynamic + --export-dynamic-symbol=<shim> (the `wild` linker needs the explicit per-symbol export beyond -rdynamic) so a dlopen'd call/cons .so resolves its neovm_jit_* imports instead of aborting on first call (audit #3). - mir_is_aot_runnable widened to Call/Apply + escaping-cons (still rejects CallBuiltin/Sym, #17). Descriptor carries has_precise_deopt/max_depth/ has_side_effects from the MIR. The precise-deopt-across-a-real-call path (already lowered in the sidecar via the sidecar spill/meta bases) is enabled + proven: resume-at-pc, the call's side effect runs EXACTLY once. AUDIT FIXES (sidecar audit wuymgwd3k): - #A eq-identity (Important): AOT no longer rebuilds string/cons constants as fresh objects (which diverged from interp/JIT on eq via deopt/escape). The load path now sources reloc_data from the LIVE func.constants (re-collected in emit-time order) — eq-identical, exactly like the JIT tier. The descriptor recipe is demoted to VERIFICATION (re-encode the live reloc set, compare to the .so's recipe; mismatch → JIT), which ALSO closes the const-vec-recheck + truncated-hash-collision gaps (#11/#14) and simplifies GC (reloc consts are already-live/rooted). - #B non-UTF-8 (Important): write_value_recipe encoded names via UTF-8 and PANICKED on raw-byte elisp names (reachable every cache miss). Now byte-faithful (resolve_sym_lisp_string / LispString::from_emacs_bytes) — round-trips any name, never panics. Strings too. - Minors: deopt-base iconst materialization restored to the COLD deopt block for aot=false (no JIT hot-path delta); checked_add on descriptor recipe_len; max_depth cap; allocate-black doc corrected to the real invariant. Validated: AOT-off full suite byte-identical (7470 passed, 0 real failures, 9 benign load::tests timeouts). Integration test tests/aot_call_bearing.rs (NEOVM_AOT=force + NEOVM_AOT_DIR via the public try_run_compiled path) proves interp==JIT==AOT for a call-bearing body INCLUDING side-effect-EXACTLY-once across a forced precise deopt AND eq-across-deopt (the #A proof). Builds clean. R1c complete (pure + reloc + symbol + call-bearing). Next: R2 (dump-time loadup AOT).
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.
Thanks for assigning this issue to me. I'm starting to work on it and will keep this PR's description up to date as I form a plan and make progress.
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.