Core-N0 Affine Unique P1V4 Contract
Status: implemented and validated
Architecture decision:
ADR-0016
Core profile: P1V4
1. Admitted owner
UniqueRef<T> = Ref<rho, Unique, T>
T = Bool | I64 | F64
RefAlloc<rho, Unique>(value) creates one direct affine owner of one fresh
opaque logical cell.
2. Affine rule
For every control-flow path:
moves(owner) <= 1
Dropping an owner is valid. Borrowing does not consume it. Borrowing or moving
an already-moved local is an OwnershipViolation.
3. Moves
The following consume a direct unique local:
let new_owner = use old_owner
call f(old_owner)
tailcall f(old_owner)
The destination binder or callee parameter becomes the sole owner. Arguments move left-to-right, so duplicate use in one argument vector fails deterministically.
4. Borrows
RefLoad(unique_owner)
RefStore(unique_owner, scalar)
borrow without consuming. Multiple sequential loads/stores are valid while the owner remains live.
There is no first-class borrow value, Read conversion, shared downgrade, or
loan escape in P1V4.
5. Function boundary
- entry parameters contain no references;
- internal direct parameters may be direct unique references;
- all function results contain no references;
- a unique direct call consumes the caller owner;
- a unique tail call transfers ownership in the same logical store;
- shared or aggregate reference tail transfer remains rejected.
6. Branches
If and Case clone the incoming affine state for mutually exclusive arms.
Each arm is checked independently. Core-N0 has no post-branch continuation or
implicit ownership join.
7. Rejected containment
Unique cannot occur recursively in:
- tuples or sums;
- arrays or logical-store cell values;
- closure captures or closure behavioral types;
- handler captures;
- operation signatures;
- function results or entry parameters.
This keeps the owner a direct local and prevents hidden duplication.
8. Runtime relation
- a move removes the unique source local from the interpreter environment;
- destination/callee receives the same opaque logical reference;
- load/store borrow the current owner;
- region close destroys all remaining cells regardless of normal return, typed error, unhandled operation, or budget failure;
- physical placement and host copying are unobservable.
9. Fail-closed boundary
P1V4 rejects:
Uniquein older profiles;- use-after-move by borrow or second move;
- duplicate owner arguments;
- aggregate, closure, or handler containment;
- entry/result escape;
- shared-reference tail transfer;
Readallocation or reference types;- unique logical-cell values and nested references;
- missing region or
State/Alloceffects.
10. Canonical encoding
Semantic encoding v1 uses:
profile P1V4 = 4
Mutability Unique = 1
No new type, rvalue, term, or effect tag is required. Existing profile vectors remain unchanged.
The locked P1V4 repeated-borrow vector is:
f314f6e72535bf12b6b42aa962a4a34c70845a7eefa709e7242b190b95fa27a9
11. Evidence required
- repeated unique load/store before move;
Usemove parity and source invalidation;- direct and tail-call ownership transfer;
- duplicate argument and use-after-move rejection;
- independent branch ownership states;
- aggregate, closure, handler, entry, result, and shared-tail negatives;
- alias-visible mutation without persistent alias creation;
- region/error/unhandled/budget cleanup behavior;
- deterministic semantic bytes/hash and tamper rejection;
- unchanged P1V0–P1V3 and T2 vectors;
- full workspace, strict lint, formatting, governance, shell, and link gates.
The executable corpus is
core_unique_p1v4.rs.
12. Non-claims
P1V4 is not general borrowing, partial moves, aggregate ownership, shared downgrade, escaping ownership, ownership-returning functions, unique closure capture, first-class affine continuations, physical placement, P1/P2, native lowering, or dependency closure.