Skip to content

feat(ownership): make move-out explicit in HIR and MIR - #404

Draft
dporkka wants to merge 15 commits into
fix/ownership-consumption-flowfrom
feat/ownership-explicit-moveout
Draft

dporkka wants to merge 15 commits into
fix/ownership-consumption-flowfrom
feat/ownership-explicit-moveout

Conversation

@dporkka

@dporkka dporkka commented Sep 18, 2026

Copy link
Copy Markdown
Collaborator

Summary

Implements #402 Phase 1 on top of #401.

consume x no longer relies on an incidental compiler pattern equivalent to:

tmp = Load(x)
x = Nil

Ownership transfer is now explicit in the non-serialized compiler IR:

HIR  RValue::MoveOut(x)
  -> MIR RValue::MoveOut(x)

This makes "copy" and "transfer" distinct facts for later ownership/drop analysis without changing the frozen bytecode artifact format.

Backend semantics

Bytecode / VM

MoveOut(src) lowers using existing instructions:

  1. Move src, dst;
  2. load existing Nil constant into src.

No new opcode and no NBC format change.

WASM

The original source value is left on the operand stack for the destination assignment, then the source local is set to tagged Nil.

Native AOT

Cranelift uses the existing source SSA value as the result, then removes the source register from local_vals before binding the destination. AOT liveness also treats MoveOut as read-then-kill so pre-move values are not threaded through continuations.

CIR / inliner

MoveOut remains a distinct MIR operation through remapping; CIR reads the source value while static ownership analysis guarantees source unavailability afterwards.

Optimizer / drop planner

This avoids the unsafe shortcut of treating capability metadata alone as proof of runtime ownership.

Tests

  • HIR test verifies consume x produces MoveOut and no separate x = nil statement.
  • MIR test verifies MoveOut survives HIR→MIR.
  • Bytecode backend test verifies the moved value is preserved and the source register becomes Nil.
  • WASM backend has the same transfer/source-invalidation regression.
  • fix(ownership): separate must-use from maybe-moved flow #401 continues to reject source reads in normal language analysis.

Stack

#384 runtime consume semantics
  -> #385 parameter capability metadata
      -> #401 path-sensitive ownership flow
          -> this PR (#402 Phase 1)

Not included

  • no drop-token propagation;
  • no new droppable parameter classes;
  • no sink/call ABI;
  • no bytecode/NBC format change.

Keep draft until exact-head Rust, WASM, AOT/release, lint, and no-default-feature validation is terminal.

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Sep 18, 2026

Copy link
Copy Markdown

Deploying nulang-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: a46f70f
Status: ✅  Deploy successful!
Preview URL: https://5a106f44.nulang-docs.pages.dev
Branch Preview URL: https://feat-ownership-moveout-drop.nulang-docs.pages.dev

View logs

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant