Found by the srpc whole-crate transpile (mako crates/srpc), after #41/#42/#43 — the last blocker in the srpc.wire chain.
Repro (cross-module; same-module never materializes it because the callers there are tests):
// varint.rs
pub fn load32(buf: &[u8; 9]) -> i32 { buf[0] as i32 }
pub fn dump32(val: i32, buf: &mut [u8; 9]) -> usize { buf[0] = val as u8; 1 }
// serde.rs
use super::varint;
pub fn ser(v: i32) -> usize {
let mut b = [0u8; 9];
let n = varint::dump32(v, &mut b);
let _ = varint::load32(&b);
n
}
Parameter position lowers &[u8; 9] / &mut [u8; 9] as const std::array<uint8_t, 9>& / std::array<uint8_t, 9>&. Argument position lowers &b as rusty::as_slice(b) (a std::span<const u8>) and &mut b as &b (a raw pointer):
error: non-const lvalue reference to 'std::array<uint8_t, 9>' cannot bind to a temporary of type 'ArrayRepeatResult<unsigned char>*'
error: no viable conversion from 'std::span<const unsigned char>' to 'const std::array<uint8_t, 9>'
The two sides assume different models (array-ref vs slice-coercion). Options that keep the no-type-inference design: (a) argument-position &/&mut on an array-typed local emits the bare lvalue (binds either param model); (b) uniformly lower array-ref params as fixed-extent spans; (c) use the crate-mode collected signatures to pick per-callee. (a) looks smallest and always safe: a bare lvalue binds std::array& exactly, and where the callee really takes a span the existing implicit array→span conversion covers it.
Concrete failing corpus: srpc.wire.serde.cppm V32/V64 serialize/deserialize (varint::dump32(this->_0, &b) / varint::load32(rusty::as_slice(b))).
Found by the srpc whole-crate transpile (mako crates/srpc), after #41/#42/#43 — the last blocker in the srpc.wire chain.
Repro (cross-module; same-module never materializes it because the callers there are tests):
Parameter position lowers
&[u8; 9]/&mut [u8; 9]asconst std::array<uint8_t, 9>&/std::array<uint8_t, 9>&. Argument position lowers&basrusty::as_slice(b)(astd::span<const u8>) and&mut bas&b(a raw pointer):The two sides assume different models (array-ref vs slice-coercion). Options that keep the no-type-inference design: (a) argument-position
&/&muton an array-typed local emits the bare lvalue (binds either param model); (b) uniformly lower array-ref params as fixed-extent spans; (c) use the crate-mode collected signatures to pick per-callee. (a) looks smallest and always safe: a bare lvalue bindsstd::array&exactly, and where the callee really takes a span the existing implicit array→span conversion covers it.Concrete failing corpus:
srpc.wire.serde.cppmV32/V64 serialize/deserialize (varint::dump32(this->_0, &b)/varint::load32(rusty::as_slice(b))).