Found by adversarial review of #3403. Latent: population 0 in todays emitted Rust. Filed so it is not discovered later as a surprise.
The shape
specs/isa/ternary_memory.t27:226:
fn mem_copy(dst: []TernaryWord, dst_addr: u32, src: []TernaryWord, src_addr: u32, count: usize) -> bool
Its body carries an explicit two-branch overlap handler — "Handle overlap (copy direction matters)" — forward when dst_addr < src_addr, backward otherwise. That branch exists for exactly one situation: dst and src are the same array. And the spec exercises it that way, twice:
- line 388,
test mem_block_copy_overlap → mem_copy(memory, 0, memory, 1, 2)
- line 472,
invariant mem_copy_handles_overlap → mem_copy(memory, 0, memory, 1, 2)
What #3403 does to it
dst is index-assigned so the fixpoint marks it; src is not. The emitted signature becomes
pub fn mem_copy(dst: &mut [TernaryWord], dst_addr: u32, src: &[TernaryWord], src_addr: u32, count: usize) -> bool
and the spec own call is then unrepresentable in safe Rust:
error[E0502]: cannot borrow `memory` as immutable because it is also borrowed as mutable
mem_copy(&mut memory, 0, &memory, 1, 2)
The backward-copy branch becomes dead by type. C takes two pointers and can express the call; Verilog can too. So this is a place where the four backends do not agree about what the spec means — the property the project exists to hold.
Why it is not urgent, stated precisely
It becomes live the moment tests or invariants are lowered to Rust — which is a direction this project wants to go, so the cost is deferred rather than avoided.
Options, none of them free
- Refuse the shape. When one function has both a written slice parameter and a read slice parameter of the same element type, the
&mut/& split cannot express a same-array call. Leave that function parameters as they were and declare it on the existing NOT LOWERED BY THIS BACKEND header line, so the omission is disclosed rather than silent.
- Lower it as one slice plus indices, matching what
slice::copy_within does. That changes the spec surface, not just the backend.
- Accept it and say so in the spec, marking
mem_copy as a construct whose Rust lowering is weaker than its C and Verilog lowerings.
Option 1 is the one that keeps the honesty property this repository already has a mechanism for. Which of the three is the owner call.
Found by adversarial review of #3403. Latent: population 0 in todays emitted Rust. Filed so it is not discovered later as a surprise.
The shape
specs/isa/ternary_memory.t27:226:Its body carries an explicit two-branch overlap handler — "Handle overlap (copy direction matters)" — forward when
dst_addr < src_addr, backward otherwise. That branch exists for exactly one situation: dst and src are the same array. And the spec exercises it that way, twice:test mem_block_copy_overlap→mem_copy(memory, 0, memory, 1, 2)invariant mem_copy_handles_overlap→mem_copy(memory, 0, memory, 1, 2)What #3403 does to it
dstis index-assigned so the fixpoint marks it;srcis not. The emitted signature becomesand the spec own call is then unrepresentable in safe Rust:
The backward-copy branch becomes dead by type. C takes two pointers and can express the call; Verilog can too. So this is a place where the four backends do not agree about what the spec means — the property the project exists to hold.
Why it is not urgent, stated precisely
testand aninvariant, andgen-rustlowers neither.mem_copyand zero call sites.E0502count in that file: 0 on master, 0 after fix(rust-backend): a written []T parameter is &mut [T], to a fixpoint #3403. Measured, not assumed.It becomes live the moment tests or invariants are lowered to Rust — which is a direction this project wants to go, so the cost is deferred rather than avoided.
Options, none of them free
&mut/&split cannot express a same-array call. Leave that function parameters as they were and declare it on the existingNOT LOWERED BY THIS BACKENDheader line, so the omission is disclosed rather than silent.slice::copy_withindoes. That changes the spec surface, not just the backend.mem_copyas a construct whose Rust lowering is weaker than its C and Verilog lowerings.Option 1 is the one that keeps the honesty property this repository already has a mechanism for. Which of the three is the owner call.