#[unsafe(no_mangle)]pub extern "C" fn jit_string_concat(
a_bits: u64,
a_kind_code: u8,
b_bits: u64,
b_kind_code: u8,
) -> u64Expand 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 atsuper::stack_kind_codeper ADR-006 §2.7.7/Q9. Kind codes are stamped at JIT-compile time from the producer-sideoperand_slot_kindresult incompile_string_concat— same kind-source discipline asjit_v2_make_result_ok’spayload_kind_code. - Each operand decodes per its kind:
String→ adopt the raw Arc pointer viaArc::from_rawand 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::DropforNativeKind::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 asArc<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 fromcompile_string_concat’soperand_slot_kindIS 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_stringshape replaced by the §2.7.5Arc::into_raw(Arc<String>)shape) or by deletion-fate (the deleted-W-seriesheap_kind-probe path).