Skip to content

gen-rust: a []T parameter written by the body is emitted as Vec<T> by value, so the caller never sees the writes #3402

Description

@gHashTag

The Rust backend renders every []T parameter as Vec<T> — by value, without mut — and then emits buf[i] = x into it.

Measured on master

  • 189 specs declare a slice parameter; 174 parse.
  • 23 of those emit Rust that index-assigns into a slice parameter.
  • 0 of the 23 compile. Not one.
  • Corpus-wide, E0382 (use of moved value) plus E0596 (cannot borrow as mutable) appear in 33 files, 143 diagnostics.

Instrument: rustc --edition 2021 --crate-type lib --crate-name g --emit=metadata over the emitted Rust of all 650 specs, with a control that accepts a valid file and rejects an invalid one. The --crate-name is load-bearing: without it rustc derives the crate name from the filename, rejects the . in .t27, and nothing is ever compiled — an earlier run of this measurement read 0 for every binary for that reason alone.

Two defects, not one

  1. It does not compile. pub fn byte_to_trits(byte: u8, trits: Vec<i32>, len: usize) then trits[i] = ... is E0382/E0596.
  2. Even if it compiled, it would be wrong. The writes would land in a moved copy and the caller would see nothing. That is the more serious half, because a plausible future fix — adding mut to the binding — makes it compile and leaves it silently wrong.

The other backends do not have this problem: the C backend passes a pointer and the Verilog backend gives the caller its writes, so the Rust column was the one disagreeing with the rest. For a project whose stated property is cross-target agreement, that is the shape that matters.

The chain, which a per-function scan cannot see

char_to_trits never assigns into its own trits — it hands it to byte_to_trits, which does. Marking only the direct writers gives the caller a Vec<i32> and the callee a &mut [i32], and the call between them is E0308: expected &mut [i32], found Vec<i32>. The marking has to reach a fixpoint over calls.

Separately: .len on a slice

Thirteen files newly report error[E0615]: attempted to take value of method len once they get far enough to be type-checked — while ((i < DEQUE_MAX_SIZE) && (i < data.len)). The emitted line is byte-identical to what master emits; those files simply died earlier before. Rust exposes length as a method, data.len(). The Zig backend documents the mirror-image of this at its own .len site (Zig exposes it as a field). Filed here as a separate defect rather than folded into the parameter change.

No activity

Activity on this issue will appear here.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions