Area
- Compiler (frontend/backend/codegen)
Summary
Expected: Incan should compile record-field access from loop items without emitting Rust that moves a non-Copy field out of a shared reference. If a field is first borrowed for a helper call and later needs to be stored in a list, the compiler should clone/own the field consistently or otherwise emit valid Rust.
Actual: a loop over list[Assignment] can borrow assignment.output_name for a helper call, then assigning or appending assignment.output_name emits Rust that tries to move the String field out of assignment, which is behind a shared reference. Rust compilation fails with E0507.
This is related to the closed ownership-inference umbrella issue #121, but it is a concrete remaining codegen failure on incan 0.3.0-rc1.
Reproduction steps
- Create
/private/tmp/incan-loop-field-move-repro/repro.incn:
@derive(Clone)
model Assignment:
output_name: str
def names(assignments: list[Assignment]) -> list[str]:
"""Collect names from assignment records."""
mut output_names: list[str] = []
for assignment in assignments:
existing_idx = index_of_name(output_names, assignment.output_name)
if existing_idx >= 0:
output_names[existing_idx] = assignment.output_name
else:
output_names.append(assignment.output_name)
return output_names
def index_of_name(names: list[str], name: str) -> int:
"""Return the first matching name index, or `-1` when absent."""
for idx, current in enumerate(names):
if current == name:
return idx
return -1
def main() -> None:
"""Exercise record-field access from a list loop item."""
result = names([Assignment(output_name="amount")])
assert result[0] == "amount"
- Run:
/Users/danny/Development/encero/incan/target/debug/incan build /private/tmp/incan-loop-field-move-repro/repro.incn /private/tmp/incan-loop-field-move-repro/out
Output / logs
Generated Rust project in: /private/tmp/incan-loop-field-move-repro/out
Building...
Build failed:
Compiling repro v0.3.0-rc1 (/private/tmp/incan-loop-field-move-repro/out)
error[E0507]: cannot move out of `assignment.output_name` which is behind a shared reference
--> src/main.rs:22:17
|
22 | ) = assignment.output_name;
| ^^^^^^^^^^^^^^^^^^^^^^ move occurs because `assignment.output_name` has type `String`, which does not implement the `Copy` trait
|
help: consider cloning the value if the performance cost is acceptable
|
22 | ) = assignment.output_name.clone();
| ++++++++
For more information about this error, try `rustc --explain E0507`.
error: could not compile `repro` (bin "repro") due to 1 previous error
Original InQL trigger is src/projection_builders.incn on InQL PR dannys-code-corner/InQL#29. Removing the explicit str(assignment.output_name) materialization from project_output_columns(...) produces the same Rust error during make build.
Environment
OS: macOS / zsh local development environment
Rust: rustc 1.96.0-nightly (362211dc2 2026-03-24)
Incan: incan 0.3.0-rc1
Incan commit: 939ff58e0013fb342c256205ad83383f21626d44
Command:
/Users/danny/Development/encero/incan/target/debug/incan build /private/tmp/incan-loop-field-move-repro/repro.incn /private/tmp/incan-loop-field-move-repro/out
Blocking / workaround status
Non-blocking for InQL PR #29 because the field can be explicitly materialized once before assignment/append:
output_name = str(assignment.output_name)
if existing_idx >= 0:
output_columns[existing_idx] = output_name
else:
output_columns.append(output_name)
That workaround preserves semantics, but it should remain tracked as a compiler/codegen bug rather than treated as ordinary InQL style.
Area
Summary
Expected: Incan should compile record-field access from loop items without emitting Rust that moves a non-
Copyfield out of a shared reference. If a field is first borrowed for a helper call and later needs to be stored in a list, the compiler should clone/own the field consistently or otherwise emit valid Rust.Actual: a loop over
list[Assignment]can borrowassignment.output_namefor a helper call, then assigning or appendingassignment.output_nameemits Rust that tries to move theStringfield out ofassignment, which is behind a shared reference. Rust compilation fails withE0507.This is related to the closed ownership-inference umbrella issue #121, but it is a concrete remaining codegen failure on
incan 0.3.0-rc1.Reproduction steps
/private/tmp/incan-loop-field-move-repro/repro.incn:Output / logs
Original InQL trigger is
src/projection_builders.incnon InQL PR dannys-code-corner/InQL#29. Removing the explicitstr(assignment.output_name)materialization fromproject_output_columns(...)produces the same Rust error duringmake build.Environment
OS: macOS / zsh local development environment
Rust:
rustc 1.96.0-nightly (362211dc2 2026-03-24)Incan:
incan 0.3.0-rc1Incan commit:
939ff58e0013fb342c256205ad83383f21626d44Command:
Blocking / workaround status
Non-blocking for InQL PR #29 because the field can be explicitly materialized once before assignment/append:
That workaround preserves semantics, but it should remain tracked as a compiler/codegen bug rather than treated as ordinary InQL style.