6. Ownership, moves, and clones
This lesson follows the exact Zryna 0.2.1 ownership surface at 841c8aee901782c9f7bf442bfe8eb2fe6b7f6446, documented in M3_OWNED_DATA_SEMANTICS.md.
Look again at the supplied String example:
export function text(): i32 { let first: String = "héllo"; const copy: String = clone(first); const moved: String = copy; first = "new"; const joined: String = concat(first, moved); return 17;}String, Vec, and aggregates containing owned values are non-Copy:
clone(first)makes a distinct owned String and leavesfirstusable.const moved: String = copytransfers ownership;copyis no longer usable.- assignment into
firstreplaces and cleans up its old owned value. - values still owned at scope exit are cleaned up in verified reverse order.
Run the wrapper on both targets:
& $zryna run src/string.zry --project-root "$workspace\tutorial-ownership" --profile data-ownership-v1 --target javascript --name ownership-js --export score& $zryna run src/string.zry --project-root "$workspace\tutorial-ownership" --profile data-ownership-v1 --target webassembly --name ownership-wasm --export scoreExpected observations are javascript: i32 17 and webassembly: i32 17. The sentinel proves that execution reached the return after the owned operations; the release conformance suite, not the sentinel alone, proves exact cleanup behavior.
Common error: use after move
Section titled “Common error: use after move”This private function is rejected:
function invalid(): String { const text: String = "owned"; const moved: String = text; return text;}text was consumed by the move. Diagnostic ZRYNA-M3011 tells you to return moved, or initialize moved with clone(text) when both owners are needed. Zryna does not add an implicit clone.
Exercise
Section titled “Exercise”Trace the owners after each line of the valid String example. At the end, which names still own a value, and which name was consumed?