Skip to main content

jit_string_concat

Function jit_string_concat 

Source
#[unsafe(no_mangle)]
pub extern "C" fn jit_string_concat( a_bits: u64, a_kind_code: u8, b_bits: u64, b_kind_code: u8, ) -> u64
Expand description

Concatenate two operand values into a freshly allocated Arc<String> carrier. Used by the MIR-lowering path for BinOp::Add when either operand has NativeKind::String (the compile_string_concat site in mir_compiler/rvalues.rs), which covers str + str directly and the f-string interpolation chain emitted by lower_formatted_string (crates/shape-vm/src/mir/lowering/expr.rs:720).

§W15.2-LANG-7 jit-print-fstring close — producer-side carrier-shape fix

ADR-006 §2.7.5 / §2.7.7 producer-side stamp. Pre-fix the FFI took (a_bits, b_bits) -> u64, decoded each via heap_kind(bits) (a NaN-tag probe — the deleted-W-series shape per CLAUDE.md “Forbidden Patterns” #4) and returned box_string(out) — a NaN-boxed UnifiedValue<Arc<String>> allocation. But the JIT-side String carrier per ADR-006 §2.7.5 is Arc::into_raw(Arc<String>) as u64 — a raw Arc pointer, NOT a NaN-box. Every downstream consumer reads the result with the canonical NativeKind::String carrier shape: jit_print_str calls print_kinded_inner(bits, NativeKind::String) which constructs KindedSlot::new(ValueSlot::from_raw(bits), String), and format_kinded’s String arm dereferences as &Arc<String>. A NaN-boxed pointer in that slot dereferences a NaN bit-pattern as a String struct’s ptr/cap/len — printing garbage memory bytes (the empirical surface at let m = "a"+"b"; print(m) pre-fix).

Per W15.1 audit §6.7 (FIX-LANGUAGE W15.2-LANG-7) the post-fix shape:

  • Inputs carry (a_bits, a_kind_code, b_bits, b_kind_code) — the parallel-track encoding at super::stack_kind_code per ADR-006 §2.7.7/Q9. Kind codes are stamped at JIT-compile time from the producer-side operand_slot_kind result in compile_string_concat — same kind-source discipline as jit_v2_make_result_ok’s payload_kind_code.
  • Each operand decodes per its kind: String → adopt the raw Arc pointer via Arc::from_raw and read &str; scalar arms format directly from the raw native value. No tag-bit dispatch, no NaN-tag probe.
  • Return is Arc::into_raw(Arc::new(out)) as u64 — the §2.7.5 String carrier shape, matching every downstream consumer (jit_print_str, arc_string_retain/_release, KindedSlot::Drop for NativeKind::String).

Strong-count contract. Each NativeKind::String operand carries one strong-count share (the producer-side per-consumption retain at mir_compiler/ownership.rs:486 for MirConstant::Str, or the compile_operand’s Copy(place) retain at line 239). The FFI consumes both shares via Arc::from_raw (which adopts the share) and drops them at scope end. The returned Arc::into_raw(Arc::new( out)) carries one fresh share that the caller installs in the destination slot with kind NativeKind::String; subsequent arc_string_release retires the share at slot-drop time.

Forbidden under W15.2-LANG-7 close (refusal log per CLAUDE.md “Renames to refuse on sight” + ADR-006 §2.7.5 producer-side stamp):

  • Returning box_string(out) — wrong carrier shape; the consumer would dereference a NaN-boxed pointer as Arc<String> raw bits and segfault on the next print (the W15.1 audit §6.7 empirical surface).
  • heap_kind(bits) probe on a kind-stamped operand — the deleted- W-series tag-bit dispatch. The producer-side stamp from compile_string_concat’s operand_slot_kind IS the discriminator.
  • Bool-default for an unknown kind code — surface-and-stop per §2.7.7 #9. Producing a malformed Arc on a kind-source gap masks the bug downstream.
  • Defection-attractor descriptors (broader-family regex per CLAUDE.md §“Renames to refuse on sight”) for this producer-side carrier-shape fix — refused on sight. Describe the change by name (the deleted box_string shape replaced by the §2.7.5 Arc::into_raw(Arc<String>) shape) or by deletion-fate (the deleted-W-series heap_kind-probe path).