Area
- Compiler (frontend/backend/codegen)
Summary
Expected: when an external Rust associated function takes a generic by-value parameter such as prost::Message::decode(buf: impl Buf), Incan should emit a valid by-value argument shape, or a valid mutable borrow if the selected Rust API requires &mut T.
Actual: Incan accepts the source, but generated Rust adds a shared borrow to the decode argument. For Cursor<Vec<u8>>, this emits FileDescriptorSet::decode(&cursor), which fails because &Cursor<Vec<u8>> does not implement bytes::Buf. The same shape surfaced in InQL as ConsumerPlan::decode(&encoded.as_slice()), producing &&[u8].
This appears to come from the external-method fallback that treats methods named decode as requiring a shared borrow when Rust metadata resolves the parameter as a generic shape. That heuristic is wrong for prost::Message::decode(buf: impl Buf).
Reproduction steps
Minimal project:
incan.toml
[project]
name = "prost_decode_repro"
version = "0.1.0"
[rust-dependencies]
prost = "0.14"
prost-types = "0.14"
src/lib.incn
from rust::prost import DecodeError, Message
from rust::prost_types import FileDescriptorSet
from rust::std::io import Cursor
pub def decode_descriptor(data: bytes) -> Result[FileDescriptorSet, DecodeError]:
mut cursor = Cursor.new(data)
return FileDescriptorSet.decode(cursor)
Run:
incan build --lib src/lib.incn target/lib
Generated Rust excerpt:
pub fn decode_descriptor(data: Vec<u8>) -> Result<FileDescriptorSet, DecodeError> {
let mut cursor = Cursor::new(data);
return FileDescriptorSet::decode(&cursor);
}
Output / logs
error[E0277]: the trait bound `&std::io::Cursor<Vec<u8>>: Buf` is not satisfied
--> src/lib.rs:12:38
|
12 | return FileDescriptorSet::decode(&cursor);
| ------------------------- ^^^^^^^ the trait `Buf` is not implemented for `&std::io::Cursor<Vec<u8>>`
| |
| required by a bound introduced by this call
|
= help: the following other types implement trait `Buf`:
&[u8]
&mut T
Box<T>
BytesMut
VecDeque<u8>
prost::bytes::Bytes
prost::bytes::buf::Chain<T, U>
prost::bytes::buf::Take<T>
note: required by a bound in `decode`
--> prost-0.14.3/src/message.rs:105:29
|
105 | fn decode(mut buf: impl Buf) -> Result<Self, DecodeError>
| ^^^ required by this bound in `Message::decode`
InQL surfaced the same bug while compiling src/session/datafusion_backend.incn:
error[E0277]: the trait bound `&&[u8]: Buf` is not satisfied
--> src/session/datafusion_backend.rs:461:32
|
461 | match ConsumerPlan::decode(&encoded.as_slice()) {
| -------------------- ^^^^^^^^^^^^^^^^^^^ the trait `Buf` is not implemented for `&&[u8]`
Environment
OS: macOS / Darwin, local development workspace
Rust: rustc 1.96.0-nightly (362211dc2 2026-03-24)
Incan: 0.3.0-dev.50, commit 8a9860d5
Command: incan build --lib src/lib.incn target/lib
Blocking status: blocks the InQL #25 v0.3 showcase transition unless InQL carries a temporary Rust helper around protobuf decode. I have not applied such a workaround yet.
Area
Summary
Expected: when an external Rust associated function takes a generic by-value parameter such as
prost::Message::decode(buf: impl Buf), Incan should emit a valid by-value argument shape, or a valid mutable borrow if the selected Rust API requires&mut T.Actual: Incan accepts the source, but generated Rust adds a shared borrow to the
decodeargument. ForCursor<Vec<u8>>, this emitsFileDescriptorSet::decode(&cursor), which fails because&Cursor<Vec<u8>>does not implementbytes::Buf. The same shape surfaced in InQL asConsumerPlan::decode(&encoded.as_slice()), producing&&[u8].This appears to come from the external-method fallback that treats methods named
decodeas requiring a shared borrow when Rust metadata resolves the parameter as a generic shape. That heuristic is wrong forprost::Message::decode(buf: impl Buf).Reproduction steps
Minimal project:
incan.tomlsrc/lib.incnRun:
Generated Rust excerpt:
Output / logs
InQL surfaced the same bug while compiling
src/session/datafusion_backend.incn:Environment
OS: macOS / Darwin, local development workspace
Rust:
rustc 1.96.0-nightly (362211dc2 2026-03-24)Incan:
0.3.0-dev.50, commit8a9860d5Command:
incan build --lib src/lib.incn target/libBlocking status: blocks the InQL #25 v0.3 showcase transition unless InQL carries a temporary Rust helper around protobuf decode. I have not applied such a workaround yet.